Repository: apache/camel-k
Pull request #3871 (2022-12-02 02:38:14)

fix(service): Create k8s service when knative-service trait is disabled
https://github.com/apache/camel-k/issues/3849

When knative-service and k8s service traits are enabled, the priority is to use knative-service in knative profile

**Release Note**
```release-note
NONE
```


christophd: uff, that confused me as well. I also added some review comments to the backport PR. Funnily enough the comments are quite the same as here 😄
claudio4j: > uff, that confused me as well. I also added some review comments to the backport PR. Funnily enough the comments are quite the same as here smile

Oh, that's not good, I did this in a hurry. Good reminder for next PR.

claudio4j: /retest


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ad2b3126..b4e2d8a39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,8 +6,6 @@
 
 **Closed issues:**
 
-- Recent testing failures [\#3861](https://github.com/apache/camel-k/issues/3861)
-- Update dependency versions in the documentation for 1.10.x and Next versions [\#3852](https://github.com/apache/camel-k/issues/3852)
 - Remove deprecated Kubernetes API [\#3840](https://github.com/apache/camel-k/issues/3840)
 - gc trait fails for: cannot list resource \"endpoints\" in API group \"submariner.io\" [\#3833](https://github.com/apache/camel-k/issues/3833)
 - Bundle m2 camel k runtime distribution [\#3826](https://github.com/apache/camel-k/issues/3826)
@@ -21,14 +19,12 @@
 - Remove code deprecated before 1.8 \(LTS\) [\#3787](https://github.com/apache/camel-k/issues/3787)
 - Native checks to run on a nightly basis instead of on each PR [\#3784](https://github.com/apache/camel-k/issues/3784)
 - Ready condition message not always taken from Camel Health Check [\#3761](https://github.com/apache/camel-k/issues/3761)
-- Unable to set env var OPERATOR\_ID in Helm installation [\#3739](https://github.com/apache/camel-k/issues/3739)
 - Camel version mismatch [\#3481](https://github.com/apache/camel-k/issues/3481)
 - Why's there JDK inside the camel-k-kit-\* images? [\#3424](https://github.com/apache/camel-k/issues/3424)
 - Drop support for Openshift 3 and related E2E test [\#3421](https://github.com/apache/camel-k/issues/3421)
 - Turn AWS region parameter into an enum? [\#3289](https://github.com/apache/camel-k/issues/3289)
 - Install Camel-K Operator based on Helm Chart with --global option [\#3054](https://github.com/apache/camel-k/issues/3054)
 - Camel 3.15 - Data formats renamed [\#2880](https://github.com/apache/camel-k/issues/2880)
-- Add official documentation on Kustomize introduced in 1.7 [\#2758](https://github.com/apache/camel-k/issues/2758)
 
 ## [1.10.4-nightly](https://github.com/apache/camel-k/tree/1.10.4-nightly) (2022-11-14)
 
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index c707ce281..3f3410ed0 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -43,12 +43,6 @@ func newServiceTrait() Trait {
 	}
 }
 
-// IsAllowedInProfile overrides default.
-func (t *serviceTrait) IsAllowedInProfile(profile v1.TraitProfile) bool {
-	return profile.Equal(v1.TraitProfileKubernetes) ||
-		profile.Equal(v1.TraitProfileOpenShift)
-}
-
 func (t *serviceTrait) Configure(e *Environment) (bool, error) {
 	if e.Integration == nil || !pointer.BoolDeref(t.Enabled, true) {
 		if e.Integration != nil {
@@ -63,6 +57,15 @@ func (t *serviceTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
+	// in case the knative-service and service trait are enabled, the knative-service has priority
+	// then this service is disabled
+	if e.GetTrait(knativeServiceTraitID) != nil {
+		knativeServiceTrait, _ := e.GetTrait(knativeServiceTraitID).(*knativeServiceTrait)
+		if pointer.BoolDeref(knativeServiceTrait.Enabled, true) {
+			return false, nil
+		}
+	}
+
 	if !e.IntegrationInRunningPhases() {
 		return false, nil
 	}


Test patch:
diff --git a/e2e/global/knative/files/http_out.groovy b/e2e/global/knative/files/http_out.groovy
new file mode 100644
index 000000000..40f75a639
--- /dev/null
+++ b/e2e/global/knative/files/http_out.groovy
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+from("rest:get:hello/")
+      .transform().simple("Hello");
\ No newline at end of file
diff --git a/e2e/global/knative/knative_test.go b/e2e/global/knative/knative_test.go
index fa9a9a2b4..a5931d687 100644
--- a/e2e/global/knative/knative_test.go
+++ b/e2e/global/knative/knative_test.go
@@ -107,6 +107,21 @@ func TestKnative(t *testing.T) {
 
 			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
 		})
+
+		t.Run("Knative-service disabled", func(t *testing.T) {
+			Expect(KamelRunWithID(operatorID, ns, "files/http_out.groovy", "-t", "knative-service.enabled=false").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, "http-out"), TestTimeoutLong).Should(Equal(v1.PodRunning))
+			Eventually(Service(ns, "http-out"), TestTimeoutShort).ShouldNot(BeNil())
+			Consistently(KnativeService(ns, "http-out"), TestTimeoutShort).Should(BeNil())
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+		})
+
+		t.Run("Knative-service priority", func(t *testing.T) {
+			Expect(KamelRunWithID(operatorID, ns, "files/http_out.groovy").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, "http-out"), TestTimeoutLong).Should(Equal(v1.PodRunning))
+			Eventually(KnativeService(ns, "http-out"), TestTimeoutShort).ShouldNot(BeNil())
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+		})
 	})
 }
 
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index 8b1cdfef0..ac2c59263 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -408,3 +408,209 @@ func TestServiceWithNodePort(t *testing.T) {
 
 	assert.Equal(t, corev1.ServiceTypeNodePort, s.Spec.Type)
 }
+
+// When service and knative-service are enabled at the integration scope in knative profile
+// knative-service has the priority and the k8s service is not run.
+func TestServiceWithKnativeServiceEnabled(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	assert.Nil(t, err)
+
+	traitCatalog := NewCatalog(nil)
+
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("netty-http:test").log("hello")`))
+	assert.NoError(t, err)
+
+	environment := Environment{
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      ServiceTestName,
+				Namespace: "ns",
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseDeploying,
+			},
+			Spec: v1.IntegrationSpec{
+				Profile: v1.TraitProfileKnative,
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:        "routes.js",
+							Content:     string(compressedRoute),
+							Compression: true,
+						},
+						Language: v1.LanguageJavaScript,
+					},
+				},
+				Traits: v1.Traits{
+					Service: &traitv1.ServiceTrait{
+						Trait: traitv1.Trait{
+							Enabled: pointer.Bool(true),
+						},
+						Auto: pointer.Bool(false),
+					},
+					KnativeService: &traitv1.KnativeServiceTrait{
+						Trait: traitv1.Trait{
+							Enabled: pointer.Bool(true),
+						},
+					},
+				},
+			},
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Cluster: v1.IntegrationPlatformClusterOpenShift,
+				Build: v1.IntegrationPlatformBuildSpec{
+					PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+					Registry:        v1.RegistrySpec{Address: "registry"},
+					RuntimeVersion:  catalog.Runtime.Version,
+				},
+			},
+			Status: v1.IntegrationPlatformStatus{
+				Phase: v1.IntegrationPlatformPhaseReady,
+			},
+		},
+		EnvVars:        make([]corev1.EnvVar, 0),
+		ExecutedTraits: make([]Trait, 0),
+		Resources:      kubernetes.NewCollection(),
+	}
+	environment.Platform.ResyncStatusFullConfig()
+
+	err = traitCatalog.apply(&environment)
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, environment.ExecutedTraits)
+	assert.Nil(t, environment.GetTrait(serviceTraitID))
+	assert.NotNil(t, environment.GetTrait(knativeServiceTraitID))
+}
+
+func TestServicesWithKnativeProfile(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	assert.Nil(t, err)
+
+	traitCatalog := NewCatalog(nil)
+
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("netty-http:test").log("hello")`))
+	assert.NoError(t, err)
+
+	environment := Environment{
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      ServiceTestName,
+				Namespace: "ns",
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseDeploying,
+			},
+			Spec: v1.IntegrationSpec{
+				Profile: v1.TraitProfileKnative,
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:        "routes.js",
+							Content:     string(compressedRoute),
+							Compression: true,
+						},
+						Language: v1.LanguageJavaScript,
+					},
+				},
+			},
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Cluster: v1.IntegrationPlatformClusterOpenShift,
+				Build: v1.IntegrationPlatformBuildSpec{
+					PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+					Registry:        v1.RegistrySpec{Address: "registry"},
+					RuntimeVersion:  catalog.Runtime.Version,
+				},
+			},
+			Status: v1.IntegrationPlatformStatus{
+				Phase: v1.IntegrationPlatformPhaseReady,
+			},
+		},
+		EnvVars:        make([]corev1.EnvVar, 0),
+		ExecutedTraits: make([]Trait, 0),
+		Resources:      kubernetes.NewCollection(),
+	}
+	environment.Platform.ResyncStatusFullConfig()
+
+	err = traitCatalog.apply(&environment)
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, environment.ExecutedTraits)
+	assert.Nil(t, environment.GetTrait(serviceTraitID))
+	assert.NotNil(t, environment.GetTrait(knativeServiceTraitID))
+}
+
+// When the knative-service is disabled at the IntegrationPlatform, the k8s service is enabled.
+func TestServiceWithKnativeServiceDisabledInIntegrationPlatform(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	assert.Nil(t, err)
+
+	traitCatalog := NewCatalog(nil)
+
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("netty-http:test").log("hello")`))
+	assert.NoError(t, err)
+
+	environment := Environment{
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      ServiceTestName,
+				Namespace: "ns",
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseDeploying,
+			},
+			Spec: v1.IntegrationSpec{
+				Profile: v1.TraitProfileKnative,
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:        "routes.js",
+							Content:     string(compressedRoute),
+							Compression: true,
+						},
+						Language: v1.LanguageJavaScript,
+					},
+				},
+			},
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Cluster: v1.IntegrationPlatformClusterOpenShift,
+				Build: v1.IntegrationPlatformBuildSpec{
+					PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+					Registry:        v1.RegistrySpec{Address: "registry"},
+					RuntimeVersion:  catalog.Runtime.Version,
+				},
+				Traits: v1.Traits{
+					KnativeService: &traitv1.KnativeServiceTrait{
+						Trait: traitv1.Trait{
+							Enabled: pointer.Bool(false),
+						},
+					},
+				},
+			},
+			Status: v1.IntegrationPlatformStatus{
+				Phase: v1.IntegrationPlatformPhaseReady,
+			},
+		},
+		EnvVars:        make([]corev1.EnvVar, 0),
+		ExecutedTraits: make([]Trait, 0),
+		Resources:      kubernetes.NewCollection(),
+	}
+	environment.Platform.ResyncStatusFullConfig()
+
+	err = traitCatalog.apply(&environment)
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, environment.ExecutedTraits)
+	assert.NotNil(t, environment.GetTrait(serviceTraitID))
+	assert.Nil(t, environment.GetTrait(knativeServiceTraitID))
+}