camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lburgazz...@apache.org
Subject [camel-k] 06/14: Added trait configuration
Date Mon, 08 Oct 2018 14:19:46 GMT
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 5d004a81f682aa55ea59989e3b3636228b936548
Author: nferraro <ni.ferraro@gmail.com>
AuthorDate: Thu Oct 4 18:13:52 2018 +0200

    Added trait configuration
---
 pkg/stub/action/integration/deploy.go |  11 +---
 pkg/trait/base.go                     |  10 ++--
 pkg/trait/catalog.go                  |  59 ++++++++------------
 pkg/trait/identity.go                 |  33 -----------
 pkg/trait/owner.go                    |   6 +-
 pkg/trait/route.go                    |   8 +--
 pkg/trait/service.go                  |  37 ++++++++-----
 pkg/trait/trait.go                    |  40 +++++++-------
 pkg/trait/types.go                    | 101 ++++++++++++++++++++++++++++++++++
 9 files changed, 181 insertions(+), 124 deletions(-)

diff --git a/pkg/stub/action/integration/deploy.go b/pkg/stub/action/integration/deploy.go
index 9790bf8..2c814bc 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -22,7 +22,6 @@ import (
 	"github.com/apache/camel-k/pkg/trait"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
-	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
 
@@ -43,18 +42,12 @@ func (action *deployAction) CanHandle(integration *v1alpha1.Integration)
bool {
 }
 
 func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
-	environment, err := trait.NewEnvironment(integration)
+	resources, err := trait.ComputeDeployment(integration)
 	if err != nil {
 		return err
 	}
-	resources := kubernetes.NewCollection()
-	customizers := trait.CustomizersFor(*environment)
-	// invoke the trait framework to determine the needed resources
-	if _, err = customizers.Customize(*environment, resources); err != nil {
-		return errors.Wrap(err, "error during trait customization")
-	}
 	// TODO we should look for objects that are no longer present in the collection and remove
them
-	err = kubernetes.ReplaceResources(resources.Items())
+	err = kubernetes.ReplaceResources(resources)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/trait/base.go b/pkg/trait/base.go
index 6ba4dfc..d5eea62 100644
--- a/pkg/trait/base.go
+++ b/pkg/trait/base.go
@@ -30,11 +30,11 @@ import (
 type baseTrait struct {
 }
 
-func (*baseTrait) ID() ID {
-	return ID("base")
+func (*baseTrait) id() id {
+	return id("base")
 }
 
-func (d *baseTrait) Customize(environment Environment, resources *kubernetes.Collection)
(bool, error) {
+func (d *baseTrait) customize(environment environment, resources *kubernetes.Collection)
(bool, error) {
 	resources.Add(d.getConfigMapFor(environment))
 	resources.Add(d.getDeploymentFor(environment))
 	return true, nil
@@ -46,7 +46,7 @@ func (d *baseTrait) Customize(environment Environment, resources *kubernetes.Col
 //
 // **********************************
 
-func (*baseTrait) getConfigMapFor(e Environment) *corev1.ConfigMap {
+func (*baseTrait) getConfigMapFor(e environment) *corev1.ConfigMap {
 	// combine properties of integration with context, integration
 	// properties have the priority
 	properties := CombineConfigurationAsMap("property", e.Context, e.Integration)
@@ -82,7 +82,7 @@ func (*baseTrait) getConfigMapFor(e Environment) *corev1.ConfigMap {
 //
 // **********************************
 
-func (*baseTrait) getDeploymentFor(e Environment) *appsv1.Deployment {
+func (*baseTrait) getDeploymentFor(e environment) *appsv1.Deployment {
 	sourceName := strings.TrimPrefix(e.Integration.Spec.Source.Name, "/")
 
 	// combine environment of integration with context, integration
diff --git a/pkg/trait/catalog.go b/pkg/trait/catalog.go
index a969012..a2ba3b5 100644
--- a/pkg/trait/catalog.go
+++ b/pkg/trait/catalog.go
@@ -23,14 +23,14 @@ import (
 )
 
 var (
-	tBase = &baseTrait{}
+	tBase    = &baseTrait{}
 	tService = &serviceTrait{}
-	tRoute = &routeTrait{}
-	tOwner = &ownerTrait{}
+	tRoute   = &routeTrait{}
+	tOwner   = &ownerTrait{}
 )
 
-// CustomizersFor returns a Catalog for the given integration details
-func CustomizersFor(environment Environment) Customizer {
+// customizersFor returns a Catalog for the given integration details
+func customizersFor(environment environment) customizer {
 	switch environment.Platform.Spec.Cluster {
 	case v1alpha1.IntegrationPlatformClusterOpenShift:
 		return compose(
@@ -50,46 +50,33 @@ func CustomizersFor(environment Environment) Customizer {
 	return nil
 }
 
-func compose(traits ...Customizer) Customizer {
-	if len(traits) == 0 {
-		return &identityTrait{}
-	} else if len(traits) == 1 {
-		return traits[0]
+func compose(traits ...customizer) customizer {
+	return &chainedCustomizer{
+		customizers: traits,
 	}
-	var composite Customizer = &identityTrait{}
-	for _, t := range traits {
-		composite = &chainedCustomizer{
-			t1: composite,
-			t2: t,
-		}
-	}
-	return composite
 }
 
 // -------------------------------------------
 
 type chainedCustomizer struct {
-	t1 Customizer
-	t2 Customizer
+	customizers []customizer
 }
 
-func (c *chainedCustomizer) ID() ID {
-	return ID("")
+func (c *chainedCustomizer) id() id {
+	return id("")
 }
 
-func (c *chainedCustomizer) Customize(environment Environment, resources *kubernetes.Collection)
(bool, error) {
-	atLeastOnce := false
-	var done bool
-	var err error
-	if done, err = c.t1.Customize(environment, resources); err != nil {
-		return false, err
-	} else if done && c.t1.ID() != "" {
-		environment.ExecutedCustomizers = append(environment.ExecutedCustomizers, c.t1.ID())
-	}
-	atLeastOnce = atLeastOnce || done
-	done2, err := c.t2.Customize(environment, resources)
-	if done2 && c.t2.ID() != "" {
-		environment.ExecutedCustomizers = append(environment.ExecutedCustomizers, c.t2.ID())
+func (c *chainedCustomizer) customize(environment environment, resources *kubernetes.Collection)
(bool, error) {
+	atLeastOne := false
+	for _, custom := range c.customizers {
+		if environment.isEnabled(custom.id()) {
+			if done, err := custom.customize(environment, resources); err != nil {
+				return false, err
+			} else if done && custom.id() != "" {
+				environment.ExecutedCustomizers = append(environment.ExecutedCustomizers, custom.id())
+				atLeastOne = atLeastOne || done
+			}
+		}
 	}
-	return atLeastOnce || done2, err
+	return atLeastOne, nil
 }
diff --git a/pkg/trait/identity.go b/pkg/trait/identity.go
deleted file mode 100644
index eda9d3a..0000000
--- a/pkg/trait/identity.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-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 (
-	"github.com/apache/camel-k/pkg/util/kubernetes"
-)
-
-type identityTrait struct {
-}
-
-func (*identityTrait) ID() ID {
-	return ID("identity")
-}
-
-func (*identityTrait) Customize(environment Environment, resources *kubernetes.Collection)
(bool, error) {
-	return false, nil
-}
diff --git a/pkg/trait/owner.go b/pkg/trait/owner.go
index 905800b..6d77ff9 100644
--- a/pkg/trait/owner.go
+++ b/pkg/trait/owner.go
@@ -24,11 +24,11 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 type ownerTrait struct {
 }
 
-func (*ownerTrait) ID() ID {
-	return ID("identity")
+func (*ownerTrait) id() id {
+	return id("owner")
 }
 
-func (*ownerTrait) Customize(e Environment, resources *kubernetes.Collection) (bool, error)
{
+func (*ownerTrait) customize(e environment, resources *kubernetes.Collection) (bool, error)
{
 	controller := true
 	blockOwnerDeletion := true
 	resources.VisitMetaObject(func(res metav1.Object) {
diff --git a/pkg/trait/route.go b/pkg/trait/route.go
index 1906442..ded0fe3 100644
--- a/pkg/trait/route.go
+++ b/pkg/trait/route.go
@@ -28,11 +28,11 @@ import (
 type routeTrait struct {
 }
 
-func (*routeTrait) ID() ID {
-	return ID("route")
+func (*routeTrait) id() id {
+	return id("route")
 }
 
-func (e *routeTrait) Customize(environment Environment, resources *kubernetes.Collection)
(bool, error) {
+func (e *routeTrait) customize(environment environment, resources *kubernetes.Collection)
(bool, error) {
 	var service *corev1.Service
 	resources.VisitService(func(s *corev1.Service) {
 		if s.ObjectMeta.Labels != nil {
@@ -50,7 +50,7 @@ func (e *routeTrait) Customize(environment Environment, resources *kubernetes.Co
 	return false, nil
 }
 
-func (*routeTrait) getRouteFor(e Environment, service *corev1.Service) *routev1.Route {
+func (*routeTrait) getRouteFor(e environment, service *corev1.Service) *routev1.Route {
 	route := routev1.Route{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "Route",
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index a6438d8..d7d116a 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -37,19 +37,32 @@ var webComponents = map[string]bool{
 type serviceTrait struct {
 }
 
-func (*serviceTrait) ID() ID {
-	return ID("service")
+const (
+	serviceTraitPortKey = "port"
+)
+
+func (*serviceTrait) id() id {
+	return id("service")
 }
 
-func (e *serviceTrait) Customize(environment Environment, resources *kubernetes.Collection)
(bool, error) {
+func (e *serviceTrait) customize(environment environment, resources *kubernetes.Collection)
(bool, error) {
 	if !e.requiresService(environment) {
 		return false, nil
 	}
-	resources.Add(e.getServiceFor(environment))
+	svc, err := e.getServiceFor(environment)
+	if err != nil {
+		return false, err
+	}
+	resources.Add(svc)
 	return true, nil
 }
 
-func (*serviceTrait) getServiceFor(e Environment) *corev1.Service {
+func (s *serviceTrait) getServiceFor(e environment) (*corev1.Service, error) {
+	port, err := e.getIntConfigOr(s.id(), serviceTraitPortKey, 8080)
+	if err != nil {
+		return nil, err
+	}
+
 	svc := corev1.Service{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "Service",
@@ -65,12 +78,10 @@ func (*serviceTrait) getServiceFor(e Environment) *corev1.Service {
 		Spec: corev1.ServiceSpec{
 			Ports: []corev1.ServicePort{
 				{
-					Name:     "http",
-					Port:     80,
-					Protocol: corev1.ProtocolTCP,
-					// TODO discovering the real port is hard - maybe we should just set 8080 as conventional
port in the doc
-					// or allow users to configure it in the trait configuration section
-					TargetPort: intstr.FromInt(8080),
+					Name:       "http",
+					Port:       80,
+					Protocol:   corev1.ProtocolTCP,
+					TargetPort: intstr.FromInt(port),
 				},
 			},
 			Selector: map[string]string{
@@ -79,10 +90,10 @@ func (*serviceTrait) getServiceFor(e Environment) *corev1.Service {
 		},
 	}
 
-	return &svc
+	return &svc, nil
 }
 
-func (*serviceTrait) requiresService(environment Environment) bool {
+func (*serviceTrait) requiresService(environment environment) bool {
 	for _, dep := range environment.Integration.Spec.Dependencies {
 		if decision, present := webComponents[dep]; present {
 			return decision
diff --git a/pkg/trait/trait.go b/pkg/trait/trait.go
index d9c372f..a2b83c6 100644
--- a/pkg/trait/trait.go
+++ b/pkg/trait/trait.go
@@ -21,18 +21,27 @@ import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/pkg/errors"
+	"k8s.io/apimachinery/pkg/runtime"
 )
 
-// A Environment provides the context where the trait is executed
-type Environment struct {
-	Platform            *v1alpha1.IntegrationPlatform
-	Context             *v1alpha1.IntegrationContext
-	Integration         *v1alpha1.Integration
-	ExecutedCustomizers []ID
+// ComputeDeployment generates all required resources for deploying the given integration
+func ComputeDeployment(integration *v1alpha1.Integration) ([]runtime.Object, error) {
+	environment, err := newEnvironment(integration)
+	if err != nil {
+		return nil, err
+	}
+	resources := kubernetes.NewCollection()
+	customizers := customizersFor(*environment)
+	// invoke the trait framework to determine the needed resources
+	if _, err = customizers.customize(*environment, resources); err != nil {
+		return nil, errors.Wrap(err, "error during trait customization")
+	}
+	return resources.Items(), nil
 }
 
-// NewEnvironment creates a Environment from the given data
-func NewEnvironment(integration *v1alpha1.Integration) (*Environment, error) {
+// newEnvironment creates a environment from the given data
+func newEnvironment(integration *v1alpha1.Integration) (*environment, error) {
 	pl, err := platform.GetCurrentPlatform(integration.Namespace)
 	if err != nil {
 		return nil, err
@@ -42,21 +51,10 @@ func NewEnvironment(integration *v1alpha1.Integration) (*Environment,
error) {
 		return nil, err
 	}
 
-	return &Environment{
+	return &environment{
 		Platform:            pl,
 		Context:             ctx,
 		Integration:         integration,
-		ExecutedCustomizers: make([]ID, 0),
+		ExecutedCustomizers: make([]id, 0),
 	}, nil
 }
-
-// ID uniquely identifies a trait
-type ID string
-
-// A Customizer performs customization of the deployed objects
-type Customizer interface {
-	// The Name of the customizer
-	ID() ID
-	// Customize executes the trait customization on the resources and return true if the resources
have been changed
-	Customize(environment Environment, resources *kubernetes.Collection) (bool, error)
-}
diff --git a/pkg/trait/types.go b/pkg/trait/types.go
new file mode 100644
index 0000000..dd8c269
--- /dev/null
+++ b/pkg/trait/types.go
@@ -0,0 +1,101 @@
+/*
+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 (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/pkg/errors"
+	"strconv"
+)
+
+// ID uniquely identifies a trait
+type id string
+
+// A Customizer performs customization of the deployed objects
+type customizer interface {
+	// The Name of the customizer
+	id() id
+	// Customize executes the trait customization on the resources and return true if the resources
have been changed
+	customize(environment environment, resources *kubernetes.Collection) (bool, error)
+}
+
+// A environment provides the context where the trait is executed
+type environment struct {
+	Platform            *v1alpha1.IntegrationPlatform
+	Context             *v1alpha1.IntegrationContext
+	Integration         *v1alpha1.Integration
+	ExecutedCustomizers []id
+}
+
+func (e environment) getTraitSpec(traitID id) *v1alpha1.IntegrationTraitSpec {
+	if e.Integration.Spec.Traits == nil {
+		return nil
+	}
+	if conf, ok := e.Integration.Spec.Traits[string(traitID)]; ok {
+		return &conf
+	}
+	return nil
+}
+
+func (e environment) isEnabled(traitID id) bool {
+	conf := e.getTraitSpec(traitID)
+	return conf == nil || conf.Enabled == nil || *conf.Enabled
+}
+
+func (e environment) getConfig(traitID id, key string) *string {
+	conf := e.getTraitSpec(traitID)
+	if conf == nil || conf.Configuration == nil {
+		return nil
+	}
+	if v, ok := conf.Configuration[key]; ok {
+		return &v
+	}
+	return nil
+}
+
+func (e environment) getConfigOr(traitID id, key string, defaultValue string) string {
+	val := e.getConfig(traitID, key)
+	if val != nil {
+		return *val
+	}
+	return defaultValue
+}
+
+func (e environment) getIntConfig(traitID id, key string) (*int, error) {
+	val := e.getConfig(traitID, key)
+	if val == nil {
+		return nil, nil
+	}
+	intVal, err := strconv.Atoi(*val)
+	if err != nil {
+		return nil, errors.Wrap(err, "cannot extract a integer from property "+key+" with value
"+*val)
+	}
+	return &intVal, nil
+}
+
+func (e environment) getIntConfigOr(traitID id, key string, defaultValue int) (int, error)
{
+	val, err := e.getIntConfig(traitID, key)
+	if err != nil {
+		return 0, err
+	}
+	if val != nil {
+		return *val, nil
+	}
+	return defaultValue, nil
+}


Mime
View raw message