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 <[email protected]>
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
+}

Reply via email to