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")
 

Reply via email to