diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 9bb29c683..c161aee17 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -224,6 +224,10 @@ type CheClusterSpecNetworking struct { // The secret must have a `app.kubernetes.io/part-of=che.eclipse.org` label. // +optional TlsSecretName string `json:"tlsSecretName,omitempty"` + // IngressClassName is the name of an IngressClass cluster resource. + // If a class name is defined in both the `IngressClassName` field and the `kubernetes.io/ingress.class` annotation, + // `IngressClassName` field takes precedence. + IngressClassName string `json:"ingressClassName,omitempty"` // Authentication settings. // +optional // +kubebuilder:default:={gateway: {configLabels: {app: che, component: che-gateway-config}}} diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index 2bb9f16dc..620a81bdf 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -7706,6 +7706,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 757cf6fe3..b6d210d55 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -7496,6 +7496,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index ca5b83ba1..f1015e886 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -7515,6 +7515,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 24b982df5..944ca1c92 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -7510,6 +7510,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 328b8474d..5912e314a 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -7515,6 +7515,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index c660b99a3..606766b24 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -7510,6 +7510,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 24b982df5..944ca1c92 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -7510,6 +7510,12 @@ spec: hostname: description: The public hostname of the installed Che server. type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. If a class name is defined in both the `IngressClassName` + field and the `kubernetes.io/ingress.class` annotation, `IngressClassName` + field takes precedence. + type: string labels: additionalProperties: type: string diff --git a/pkg/deploy/ingress.go b/pkg/deploy/ingress.go index 545ca8d29..4acab5532 100644 --- a/pkg/deploy/ingress.go +++ b/pkg/deploy/ingress.go @@ -15,6 +15,8 @@ import ( "reflect" "sort" + "k8s.io/utils/pointer" + "github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/common/test" @@ -124,6 +126,13 @@ func GetIngressSpec( } } + ingressClassName := deployContext.CheCluster.Spec.Networking.IngressClassName + if ingressClassName == "" { + ingressClassName = annotations["kubernetes.io/ingress.class"] + } + // annotations `kubernetes.io/ingress.class` can not be set when the class field is also set + delete(annotations, "kubernetes.io/ingress.class") + ingress := &networking.Ingress{ TypeMeta: metav1.TypeMeta{ Kind: "Ingress", @@ -136,6 +145,7 @@ func GetIngressSpec( Annotations: annotations, }, Spec: networking.IngressSpec{ + IngressClassName: pointer.String(ingressClassName), Rules: []networking.IngressRule{ { Host: host, diff --git a/pkg/deploy/ingress_test.go b/pkg/deploy/ingress_test.go index 6689f49e5..18421d4f0 100644 --- a/pkg/deploy/ingress_test.go +++ b/pkg/deploy/ingress_test.go @@ -31,20 +31,14 @@ import ( func TestIngressSpec(t *testing.T) { type testCase struct { - name string - ingressName string - ingressPath string - ingressComponent string - serviceName string - servicePort int - expectedIngress *networking.Ingress - cheCluster *chev2.CheCluster + name string + expectedIngress *networking.Ingress + cheCluster *chev2.CheCluster } testCases := []testCase{ { - name: "Test ingress", - ingressName: "test", + name: "Test case #1", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -52,16 +46,13 @@ func TestIngressSpec(t *testing.T) { }, Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ - Hostname: "test-host", - Labels: map[string]string{"type": "default"}, - Annotations: map[string]string{"annotation-key": "annotation-value"}, + Hostname: "test-host", + Labels: map[string]string{"type": "default"}, + Annotations: map[string]string{"annotation-key": "annotation-value"}, + IngressClassName: "nginx", }, }, }, - ingressPath: "", - ingressComponent: defaults.GetCheFlavor(), - serviceName: "che-host", - servicePort: 8080, expectedIngress: &networking.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -84,7 +75,73 @@ func TestIngressSpec(t *testing.T) { APIVersion: networking.SchemeGroupVersion.String(), }, Spec: networking.IngressSpec{ - TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, + IngressClassName: pointer.String("nginx"), + TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, + Rules: []networking.IngressRule{ + { + Host: "test-host", + IngressRuleValue: networking.IngressRuleValue{ + HTTP: &networking.HTTPIngressRuleValue{ + Paths: []networking.HTTPIngressPath{ + { + Backend: networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: "che-host", + Port: networking.ServiceBackendPort{ + Number: 8080, + }, + }, + }, + Path: "/", + PathType: (*networking.PathType)(pointer.StringPtr(string(networking.PathTypeImplementationSpecific))), + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "Test case #1", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + Hostname: "test-host", + Labels: map[string]string{"type": "default"}, + Annotations: map[string]string{"annotation-key": "annotation-value", "kubernetes.io/ingress.class": "nginx"}, + }, + }, + }, + expectedIngress: &networking.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "eclipse-che", + Labels: map[string]string{ + "type": "default", + "app.kubernetes.io/component": defaults.GetCheFlavor(), + "app.kubernetes.io/instance": defaults.GetCheFlavor(), + "app.kubernetes.io/part-of": "che.eclipse.org", + "app.kubernetes.io/managed-by": defaults.GetCheFlavor() + "-operator", + "app.kubernetes.io/name": defaults.GetCheFlavor(), + }, + Annotations: map[string]string{ + "che.eclipse.org/managed-annotations-digest": "0000", + "annotation-key": "annotation-value", + }, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Ingress", + APIVersion: networking.SchemeGroupVersion.String(), + }, + Spec: networking.IngressSpec{ + IngressClassName: pointer.String("nginx"), + TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, Rules: []networking.IngressRule{ { Host: "test-host", @@ -116,15 +173,13 @@ func TestIngressSpec(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{}) - _, actualIngress := GetIngressSpec(deployContext, - testCase.ingressName, - testCase.ingressPath, - testCase.serviceName, - testCase.servicePort, - testCase.ingressComponent, + "test", + "", + "che-host", + 8080, + defaults.GetCheFlavor(), ) - assert.Equal(t, testCase.expectedIngress, actualIngress) }) }