diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc index 89c648300b..2dd82a59f9 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -7228,6 +7228,20 @@ bool To automatically add an ingress whenever the integration uses an HTTP endpoint consumer. +|`tlsHosts` + +[]string +| + + +To configure tls hosts + +|`tlsSecretName` + +string +| + + +To configure tls secret name + |=== diff --git a/docs/modules/traits/pages/ingress.adoc b/docs/modules/traits/pages/ingress.adoc index bf26cee14c..8ed29dff9c 100755 --- a/docs/modules/traits/pages/ingress.adoc +++ b/docs/modules/traits/pages/ingress.adoc @@ -53,6 +53,14 @@ One of `Exact`, `Prefix`, `ImplementationSpecific` (default to `Prefix`). | bool | To automatically add an ingress whenever the integration uses an HTTP endpoint consumer. +| ingress.tls-hosts +| []string +| To configure tls hosts + +| ingress.tls-secret-name +| string +| To configure tls secret name + |=== // End of autogenerated code - DO NOT EDIT! (configuration) diff --git a/helm/camel-k/crds/crd-integration-platform.yaml b/helm/camel-k/crds/crd-integration-platform.yaml index 3107e80cbd..9bc5fb4702 100644 --- a/helm/camel-k/crds/crd-integration-platform.yaml +++ b/helm/camel-k/crds/crd-integration-platform.yaml @@ -1166,6 +1166,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait @@ -3180,6 +3188,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/helm/camel-k/crds/crd-integration-profile.yaml b/helm/camel-k/crds/crd-integration-profile.yaml index 2c24920a10..a5f9689e59 100644 --- a/helm/camel-k/crds/crd-integration-profile.yaml +++ b/helm/camel-k/crds/crd-integration-profile.yaml @@ -1043,6 +1043,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait @@ -2940,6 +2948,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/helm/camel-k/crds/crd-integration.yaml b/helm/camel-k/crds/crd-integration.yaml index 26fe736411..41ef39a36a 100644 --- a/helm/camel-k/crds/crd-integration.yaml +++ b/helm/camel-k/crds/crd-integration.yaml @@ -7107,6 +7107,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml index 202a701edc..9f420d5280 100644 --- a/helm/camel-k/crds/crd-kamelet-binding.yaml +++ b/helm/camel-k/crds/crd-kamelet-binding.yaml @@ -7391,6 +7391,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/helm/camel-k/crds/crd-pipe.yaml b/helm/camel-k/crds/crd-pipe.yaml index c2648f8c8b..89703a6cc0 100644 --- a/helm/camel-k/crds/crd-pipe.yaml +++ b/helm/camel-k/crds/crd-pipe.yaml @@ -7389,6 +7389,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/pkg/apis/camel/v1/trait/ingress.go b/pkg/apis/camel/v1/trait/ingress.go index 128b36f028..a211ae4b62 100644 --- a/pkg/apis/camel/v1/trait/ingress.go +++ b/pkg/apis/camel/v1/trait/ingress.go @@ -41,4 +41,8 @@ type IngressTrait struct { PathType *networkingv1.PathType `property:"path-type" json:"pathType,omitempty"` // To automatically add an ingress whenever the integration uses an HTTP endpoint consumer. Auto *bool `property:"auto" json:"auto,omitempty"` + // To configure tls hosts + TLSHosts []string `property:"tls-hosts" json:"tlsHosts,omitempty"` + // To configure tls secret name + TLSSecretName string `property:"tls-secret-name" json:"tlsSecretName,omitempty"` } diff --git a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go index a8db3093a2..c428ad5dfd 100644 --- a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go @@ -453,6 +453,11 @@ func (in *IngressTrait) DeepCopyInto(out *IngressTrait) { *out = new(bool) **out = **in } + if in.TLSHosts != nil { + in, out := &in.TLSHosts, &out.TLSHosts + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressTrait. 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 3107e80cbd..9bc5fb4702 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml @@ -1166,6 +1166,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait @@ -3180,6 +3188,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait 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 2c24920a10..a5f9689e59 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml @@ -1043,6 +1043,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait @@ -2940,6 +2948,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait 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 26fe736411..41ef39a36a 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml @@ -7107,6 +7107,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/pkg/resources/config/crd/bases/camel.apache.org_kameletbindings.yaml b/pkg/resources/config/crd/bases/camel.apache.org_kameletbindings.yaml index 202a701edc..9f420d5280 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_kameletbindings.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_kameletbindings.yaml @@ -7391,6 +7391,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait 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 c2648f8c8b..89703a6cc0 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml @@ -7389,6 +7389,14 @@ spec: - Prefix - ImplementationSpecific type: string + tlsHosts: + description: To configure tls hosts + items: + type: string + type: array + tlsSecretName: + description: To configure tls secret name + type: string type: object istio: description: The configuration of Istio trait diff --git a/pkg/trait/ingress.go b/pkg/trait/ingress.go index 6c0fee9629..2777847087 100644 --- a/pkg/trait/ingress.go +++ b/pkg/trait/ingress.go @@ -21,13 +21,12 @@ import ( "errors" "fmt" + v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" + traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait" ) const ( @@ -44,10 +43,12 @@ func newIngressTrait() Trait { return &ingressTrait{ BaseTrait: NewBaseTrait(ingressTraitID, ingressTraitOrder), IngressTrait: traitv1.IngressTrait{ - Annotations: map[string]string{}, - Host: "", - Path: "/", - PathType: ptrFrom(networkingv1.PathTypePrefix), + Annotations: map[string]string{}, + Host: "", + Path: "/", + PathType: ptrFrom(networkingv1.PathTypePrefix), + TLSHosts: []string{}, + TLSSecretName: "", }, } } @@ -126,6 +127,15 @@ func (t *ingressTrait) Apply(e *Environment) error { }, } + if len(t.TLSHosts) > 0 && t.TLSSecretName != "" { + ingress.Spec.TLS = []networkingv1.IngressTLS{ + { + Hosts: t.TLSHosts, + SecretName: t.TLSSecretName, + }, + } + } + e.Resources.Add(&ingress) message := fmt.Sprintf("%s(%s) -> %s(%s)", ingress.Name, t.Host, service.Name, "http") diff --git a/pkg/trait/ingress_test.go b/pkg/trait/ingress_test.go index 29e9ddc94b..79249b2a66 100644 --- a/pkg/trait/ingress_test.go +++ b/pkg/trait/ingress_test.go @@ -118,6 +118,7 @@ func TestApplyIngressTraitDoesSucceed(t *testing.T) { assert.Equal(t, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) assert.Equal(t, "/", ingress.Spec.Rules[0].HTTP.Paths[0].Path) assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Nil(t, ingress.Spec.TLS) assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) } }) @@ -127,6 +128,99 @@ func TestApplyIngressTraitDoesSucceed(t *testing.T) { assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) } +func TestConfigureTLSIngressTraitWDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.TLSHosts = []string{"host1.com", "host2.com"} + ingressTrait.TLSSecretName = "nginxWildcard" + + 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, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) + assert.Equal(t, "/", ingress.Spec.Rules[0].HTTP.Paths[0].Path) + assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, "host1.com", ingress.Spec.TLS[0].Hosts[0]) + assert.Equal(t, "host2.com", ingress.Spec.TLS[0].Hosts[1]) + assert.Equal(t, "nginxWildcard", ingress.Spec.TLS[0].SecretName) + } + }) + + conditions := environment.Integration.Status.Conditions + assert.Len(t, conditions, 1) + assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) +} + +func TestConfigureTLSWithoutHostsIngressTraitWDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.TLSSecretName = "nginxWildcard" + + 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, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) + assert.Equal(t, "/", ingress.Spec.Rules[0].HTTP.Paths[0].Path) + assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Nil(t, ingress.Spec.TLS) + } + }) + + conditions := environment.Integration.Status.Conditions + assert.Len(t, conditions, 1) + assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) +} + +func TestConfigureTLSWithoutSecretNameIngressTraitWDoesSucceed(t *testing.T) { + ingressTrait, environment := createNominalIngressTest() + ingressTrait.TLSHosts = []string{"host1.com", "host2.com"} + + 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, "service-name", ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name) + assert.Equal(t, "/", ingress.Spec.Rules[0].HTTP.Paths[0].Path) + assert.NotNil(t, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Equal(t, networkingv1.PathTypePrefix, *ingress.Spec.Rules[0].HTTP.Paths[0].PathType) + assert.Nil(t, ingress.Spec.TLS) + } + }) + + conditions := environment.Integration.Status.Conditions + assert.Len(t, conditions, 1) + assert.Equal(t, "service-name(hostname) -> service-name(http)", conditions[0].Message) +} + func createNominalIngressTest() (*ingressTrait, *Environment) { trait, _ := newIngressTrait().(*ingressTrait) trait.Enabled = pointer.Bool(true)