This is an automated email from the ASF dual-hosted git repository. pcongiusti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/main by this push: new 15a4efe4f feat(trait): add support for multiple ingress paths (#5996) 15a4efe4f is described below commit 15a4efe4f51852ff85e6128cc51aa92cc642205b Author: cfitzw <20694057+cfi...@users.noreply.github.com> AuthorDate: Wed Jan 8 01:25:26 2025 -0600 feat(trait): add support for multiple ingress paths (#5996) * add support for multiple ingress paths * allow path related ingress fields to co-exist * add a depreciation warning for ingress.path * ensure depreciation warning shows in operator log * add test for the new depreciation condition --- docs/modules/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 ++++-- .../crd/bases/camel.apache.org_integrations.yaml | 20 ++++-- .../config/crd/bases/camel.apache.org_pipes.yaml | 10 ++- pkg/trait/ingress.go | 62 +++++++++++----- pkg/trait/ingress_test.go | 83 ++++++++++++++++++++++ 9 files changed, 252 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 8cb076f6d..fc8d35920 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -7338,6 +7338,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 42a7f1da5..b37446cc7 100644 --- a/helm/camel-k/crds/camel-k-crds.yaml +++ b/helm/camel-k/crds/camel-k-crds.yaml @@ -4481,9 +4481,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. @@ -6677,9 +6683,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. @@ -8776,9 +8788,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. @@ -10851,9 +10869,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. @@ -19307,9 +19331,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. @@ -21309,9 +21339,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. @@ -31145,6 +31181,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 7cd165311..f8125bff1 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 a5c62d97a..2bdb23de4 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml @@ -1244,9 +1244,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. @@ -3440,9 +3446,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 84efe5230..edfe4bd9a 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml @@ -1113,9 +1113,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. @@ -3188,9 +3194,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 5baf4779a..0173b74ab 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml @@ -7473,9 +7473,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. @@ -9475,9 +9481,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 e71202e95..3ec1009b6 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml @@ -7538,9 +7538,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 d78a6248e..1605377b5 100644 --- a/pkg/trait/ingress.go +++ b/pkg/trait/ingress.go @@ -57,9 +57,11 @@ func (t *ingressTrait) Configure(e *Environment) (bool, *TraitCondition, error) if e.Integration == nil { return false, nil, nil } + if !e.IntegrationInRunningPhases() { return false, nil, nil } + if !ptr.Deref(t.Enabled, true) { return false, NewIntegrationCondition( "Ingress", @@ -76,6 +78,20 @@ func (t *ingressTrait) Configure(e *Environment) (bool, *TraitCondition, error) } } + if t.Path != "" { + m := "The path parameter is deprecated and may be removed in a future release. Use the paths parameter instead." + t.L.Info(m) + condition := NewIntegrationCondition( + "Ingress", + v1.IntegrationConditionTraitInfo, + corev1.ConditionTrue, + TraitConfigurationReason, + m, + ) + + return true, condition, nil + } + return true, nil, nil } @@ -101,20 +117,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 +151,35 @@ 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)) + } + 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 6635bd124..763cfcbd9 100644 --- a/pkg/trait/ingress_test.go +++ b/pkg/trait/ingress_test.go @@ -129,6 +129,89 @@ 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) + + // ensure a condition exists with the depreciation notice + enabled, condition, err := ingressTrait.Configure(environment) + require.NoError(t, err) + assert.True(t, enabled) + assert.NotNil(t, condition) + assert.Equal(t, "The path parameter is deprecated and may be removed in a future release. Use the paths parameter instead.", + condition.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 TestApplyIngressTraitWithPathAndPathsDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.Path = string("/path") + ingressTrait.Paths = []string{"/path-a", "/path-b"} + + err := ingressTrait.Apply(environment) + + require.NoError(t, err) + environment.Resources.Visit(func(resource runtime.Object) { + if ingress, ok := resource.(*networkingv1.Ingress); ok { + assert.Len(t, ingress.Spec.Rules[0].HTTP.Paths, 3) + } + }) +} + func TestApplyIngressTraitWithIngressClassNameDoesSucceed(t *testing.T) { ingressTrait, environment := createNominalIngressTestWithIngressClassName("someIngressClass")