From 8d2f4f5bb48c84ceaaa45b058f38e4be5fbf53a9 Mon Sep 17 00:00:00 2001 From: cfitzw <20694057+cfitzw@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:43:43 -0600 Subject: [PATCH] add support for multiple ingress paths --- .../ROOT/partials/apis/camel-k-crds.adoc | 8 +++ helm/camel-k/crds/camel-k-crds.yaml | 70 +++++++++++++++---- pkg/apis/camel/v1/trait/ingress.go | 3 + ...camel.apache.org_integrationplatforms.yaml | 20 ++++-- .../camel.apache.org_integrationprofiles.yaml | 20 ++++-- .../bases/camel.apache.org_integrations.yaml | 20 ++++-- .../crd/bases/camel.apache.org_pipes.yaml | 10 ++- pkg/trait/ingress.go | 45 +++++++----- pkg/trait/ingress_test.go | 59 ++++++++++++++++ 9 files changed, 211 insertions(+), 44 deletions(-) diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc index c92a62aec0..f2fb39de66 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -7331,6 +7331,14 @@ string To configure the path exposed by the ingress (default `/`). +Deprecated: In favor of `paths` - left for backward compatibility. + +|`paths` + +[]string +| + + +To configure the paths exposed by the ingress (default `['/']`). |`pathType` + *https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#pathtype-v1-networking[Kubernetes networking/v1.PathType]* diff --git a/helm/camel-k/crds/camel-k-crds.yaml b/helm/camel-k/crds/camel-k-crds.yaml index f2dde79ccb..291a70d2d4 100644 --- a/helm/camel-k/crds/camel-k-crds.yaml +++ b/helm/camel-k/crds/camel-k-crds.yaml @@ -4467,9 +4467,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -6656,9 +6662,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -8748,9 +8760,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -10816,9 +10834,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -19265,9 +19289,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -21260,9 +21290,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -31089,6 +31125,16 @@ spec: description: To configure the path exposed by the ingress (default `/`). type: string + path: + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. + type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. diff --git a/pkg/apis/camel/v1/trait/ingress.go b/pkg/apis/camel/v1/trait/ingress.go index 7cd1653116..f8125bff13 100644 --- a/pkg/apis/camel/v1/trait/ingress.go +++ b/pkg/apis/camel/v1/trait/ingress.go @@ -38,6 +38,9 @@ type IngressTrait struct { Host string `property:"host" json:"host,omitempty"` // To configure the path exposed by the ingress (default `/`). Path string `property:"path" json:"path,omitempty"` + // To configure the paths exposed by the ingress (default `['/']`). + // Deprecated: In favor of `paths` - left for backward compatibility. + Paths []string `property:"paths" json:"paths,omitempty"` // To configure the path type exposed by the ingress. // One of `Exact`, `Prefix`, `ImplementationSpecific` (default to `Prefix`). // +kubebuilder:validation:Enum=Exact;Prefix;ImplementationSpecific diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml index fb199688e6..2de4164125 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml @@ -1237,9 +1237,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -3426,9 +3432,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml index 79425e7751..9d8107750c 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml @@ -1106,9 +1106,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -3174,9 +3180,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml index 2169dc54f7..3c2cfbc204 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml @@ -7466,9 +7466,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. @@ -9461,9 +9467,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml index 16d1270da6..9318b2c3c5 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml @@ -7531,9 +7531,15 @@ spec: See https://kubernetes.io/docs/concepts/services-networking/ingress/ type: string path: - description: To configure the path exposed by the ingress - (default `/`). + description: |- + To configure the path exposed by the ingress (default `/`). + Deprecated: In favor of `paths` - left for backward compatibility. type: string + paths: + description: To configure the paths exposed by the ingress (default `['/']`). + items: + type: string + type: array pathType: description: |- To configure the path type exposed by the ingress. diff --git a/pkg/trait/ingress.go b/pkg/trait/ingress.go index d78a6248e6..55f6408142 100644 --- a/pkg/trait/ingress.go +++ b/pkg/trait/ingress.go @@ -101,20 +101,7 @@ func (t *ingressTrait) Apply(e *Environment) error { Host: t.Host, IngressRuleValue: networkingv1.IngressRuleValue{ HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: t.getPath(), - PathType: t.getPathType(), - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: service.Name, - Port: networkingv1.ServiceBackendPort{ - Name: "http", - }, - }, - }, - }, - }, + Paths: t.getPaths(service), }, }, }, @@ -148,12 +135,34 @@ func (t *ingressTrait) Apply(e *Environment) error { return nil } -func (t *ingressTrait) getPath() string { - if t.Path == "" { - return defaultPath +func (t *ingressTrait) getPaths(service *corev1.Service) []networkingv1.HTTPIngressPath { + createIngressPath := func(path string) networkingv1.HTTPIngressPath { + return networkingv1.HTTPIngressPath{ + Path: path, + PathType: t.getPathType(), + Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: service.Name, + Port: networkingv1.ServiceBackendPort{ + Name: "http", + }, + }, + }, + } + } + + paths := []networkingv1.HTTPIngressPath{} + if t.Path == "" && len(t.Paths) == 0 { + paths = append(paths, createIngressPath(defaultPath)) + } else if t.Path != "" { + paths = append(paths, createIngressPath(t.Path)) + } else { + for _, p := range t.Paths { + paths = append(paths, createIngressPath(p)) + } } - return t.Path + return paths } func (t *ingressTrait) getPathType() *networkingv1.PathType { diff --git a/pkg/trait/ingress_test.go b/pkg/trait/ingress_test.go index 6635bd1249..d83f915bfe 100644 --- a/pkg/trait/ingress_test.go +++ b/pkg/trait/ingress_test.go @@ -129,6 +129,65 @@ func TestApplyIngressTraitDoesSucceed(t *testing.T) { assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) } +func TestApplyIngressTraitWithPathDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.Path = string("/path") + + err := ingressTrait.Apply(environment) + + require.NoError(t, err) + assert.Len(t, environment.Integration.Status.Conditions, 1) + + assert.Len(t, environment.Resources.Items(), 2) + environment.Resources.Visit(func(resource runtime.Object) { + if ingress, ok := resource.(*networkingv1.Ingress); ok { + assert.Equal(t, "service-name", ingress.Name) + assert.Equal(t, "namespace", ingress.Namespace) + assert.Len(t, ingress.Spec.Rules, 1) + assert.Equal(t, "hostname", ingress.Spec.Rules[0].Host) + assert.Len(t, ingress.Spec.Rules[0].HTTP.Paths, 1) + assert.Equal(t, "/path", ingress.Spec.Rules[0].HTTP.Paths[0].Path) + assert.Equal(t, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) + assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + } + }) + + conditions := environment.Integration.Status.Conditions + assert.Len(t, conditions, 1) + assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) +} + +func TestApplyIngressTraitWithPathsDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.Paths = []string{"/path-a", "/path-b"} + + err := ingressTrait.Apply(environment) + + require.NoError(t, err) + assert.Len(t, environment.Integration.Status.Conditions, 1) + + assert.Len(t, environment.Resources.Items(), 2) + environment.Resources.Visit(func(resource runtime.Object) { + if ingress, ok := resource.(*networkingv1.Ingress); ok { + assert.Equal(t, "service-name", ingress.Name) + assert.Equal(t, "namespace", ingress.Namespace) + assert.Len(t, ingress.Spec.Rules, 1) + assert.Equal(t, "hostname", ingress.Spec.Rules[0].Host) + assert.Len(t, ingress.Spec.Rules[0].HTTP.Paths, 2) + assert.Equal(t, "/path-a", ingress.Spec.Rules[0].HTTP.Paths[0].Path) + assert.Equal(t, "/path-b", ingress.Spec.Rules[0].HTTP.Paths[1].Path) + assert.Equal(t, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) + assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + } + }) + + conditions := environment.Integration.Status.Conditions + assert.Len(t, conditions, 1) + assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) +} + func TestApplyIngressTraitWithIngressClassNameDoesSucceed(t *testing.T) { ingressTrait, environment := createNominalIngressTestWithIngressClassName("someIngressClass")