This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/master by this push: new 2b47d49 Service trait: confusing behavior #753 2b47d49 is described below commit 2b47d49d76518c8fb6c017a8f49c3725ff51f9f6 Author: lburgazzoli <lburgazz...@gmail.com> AuthorDate: Thu Jun 20 12:37:51 2019 +0200 Service trait: confusing behavior #753 --- docs/traits.adoc | 9 ++ pkg/trait/service.go | 24 ++++-- pkg/trait/service_test.go | 213 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 9 deletions(-) diff --git a/docs/traits.adoc b/docs/traits.adoc index 6fe5929..72c5dce 100644 --- a/docs/traits.adoc +++ b/docs/traits.adoc @@ -191,8 +191,17 @@ More information can be found in the official Kubernetes documentation about htt !=== ! service.port +! To configure a different port exposed by the service (default `80`). + +! service.port-name +! To configure a different port name for the port exposed by the service (default `http`). + +! service.container-port ! To configure a different port exposed by the container (default `8080`). +! service.container-port-name +! To configure a different port name for the port exposed by the container (default `http`). + !=== | route diff --git a/pkg/trait/service.go b/pkg/trait/service.go index 408a05b..f852c2c 100644 --- a/pkg/trait/service.go +++ b/pkg/trait/service.go @@ -30,16 +30,22 @@ import ( type serviceTrait struct { BaseTrait `property:",squash"` - Auto *bool `property:"auto"` - Port int `property:"port"` + Auto *bool `property:"auto"` + Port int `property:"port"` + PortName string `property:"port-name"` + ContainerPort int `property:"container-port"` + ContainerPortName string `property:"container-port-name"` } const httpPortName = "http" func newServiceTrait() *serviceTrait { return &serviceTrait{ - BaseTrait: newBaseTrait("service"), - Port: 8080, + BaseTrait: newBaseTrait("service"), + Port: 80, + PortName: httpPortName, + ContainerPort: 8080, + ContainerPortName: httpPortName, } } @@ -77,10 +83,10 @@ func (t *serviceTrait) Apply(e *Environment) (err error) { e.Resources.Add(svc) } port := corev1.ServicePort{ - Name: httpPortName, - Port: 80, + Name: t.PortName, + Port: int32(t.Port), Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromString(httpPortName), + TargetPort: intstr.FromString(t.ContainerPortName), } svc.Spec.Ports = append(svc.Spec.Ports, port) @@ -97,8 +103,8 @@ func (t *serviceTrait) Apply(e *Environment) (err error) { }) if container != nil { container.Ports = append(container.Ports, corev1.ContainerPort{ - Name: httpPortName, - ContainerPort: int32(t.Port), + Name: t.ContainerPortName, + ContainerPort: int32(t.ContainerPort), Protocol: corev1.ProtocolTCP, }) } else { diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go new file mode 100644 index 0000000..7196c77 --- /dev/null +++ b/pkg/trait/service_test.go @@ -0,0 +1,213 @@ +/* +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. +*/ + +package trait + +import ( + "context" + "testing" + + "github.com/scylladb/go-set/strset" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "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" +) + +func TestServiceWithDefaults(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: "test", + 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", + "auto": "false", + }, + }, + }, + }, + }, + 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(&appsv1.Deployment{}), + 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"))) + + s := environment.Resources.GetService(func(service *corev1.Service) bool { + return service.Name == "test" + }) + d := environment.Resources.GetDeployment(func(deployment *appsv1.Deployment) bool { + return deployment.Name == "test" + }) + + 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) +} + +func TestService(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: "test", + 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", + "auto": "false", + "port": "81", + "port-name": "http-81", + "container-port": "8081", + "container-port-name": "http-8081", + }, + }, + }, + }, + }, + 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(&appsv1.Deployment{}), + 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"))) + + s := environment.Resources.GetService(func(service *corev1.Service) bool { + return service.Name == "test" + }) + d := environment.Resources.GetDeployment(func(deployment *appsv1.Deployment) bool { + return deployment.Name == "test" + }) + + 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) +}