Skip to content

Commit

Permalink
add ingressClassName in ingress spec (#48)
Browse files Browse the repository at this point in the history
* add ingressClassName in ingress spec

* make ingress.spec.ingressClassName optional
  • Loading branch information
reginaldosousa authored Oct 18, 2024
1 parent 92378b1 commit 714a1c2
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 34 deletions.
3 changes: 3 additions & 0 deletions cmd/router/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ func main() {

ingressClass := flag.String("ingress-class", "", "Default class used for ingress objects")

useIngressClassName := flag.Bool("use-ingress-class-name", false, "If true, the ingress.spec.ingressClassName will be used instead of the ingress.class annotation")

ingressAnnotationsPrefix := flag.String("ingress-annotations-prefix", "", "Default prefix for annotations based on options")

poolLabels := &cmd.MultiMapFlag{}
Expand Down Expand Up @@ -103,6 +105,7 @@ func main() {
IngressClass: *ingressClass,
AnnotationsPrefix: *ingressAnnotationsPrefix,
HTTPPort: *ingressPort,
UseIngressClassName: *useIngressClassName,
}
case "service", "loadbalancer":
localBackend.Routers[mode] = &kubernetes.LBService{
Expand Down
17 changes: 13 additions & 4 deletions kubernetes/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ type IngressService struct {
AnnotationsPrefix string
// IngressClass defines the default ingress class used by the controller
IngressClass string
UseIngressClassName bool
HTTPPort int
OptsAsAnnotations map[string]string
OptsAsAnnotationsDocs map[string]string
Expand Down Expand Up @@ -189,7 +190,7 @@ func (k *IngressService) Ensure(ctx context.Context, id router.InstanceID, o rou
}),
},
},
Spec: buildIngressSpec(vhosts, o.Opts.Route, backendServices),
Spec: buildIngressSpec(vhosts, o.Opts.Route, backendServices, k),
}
k.fillIngressMeta(ingress, o.Opts, id, o.Team)
if o.Opts.Acme {
Expand Down Expand Up @@ -272,7 +273,7 @@ func (k *IngressService) mergeIngresses(ctx context.Context, ingress *networking
return nil
}

func buildIngressSpec(hosts map[string]string, path string, services map[string]*v1.Service) networkingV1.IngressSpec {
func buildIngressSpec(hosts map[string]string, path string, services map[string]*v1.Service, k *IngressService) networkingV1.IngressSpec {
pathType := networkingV1.PathTypeImplementationSpecific
rules := []networkingV1.IngressRule{}
for k, service := range services {
Expand Down Expand Up @@ -301,6 +302,14 @@ func buildIngressSpec(hosts map[string]string, path string, services map[string]
rules = append(rules, r)
}

if k.IngressClass != "" && k.UseIngressClassName {
className := k.IngressClass
return networkingV1.IngressSpec{
IngressClassName: &className,
Rules: rules,
}
}

return networkingV1.IngressSpec{
Rules: rules,
}
Expand Down Expand Up @@ -365,7 +374,7 @@ func (k *IngressService) ensureCNameBackend(ctx context.Context, opts ensureCNam
}),
},
},
Spec: buildIngressSpec(map[string]string{"ensureCnameBackend": opts.cname}, opts.routerOpts.Route, map[string]*v1.Service{"ensureCnameBackend": opts.service}),
Spec: buildIngressSpec(map[string]string{"ensureCnameBackend": opts.cname}, opts.routerOpts.Route, map[string]*v1.Service{"ensureCnameBackend": opts.service}, k),
}

k.fillIngressMeta(ingress, opts.routerOpts, opts.id, opts.team)
Expand Down Expand Up @@ -783,7 +792,7 @@ func (s *IngressService) fillIngressMeta(i *networkingV1.Ingress, routerOpts rou
i.ObjectMeta.Labels[teamLabel] = team

additionalOpts := routerOpts.AdditionalOpts
if s.IngressClass != "" {
if s.IngressClass != "" && !s.UseIngressClassName {
additionalOpts = mergeMaps(routerOpts.AdditionalOpts, map[string]string{
defaultClassOpt: s.IngressClass,
})
Expand Down
94 changes: 64 additions & 30 deletions kubernetes/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ import (
ktesting "k8s.io/client-go/testing"
)

func createFakeService() IngressService {
func createFakeService(useIngressClassName bool) IngressService {
client := fake.NewSimpleClientset()
err := createAppWebService(client, "default", "test")
if err != nil {
panic(err)
}

return IngressService{
DomainSuffix: "mycloud.com",
UseIngressClassName: useIngressClassName,
DomainSuffix: "mycloud.com",
BaseService: &BaseService{
Namespace: "default",
Client: client,
Expand Down Expand Up @@ -101,7 +102,7 @@ func createCertManagerClusterIssuer(client certmanagerv1clientset.Interface, nam
}

func TestSecretName(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
appName := "tsuru-dashboard"
certName := "bigerdomain1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.cloud.evenbiiiiiiiiigerrrrr.com"
sName := svc.secretName(idForApp(appName), certName)
Expand All @@ -110,15 +111,15 @@ func TestSecretName(t *testing.T) {
certName = "domain.com"
sName = svc.secretName(idForApp(appName), certName)
assert.Equal(t, "kr-tsuru-dashboard-domain.com", sName)
svc2 := createFakeService()
svc2 := createFakeService(false)
appName = "tsuru-dashboard"
certName = "domain.com"
sName = svc2.secretName(router.InstanceID{AppName: appName, InstanceName: "custom1"}, certName)
assert.Equal(t, "kr-tsuru-dashboard-domain.com-custom1", sName)
}

func TestIngressEnsure(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -357,7 +358,7 @@ func TestIngressEnsureWithMultipleBackendsWithTLS(t *testing.T) {
}

func TestIngressEnsureWithCNames(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -526,7 +527,7 @@ func TestIngressEnsureWithCNames(t *testing.T) {
}

func TestEnsureCertManagerIssuer(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)

createCertManagerIssuer(svc.CertManagerClient, svc.Namespace, "letsencrypt")
createCertManagerClusterIssuer(svc.CertManagerClient, "letsencrypt-cluster")
Expand Down Expand Up @@ -568,7 +569,7 @@ func TestEnsureCertManagerIssuer(t *testing.T) {
}

func TestEnsureCertManagerIssuerNotFound(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -597,7 +598,7 @@ func TestEnsureCertManagerIssuerNotFound(t *testing.T) {
}

func TestIngressCreateDefaultClass(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
svc.IngressClass = "nginx"
Expand Down Expand Up @@ -633,7 +634,7 @@ func TestIngressCreateDefaultClass(t *testing.T) {
}

func TestIngressEnsureDefaultClassOverride(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
svc.IngressClass = "nginx"
Expand Down Expand Up @@ -667,8 +668,41 @@ func TestIngressEnsureDefaultClassOverride(t *testing.T) {
assert.Equal(t, expectedIngress, foundIngress)
}

func TestIngressEnsureIngressClassName(t *testing.T) {
svc := createFakeService(true)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
svc.IngressClass = "nginx"
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Team: "default",
Prefixes: []router.BackendPrefix{
{
Target: router.BackendTarget{
Service: "test-web",
Namespace: "default",
},
},
},
})
require.NoError(t, err)
foundIngress, err := svc.Client.NetworkingV1().Ingresses(svc.Namespace).Get(ctx, "kubernetes-router-test-ingress", metav1.GetOptions{})
require.NoError(t, err)

expectedIngress := defaultIngress("test", "default")
expectedIngress.Labels["controller"] = "my-controller"
expectedIngress.Labels["XPTO"] = "true"
expectedIngress.Labels["tsuru.io/app-name"] = "test"
expectedIngress.Labels["tsuru.io/app-team"] = "default"
expectedIngress.Annotations["ann1"] = "val1"
expectedIngress.Annotations["ann2"] = "val2"

expectedIngress.Spec.IngressClassName = &svc.IngressClass

assert.Equal(t, expectedIngress, foundIngress)
}

func TestIngressEnsureDefaultPrefix(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
svc.AnnotationsPrefix = "my.prefix.com"
Expand Down Expand Up @@ -708,7 +742,7 @@ func TestIngressEnsureDefaultPrefix(t *testing.T) {
}

func TestIngressEnsureRemoveAnnotation(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -743,7 +777,7 @@ func TestIngressEnsureRemoveAnnotation(t *testing.T) {
}

func TestIngressCreateDefaultPort(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createCRD(svc.BaseService, "myapp", "custom-namespace", nil)
require.NoError(t, err)
err = createAppWebService(svc.Client, svc.Namespace, "myapp")
Expand Down Expand Up @@ -778,7 +812,7 @@ func TestIngressCreateDefaultPort(t *testing.T) {
}

func TestEnsureExistingIngress(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svcName := "test"
svcPort := 8000
resourceVersion := "123"
Expand Down Expand Up @@ -836,7 +870,7 @@ func TestEnsureExistingIngress(t *testing.T) {
}

func TestEnsureExistingIngressWithFreeze(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svcName := "test"
svcPort := 8000
resourceVersion := "123"
Expand Down Expand Up @@ -893,7 +927,7 @@ func TestEnsureExistingIngressWithFreeze(t *testing.T) {
}

func TestEnsureIngressAppNamespace(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createCRD(svc.BaseService, "app", "custom-namespace", nil)
require.NoError(t, err)
err = createAppWebService(svc.Client, svc.Namespace, "app")
Expand All @@ -919,7 +953,7 @@ func TestEnsureIngressAppNamespace(t *testing.T) {
}

func TestIngressGetAddress(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.DomainSuffix = "apps.example.org"
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
Expand All @@ -940,7 +974,7 @@ func TestIngressGetAddress(t *testing.T) {
assert.Equal(t, []string{"test.apps.example.org"}, addrs)
}
func TestIngressGetAddressWithPort(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.HTTPPort = 8888
svc.DomainSuffix = "apps.example.org"
Expand All @@ -963,7 +997,7 @@ func TestIngressGetAddressWithPort(t *testing.T) {
assert.Equal(t, []string{"test.apps.example.org:8888"}, addrs)
}
func TestIngressGetAddressWithPortTLS(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.DomainSuffix = "" // cleaning the precedence of domainSuffix
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.HTTPPort = 8888
Expand All @@ -989,7 +1023,7 @@ func TestIngressGetAddressWithPortTLS(t *testing.T) {
assert.Equal(t, []string{"https://test.apps.example.org"}, addrs)
}
func TestIngressGetAddressTLS(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
svc.DomainSuffix = "" // cleaning the precedence of domainSuffix
svc.Labels = map[string]string{"controller": "my-controller", "XPTO": "true"}
svc.Annotations = map[string]string{"ann1": "val1", "ann2": "val2"}
Expand Down Expand Up @@ -1096,7 +1130,7 @@ func TestRemove(t *testing.T) {
for _, tc := range tt {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)

err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Prefixes: []router.BackendPrefix{
Expand All @@ -1122,7 +1156,7 @@ func TestRemove(t *testing.T) {
}

func TestRemoveCertificate(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand All @@ -1144,7 +1178,7 @@ func TestRemoveCertificate(t *testing.T) {
}

func TestRemoveCertificateACMEHandled(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand All @@ -1166,7 +1200,7 @@ func TestRemoveCertificateACMEHandled(t *testing.T) {
}

func TestAddCertificate(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -1213,7 +1247,7 @@ func TestAddCertificate(t *testing.T) {
}

func TestAddCertificateACMEHandled(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand All @@ -1237,7 +1271,7 @@ func TestAddCertificateACMEHandled(t *testing.T) {
}

func TestAddCertificateWithOverride(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -1280,7 +1314,7 @@ func TestAddCertificateWithOverride(t *testing.T) {
}

func TestAddCertificateWithCName(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -1341,7 +1375,7 @@ func TestAddCertificateWithCName(t *testing.T) {
}

func TestGetCertificate(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := createAppWebService(svc.Client, svc.Namespace, "test-blue")
require.NoError(t, err)
err = svc.Ensure(ctx, idForApp("test-blue"), router.EnsureBackendOpts{
Expand Down Expand Up @@ -1378,7 +1412,7 @@ func TestGetCertificate(t *testing.T) {
}

func TestEnsureWithTLSAndCName(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Opts: router.Opts{
Acme: true,
Expand Down Expand Up @@ -1429,7 +1463,7 @@ func TestEnsureWithTLSAndCName(t *testing.T) {
}

func TestEnsureWithTLSAndCNameAndAcmeCName(t *testing.T) {
svc := createFakeService()
svc := createFakeService(false)
err := svc.Ensure(ctx, idForApp("test"), router.EnsureBackendOpts{
Opts: router.Opts{
Acme: true,
Expand Down

0 comments on commit 714a1c2

Please sign in to comment.