Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ingressClassName in ingress spec #48

Merged
merged 2 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading