You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2024/03/27 14:16:28 UTC

(camel-k) branch main updated: fix(knative): enable service container port

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 58c4fdac8 fix(knative): enable service container port
58c4fdac8 is described below

commit 58c4fdac889eaccb938aa4b26b24116842d37ed6
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Mar 27 10:57:17 2024 +0100

    fix(knative): enable service container port
    
    The container port was skipped in case of a Knative service, as the Service resource is missing in such case.
---
 pkg/trait/container.go      | 100 +++++++++++++++-------------------
 pkg/trait/container_test.go | 127 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 169 insertions(+), 58 deletions(-)

diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index b58842df1..7d32a06d6 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -176,57 +176,36 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 	if e.ApplicationProperties == nil {
 		e.ApplicationProperties = make(map[string]string)
 	}
-
 	container := corev1.Container{
 		Name:  t.Name,
 		Image: e.Integration.Status.Image,
 		Env:   make([]corev1.EnvVar, 0),
 	}
-
 	if t.ImagePullPolicy != "" {
 		container.ImagePullPolicy = t.ImagePullPolicy
 	}
-
 	// combine Environment of integration with platform, kit, integration
 	for _, env := range e.collectConfigurationPairs("env") {
 		envvar.SetVal(&container.Env, env.Name, env.Value)
 	}
-
 	envvar.SetVal(&container.Env, digest.IntegrationDigestEnvVar, e.Integration.Status.Digest)
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF", filepath.Join(camel.BasePath, "application.properties"))
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", camel.ConfDPath)
 
-	e.addSourcesProperties()
-	if props, err := e.computeApplicationProperties(); err != nil {
-		return err
-	} else if props != nil {
-		e.Resources.Add(props)
-	}
-
-	t.configureResources(&container)
-	if pointer.BoolDeref(t.Expose, false) {
-		t.configureService(e, &container)
-	}
-	t.configureCapabilities(e)
-
-	t.configureSecurityContext(e, &container)
-
 	var containers *[]corev1.Container
 	visited := false
-
+	knative := false
 	// Deployment
 	if err := e.Resources.VisitDeploymentE(func(deployment *appsv1.Deployment) error {
 		for _, envVar := range e.EnvVars {
 			envvar.SetVar(&container.Env, envVar)
 		}
-
 		containers = &deployment.Spec.Template.Spec.Containers
 		visited = true
 		return nil
 	}); err != nil {
 		return err
 	}
-
 	// Knative Service
 	if err := e.Resources.VisitKnativeServiceE(func(service *serving.Service) error {
 		for _, env := range e.EnvVars {
@@ -236,34 +215,43 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 			case env.ValueFrom.FieldRef != nil && env.ValueFrom.FieldRef.FieldPath == "metadata.namespace":
 				envvar.SetVar(&container.Env, corev1.EnvVar{Name: env.Name, Value: e.Integration.Namespace})
 			case env.ValueFrom.FieldRef != nil:
-				t.L.Infof("Skipping environment variable %s (fieldRef)", env.Name)
+				t.L.Debugf("Skipping environment variable %s (fieldRef)", env.Name)
 			case env.ValueFrom.ResourceFieldRef != nil:
-				t.L.Infof("Skipping environment variable %s (resourceFieldRef)", env.Name)
+				t.L.Debugf("Skipping environment variable %s (resourceFieldRef)", env.Name)
 			default:
 				envvar.SetVar(&container.Env, env)
 			}
 		}
-
 		containers = &service.Spec.ConfigurationSpec.Template.Spec.Containers
 		visited = true
+		knative = true
 		return nil
 	}); err != nil {
 		return err
 	}
-
 	// CronJob
 	if err := e.Resources.VisitCronJobE(func(cron *batchv1.CronJob) error {
 		for _, envVar := range e.EnvVars {
 			envvar.SetVar(&container.Env, envVar)
 		}
-
 		containers = &cron.Spec.JobTemplate.Spec.Template.Spec.Containers
 		visited = true
 		return nil
 	}); err != nil {
 		return err
 	}
-
+	e.addSourcesProperties()
+	if props, err := e.computeApplicationProperties(); err != nil {
+		return err
+	} else if props != nil {
+		e.Resources.Add(props)
+	}
+	t.configureResources(&container)
+	if knative || pointer.BoolDeref(t.Expose, false) {
+		t.configureService(e, &container, knative)
+	}
+	t.configureCapabilities(e)
+	t.configureSecurityContext(e, &container)
 	if visited {
 		*containers = append(*containers, container)
 	}
@@ -271,46 +259,42 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 	return nil
 }
 
-func (t *containerTrait) configureService(e *Environment, container *corev1.Container) {
-	service := e.Resources.GetServiceForIntegration(e.Integration)
-	if service == nil {
-		return
-	}
-
+func (t *containerTrait) configureService(e *Environment, container *corev1.Container, isKnative bool) {
 	name := t.PortName
 	if name == "" {
 		name = defaultContainerPortName
 	}
-
 	containerPort := corev1.ContainerPort{
-		Name:          name,
 		ContainerPort: int32(t.Port),
 		Protocol:      corev1.ProtocolTCP,
 	}
-
-	servicePort := corev1.ServicePort{
-		Name:       t.ServicePortName,
-		Port:       int32(t.ServicePort),
-		Protocol:   corev1.ProtocolTCP,
-		TargetPort: intstr.FromString(name),
+	if !isKnative {
+		// Knative does not want name=http
+		containerPort.Name = name
+		// The service is managed by Knative, so, we only take care of this when it's managed by us
+		service := e.Resources.GetServiceForIntegration(e.Integration)
+		if service != nil {
+			servicePort := corev1.ServicePort{
+				Name:       t.ServicePortName,
+				Port:       int32(t.ServicePort),
+				Protocol:   corev1.ProtocolTCP,
+				TargetPort: intstr.FromString(name),
+			}
+			e.Integration.Status.SetCondition(
+				v1.IntegrationConditionServiceAvailable,
+				corev1.ConditionTrue,
+				v1.IntegrationConditionServiceAvailableReason,
+				// service -> container
+				fmt.Sprintf("%s(%s/%d) -> %s(%s/%d)",
+					service.Name, servicePort.Name, servicePort.Port,
+					container.Name, containerPort.Name, containerPort.ContainerPort),
+			)
+			service.Spec.Ports = append(service.Spec.Ports, servicePort)
+			// Mark the service as a user service
+			service.Labels["camel.apache.org/service.type"] = v1.ServiceTypeUser
+		}
 	}
-
-	e.Integration.Status.SetCondition(
-		v1.IntegrationConditionServiceAvailable,
-		corev1.ConditionTrue,
-		v1.IntegrationConditionServiceAvailableReason,
-
-		// service -> container
-		fmt.Sprintf("%s(%s/%d) -> %s(%s/%d)",
-			service.Name, servicePort.Name, servicePort.Port,
-			container.Name, containerPort.Name, containerPort.ContainerPort),
-	)
-
 	container.Ports = append(container.Ports, containerPort)
-	service.Spec.Ports = append(service.Spec.Ports, servicePort)
-
-	// Mark the service as a user service
-	service.Labels["camel.apache.org/service.type"] = v1.ServiceTypeUser
 }
 
 func (t *containerTrait) configureResources(container *corev1.Container) {
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index 6d039cda8..176dd9794 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -528,3 +528,130 @@ func createEnvironment() *Environment {
 
 	return environment
 }
+
+func TestDeploymentContainerPorts(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	require.NoError(t, err)
+
+	client, _ := test.NewFakeClient()
+	traitCatalog := NewCatalog(nil)
+
+	environment := Environment{
+		Ctx:          context.TODO(),
+		Client:       client,
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1.Integration{
+			Spec: v1.IntegrationSpec{
+				Profile: v1.TraitProfileKubernetes,
+				Traits: v1.Traits{
+					Container: &traitv1.ContainerTrait{
+						Port:        8081,
+						ServicePort: 8081,
+					},
+				},
+				Sources: []v1.SourceSpec{
+					{
+						Language: v1.LanguageJavaSource,
+						DataSpec: v1.DataSpec{
+							Name: "MyTest.java",
+							Content: `
+							public class MyRouteBuilder extends RouteBuilder {
+								@Override
+								public void configure() throws Exception {
+									from("netty-http:http://0.0.0.0:8081/hello").log("Received message: ${body}");
+								}
+							}
+							`,
+						},
+					},
+				},
+			},
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Build: v1.IntegrationPlatformBuildSpec{
+					RuntimeVersion: catalog.Runtime.Version,
+				},
+			},
+			Status: v1.IntegrationPlatformStatus{
+				Phase: v1.IntegrationPlatformPhaseReady,
+			},
+		},
+		Resources: kubernetes.NewCollection(),
+	}
+	environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+	environment.Platform.ResyncStatusFullConfig()
+
+	_, err = traitCatalog.apply(&environment)
+	require.NoError(t, err)
+	container := environment.GetIntegrationContainer()
+	assert.Len(t, container.Ports, 1)
+	assert.Equal(t, int32(8081), container.Ports[0].ContainerPort)
+	assert.Equal(t, "http", container.Ports[0].Name)
+	svc := environment.Resources.GetServiceForIntegration(environment.Integration)
+	assert.Len(t, svc.Spec.Ports, 1)
+	assert.Equal(t, int32(8081), svc.Spec.Ports[0].Port)
+}
+
+func TestKnativeServiceContainerPorts(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	require.NoError(t, err)
+
+	client, _ := test.NewFakeClient()
+	traitCatalog := NewCatalog(nil)
+
+	environment := Environment{
+		Ctx:          context.TODO(),
+		Client:       client,
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1.Integration{
+			Spec: v1.IntegrationSpec{
+				Profile: v1.TraitProfileKnative,
+				Traits: v1.Traits{
+					Container: &traitv1.ContainerTrait{
+						Port:        8081,
+						ServicePort: 8081,
+					},
+				},
+				Sources: []v1.SourceSpec{
+					{
+						Language: v1.LanguageJavaSource,
+						DataSpec: v1.DataSpec{
+							Name: "MyTest.java",
+							Content: `
+							public class MyRouteBuilder extends RouteBuilder {
+								@Override
+								public void configure() throws Exception {
+									from("netty-http:http://0.0.0.0:8081/hello").log("Received message: ${body}");
+								}
+							}
+							`,
+						},
+					},
+				},
+			},
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Build: v1.IntegrationPlatformBuildSpec{
+					RuntimeVersion: catalog.Runtime.Version,
+				},
+			},
+			Status: v1.IntegrationPlatformStatus{
+				Phase: v1.IntegrationPlatformPhaseReady,
+			},
+		},
+		Resources: kubernetes.NewCollection(),
+	}
+	environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+	environment.Platform.ResyncStatusFullConfig()
+
+	_, err = traitCatalog.apply(&environment)
+	require.NoError(t, err)
+	container := environment.GetIntegrationContainer()
+	assert.Len(t, container.Ports, 1)
+	assert.Equal(t, int32(8081), container.Ports[0].ContainerPort)
+	assert.Equal(t, "", container.Ports[0].Name)
+}