You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2019/07/18 16:18:50 UTC

[camel-k] 01/02: Stable container name #826

This is an automated email from the ASF dual-hosted git repository.

lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 98a8b9b1dfd5b285a7bc1881a3b73ad3a1a54ee0
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Thu Jul 18 11:20:19 2019 +0200

    Stable container name #826
---
 pkg/trait/container.go                           | 41 +++++++----
 pkg/trait/{service_test.go => container_test.go} | 91 +++---------------------
 pkg/trait/jolokia.go                             |  9 ++-
 pkg/trait/knative_service_test.go                | 79 ++++++++++++++++++++
 pkg/trait/prometheus.go                          |  8 ++-
 pkg/trait/service_test.go                        | 73 +++++++++++++++++++
 pkg/util/kubernetes/collection.go                | 10 +--
 7 files changed, 203 insertions(+), 108 deletions(-)

diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 118428a..2a127a8 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -28,6 +28,11 @@ import (
 	"k8s.io/apimachinery/pkg/util/intstr"
 )
 
+const (
+	defaultContainerName = "integration-container"
+	containerTraitID     = "container"
+)
+
 type containerTrait struct {
 	BaseTrait `property:",squash"`
 
@@ -41,15 +46,17 @@ type containerTrait struct {
 	PortName        string `property:"port-name"`
 	ServicePort     int    `property:"service-port"`
 	ServicePortName string `property:"service-port-name"`
+	Name            string `property:"name"`
 }
 
 func newContainerTrait() *containerTrait {
 	return &containerTrait{
-		BaseTrait:       newBaseTrait("container"),
+		BaseTrait:       newBaseTrait(containerTraitID),
 		Port:            8080,
 		PortName:        httpPortName,
 		ServicePort:     80,
 		ServicePortName: httpPortName,
+		Name:            defaultContainerName,
 	}
 }
 
@@ -74,19 +81,23 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) {
 
 func (t *containerTrait) Apply(e *Environment) error {
 
-	if e.Resources != nil {
-		//
-		// Add mounted volumes as resources
-		//
-		e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
-			for i := 0; i < len(deployment.Spec.Template.Spec.Containers); i++ {
-				t.configureResources(e, &deployment.Spec.Template.Spec.Containers[i])
-			}
-		})
-		e.Resources.VisitKnativeService(func(service *serving.Service) {
-			t.configureResources(e, &service.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container)
-		})
-	}
+	//
+	// Add mounted volumes as resources
+	//
+	e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
+		for i := 0; i < len(deployment.Spec.Template.Spec.Containers); i++ {
+			container := &deployment.Spec.Template.Spec.Containers[i]
+			container.Name = t.Name
+
+			t.configureResources(e, container)
+		}
+	})
+	e.Resources.VisitKnativeService(func(service *serving.Service) {
+		container := &service.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container
+		container.Name = t.Name
+
+		t.configureResources(e, container)
+	})
 
 	if t.Expose != nil && *t.Expose {
 		t.configureService(e)
@@ -101,7 +112,7 @@ func (t *containerTrait) configureService(e *Environment) {
 		return
 	}
 
-	container := e.Resources.GetContainerForIntegration(e.Integration)
+	container := e.Resources.GetContainerByName(t.Name)
 	if container == nil {
 		return
 	}
diff --git a/pkg/trait/service_test.go b/pkg/trait/container_test.go
similarity index 60%
copy from pkg/trait/service_test.go
copy to pkg/trait/container_test.go
index 4e14f66..f5793cc 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/container_test.go
@@ -27,19 +27,13 @@ import (
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/test"
 
-	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"github.com/stretchr/testify/assert"
 )
 
-const (
-	ServiceTestNamespace = "ns"
-	ServiceTestName      = "test"
-)
-
-func TestServiceWithDefaults(t *testing.T) {
+func TestContainerWithDefaults(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
@@ -58,24 +52,6 @@ func TestServiceWithDefaults(t *testing.T) {
 			},
 			Spec: v1alpha1.IntegrationSpec{
 				Profile: v1alpha1.TraitProfileKubernetes,
-				Sources: []v1alpha1.SourceSpec{
-					{
-						DataSpec: v1alpha1.DataSpec{
-							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
-							Compression: true,
-						},
-						Language: v1alpha1.LanguageJavaScript,
-					},
-				},
-				Traits: map[string]v1alpha1.TraitSpec{
-					"service": {
-						Configuration: map[string]string{
-							"enabled": "true",
-							"auto":    "false",
-						},
-					},
-				},
 			},
 		},
 		IntegrationKit: &v1alpha1.IntegrationKit{
@@ -103,31 +79,16 @@ func TestServiceWithDefaults(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotEmpty(t, environment.ExecutedTraits)
 	assert.NotNil(t, environment.GetTrait(ID("deployment")))
-	assert.NotNil(t, environment.GetTrait(ID("service")))
 	assert.NotNil(t, environment.GetTrait(ID("container")))
 
-	s := environment.Resources.GetService(func(service *corev1.Service) bool {
-		return service.Name == ServiceTestName
-	})
-	d := environment.Resources.GetDeployment(func(deployment *appsv1.Deployment) bool {
-		return deployment.Name == ServiceTestName
-	})
+	d := environment.Resources.GetDeploymentForIntegration(environment.Integration)
 
 	assert.NotNil(t, d)
-	assert.NotNil(t, s)
-
-	assert.Len(t, s.Spec.Ports, 1)
-	assert.Equal(t, int32(80), s.Spec.Ports[0].Port)
-	assert.Equal(t, "http", s.Spec.Ports[0].Name)
-	assert.Equal(t, "http", s.Spec.Ports[0].TargetPort.String())
-
 	assert.Len(t, d.Spec.Template.Spec.Containers, 1)
-	assert.Len(t, d.Spec.Template.Spec.Containers[0].Ports, 1)
-	assert.Equal(t, int32(8080), d.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort)
-	assert.Equal(t, "http", d.Spec.Template.Spec.Containers[0].Ports[0].Name)
+	assert.Equal(t, defaultContainerName, d.Spec.Template.Spec.Containers[0].Name)
 }
 
-func TestService(t *testing.T) {
+func TestContainerWithCustomName(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
@@ -139,38 +100,17 @@ func TestService(t *testing.T) {
 		Integration: &v1alpha1.Integration{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      ServiceTestName,
-				Namespace: ServiceTestNamespace,
+				Namespace: "ns",
 			},
 			Status: v1alpha1.IntegrationStatus{
 				Phase: v1alpha1.IntegrationPhaseDeploying,
 			},
 			Spec: v1alpha1.IntegrationSpec{
 				Profile: v1alpha1.TraitProfileKubernetes,
-				Sources: []v1alpha1.SourceSpec{
-					{
-						DataSpec: v1alpha1.DataSpec{
-							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
-							Compression: true,
-						},
-						Language: v1alpha1.LanguageJavaScript,
-					},
-				},
 				Traits: map[string]v1alpha1.TraitSpec{
-					"service": {
-						Configuration: map[string]string{
-							"enabled": "true",
-						},
-					},
 					"container": {
 						Configuration: map[string]string{
-							"enabled":           "true",
-							"auto":              "false",
-							"expose":            "true",
-							"port":              "8081",
-							"port-name":         "http-8081",
-							"service-port":      "81",
-							"service-port-name": "http-81",
+							"name": "my-container-name",
 						},
 					},
 				},
@@ -201,26 +141,11 @@ func TestService(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotEmpty(t, environment.ExecutedTraits)
 	assert.NotNil(t, environment.GetTrait(ID("deployment")))
-	assert.NotNil(t, environment.GetTrait(ID("service")))
 	assert.NotNil(t, environment.GetTrait(ID("container")))
 
-	s := environment.Resources.GetService(func(service *corev1.Service) bool {
-		return service.Name == ServiceTestName
-	})
-	d := environment.Resources.GetDeployment(func(deployment *appsv1.Deployment) bool {
-		return deployment.Name == ServiceTestName
-	})
+	d := environment.Resources.GetDeploymentForIntegration(environment.Integration)
 
 	assert.NotNil(t, d)
-	assert.NotNil(t, s)
-
-	assert.Len(t, s.Spec.Ports, 1)
-	assert.Equal(t, int32(81), s.Spec.Ports[0].Port)
-	assert.Equal(t, "http-81", s.Spec.Ports[0].Name)
-	assert.Equal(t, "http-8081", s.Spec.Ports[0].TargetPort.String())
-
 	assert.Len(t, d.Spec.Template.Spec.Containers, 1)
-	assert.Len(t, d.Spec.Template.Spec.Containers[0].Ports, 1)
-	assert.Equal(t, int32(8081), d.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort)
-	assert.Equal(t, "http-8081", d.Spec.Template.Spec.Containers[0].Ports[0].Name)
+	assert.Equal(t, environment.Integration.Spec.Traits["container"].Configuration["name"], d.Spec.Template.Spec.Containers[0].Name)
 }
diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go
index 60dec4d..bfe6174 100644
--- a/pkg/trait/jolokia.go
+++ b/pkg/trait/jolokia.go
@@ -115,7 +115,13 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) {
 	}
 	envvar.SetVal(&e.EnvVars, "AB_JOLOKIA_OPTS", strings.Join(optionValues, ","))
 
-	container := e.Resources.GetContainerForIntegration(e.Integration)
+	containerName := defaultContainerName
+	dt := e.Catalog.GetTrait(containerTraitID)
+	if dt != nil {
+		containerName = dt.(*containerTrait).Name
+	}
+
+	container := e.Resources.GetContainerByName(containerName)
 	if container == nil {
 		e.Integration.Status.SetCondition(
 			v1alpha1.IntegrationConditionJolokiaAvailable,
@@ -137,7 +143,6 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) {
 		v1alpha1.IntegrationConditionJolokiaAvailable,
 		corev1.ConditionTrue,
 		v1alpha1.IntegrationConditionJolokiaAvailableReason,
-		// service -> container
 		fmt.Sprintf("%s(%s/%d)", container.Name, containerPort.Name, containerPort.ContainerPort),
 	)
 
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index 30db759..01e2fb1 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -178,3 +178,82 @@ func TestKnativeService(t *testing.T) {
 	test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties")
 	test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d")
 }
+
+func TestKnativeServiceWithCustomContainerName(t *testing.T) {
+	catalog, err := test.DefaultCatalog()
+	assert.Nil(t, err)
+
+	traitCatalog := NewCatalog(context.TODO(), nil)
+
+	environment := Environment{
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1alpha1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      KnativeServiceTestName,
+				Namespace: KnativeServiceTestNamespace,
+			},
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseDeploying,
+			},
+
+			Spec: v1alpha1.IntegrationSpec{
+				Profile: v1alpha1.TraitProfileKnative,
+				Traits: map[string]v1alpha1.TraitSpec{
+					"deployer": {
+						Configuration: map[string]string{
+							"kind": "knative-service",
+						},
+					},
+					"knative-service": {
+						Configuration: map[string]string{
+							"enabled": "true",
+							"auto":    "false",
+						},
+					},
+					"container": {
+						Configuration: map[string]string{
+							"name": "my-container-name",
+						},
+					},
+				},
+			},
+		},
+		IntegrationKit: &v1alpha1.IntegrationKit{
+			Status: v1alpha1.IntegrationKitStatus{
+				Phase: v1alpha1.IntegrationKitPhaseReady,
+			},
+		},
+		Platform: &v1alpha1.IntegrationPlatform{
+			Spec: v1alpha1.IntegrationPlatformSpec{
+				Cluster: v1alpha1.IntegrationPlatformClusterOpenShift,
+				Build: v1alpha1.IntegrationPlatformBuildSpec{
+					PublishStrategy: v1alpha1.IntegrationPlatformBuildPublishStrategyS2I,
+					Registry:        v1alpha1.IntegrationPlatformRegistrySpec{Address: "registry"},
+				},
+			},
+		},
+		EnvVars:        make([]corev1.EnvVar, 0),
+		ExecutedTraits: make([]Trait, 0),
+		Resources:      kubernetes.NewCollection(),
+		Classpath:      strset.New(),
+	}
+
+	err = traitCatalog.apply(&environment)
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, environment.ExecutedTraits)
+	assert.NotNil(t, environment.GetTrait(ID("knative-service")))
+	assert.NotNil(t, environment.GetTrait(ID("container")))
+
+	s := environment.Resources.GetKnativeService(func(service *serving.Service) bool {
+		return service.Name == KnativeServiceTestName
+	})
+
+	assert.NotNil(t, s)
+	assert.Equal(
+		t,
+		environment.Integration.Spec.Traits["container"].Configuration["name"],
+		s.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.Name,
+	)
+}
diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go
index 51cdbb5..f52ad54 100644
--- a/pkg/trait/prometheus.go
+++ b/pkg/trait/prometheus.go
@@ -110,7 +110,13 @@ func (t *prometheusTrait) Apply(e *Environment) (err error) {
 }
 
 func (t *prometheusTrait) configureContainerPort(e *Environment) (*corev1.Container, *corev1.ContainerPort) {
-	container := e.Resources.GetContainerForIntegration(e.Integration)
+	containerName := defaultContainerName
+	dt := e.Catalog.GetTrait(containerTraitID)
+	if dt != nil {
+		containerName = dt.(*containerTrait).Name
+	}
+
+	container := e.Resources.GetContainerByName(containerName)
 	if container == nil {
 		return nil, nil
 	}
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index 4e14f66..fb5f6f5 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -224,3 +224,76 @@ func TestService(t *testing.T) {
 	assert.Equal(t, int32(8081), d.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort)
 	assert.Equal(t, "http-8081", d.Spec.Template.Spec.Containers[0].Ports[0].Name)
 }
+
+func TestServiceWithCustomContainerName(t *testing.T) {
+	catalog, err := test.DefaultCatalog()
+	assert.Nil(t, err)
+
+	traitCatalog := NewCatalog(context.TODO(), nil)
+
+	environment := Environment{
+		CamelCatalog: catalog,
+		Catalog:      traitCatalog,
+		Integration: &v1alpha1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      ServiceTestName,
+				Namespace: ServiceTestNamespace,
+			},
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseDeploying,
+			},
+			Spec: v1alpha1.IntegrationSpec{
+				Profile: v1alpha1.TraitProfileKubernetes,
+				Traits: map[string]v1alpha1.TraitSpec{
+					"service": {
+						Configuration: map[string]string{
+							"enabled": "true",
+							"auto":    "false",
+						},
+					},
+					"container": {
+						Configuration: map[string]string{
+							"name": "my-container-name",
+						},
+					},
+				},
+			},
+		},
+		IntegrationKit: &v1alpha1.IntegrationKit{
+			Status: v1alpha1.IntegrationKitStatus{
+				Phase: v1alpha1.IntegrationKitPhaseReady,
+			},
+		},
+		Platform: &v1alpha1.IntegrationPlatform{
+			Spec: v1alpha1.IntegrationPlatformSpec{
+				Cluster: v1alpha1.IntegrationPlatformClusterOpenShift,
+				Build: v1alpha1.IntegrationPlatformBuildSpec{
+					PublishStrategy: v1alpha1.IntegrationPlatformBuildPublishStrategyS2I,
+					Registry:        v1alpha1.IntegrationPlatformRegistrySpec{Address: "registry"},
+				},
+			},
+		},
+		EnvVars:        make([]corev1.EnvVar, 0),
+		ExecutedTraits: make([]Trait, 0),
+		Resources:      kubernetes.NewCollection(),
+		Classpath:      strset.New(),
+	}
+
+	err = traitCatalog.apply(&environment)
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, environment.ExecutedTraits)
+	assert.NotNil(t, environment.GetTrait(ID("deployment")))
+	assert.NotNil(t, environment.GetTrait(ID("service")))
+	assert.NotNil(t, environment.GetTrait(ID("container")))
+
+	d := environment.Resources.GetDeploymentForIntegration(environment.Integration)
+	assert.NotNil(t, d)
+
+	assert.Len(t, d.Spec.Template.Spec.Containers, 1)
+	assert.Equal(
+		t,
+		environment.Integration.Spec.Traits["container"].Configuration["name"],
+		d.Spec.Template.Spec.Containers[0].Name,
+	)
+}
diff --git a/pkg/util/kubernetes/collection.go b/pkg/util/kubernetes/collection.go
index ca27e9a..b1444c3 100644
--- a/pkg/util/kubernetes/collection.go
+++ b/pkg/util/kubernetes/collection.go
@@ -261,14 +261,10 @@ func (c *Collection) GetContainer(filter func(container *corev1.Container) bool)
 	return retValue
 }
 
-// GetContainerForIntegration --
-func (c *Collection) GetContainerForIntegration(integration *v1alpha1.Integration) *corev1.Container {
-	if integration == nil {
-		return nil
-	}
-
+// GetContainerByName --
+func (c *Collection) GetContainerByName(name string) *corev1.Container {
 	return c.GetContainer(func(c *corev1.Container) bool {
-		return c.Name == integration.Name
+		return c.Name == name
 	})
 }