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

astefanutti pushed a commit to branch release-1.6.x
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit a6e181b02d8450a0564dc4cfb2783daf4b607c61
Author: Antonin Stefanutti <anto...@stefanutti.fr>
AuthorDate: Fri Sep 17 11:49:01 2021 +0200

    fix: Unify post-build integration phases reconciliation
---
 pkg/controller/integration/build_kit.go            |   5 +-
 pkg/controller/integration/deploy.go               |  64 ----------
 pkg/controller/integration/error.go                |  97 ---------------
 .../integration/integration_controller.go          |   2 -
 pkg/controller/integration/monitor.go              |  92 ++++++++++----
 pkg/trait/affinity.go                              |   2 +-
 pkg/trait/container.go                             |  16 +--
 pkg/trait/cron.go                                  |  23 ++--
 pkg/trait/deployer.go                              |  75 ++++--------
 pkg/trait/deployer_test.go                         |  12 +-
 pkg/trait/deployment.go                            |  49 ++++----
 pkg/trait/environment.go                           |   3 +-
 pkg/trait/error_handler.go                         |   7 +-
 pkg/trait/gc.go                                    |   7 +-
 pkg/trait/ingress.go                               |   2 +-
 pkg/trait/ingress_test.go                          |   2 +-
 pkg/trait/init.go                                  |  72 +++++------
 pkg/trait/istio.go                                 |   6 +-
 pkg/trait/jolokia.go                               |  10 +-
 pkg/trait/jvm.go                                   |   7 +-
 pkg/trait/jvm_test.go                              |   2 +-
 pkg/trait/kamelets.go                              |  13 +-
 pkg/trait/knative.go                               |   4 +-
 pkg/trait/knative_service.go                       | 134 ++++++++++-----------
 pkg/trait/logging.go                               |   3 +-
 pkg/trait/owner.go                                 |   3 +-
 pkg/trait/pdb.go                                   |   5 +-
 pkg/trait/platform.go                              |   3 +-
 pkg/trait/pod.go                                   |   2 +-
 pkg/trait/prometheus.go                            |  10 +-
 pkg/trait/pull_secret.go                           |  18 +--
 pkg/trait/route.go                                 |   6 +-
 pkg/trait/service.go                               |   2 +-
 pkg/trait/service_binding.go                       |  16 +--
 pkg/trait/toleration.go                            |   3 +-
 pkg/trait/trait_types.go                           |   5 +-
 36 files changed, 299 insertions(+), 483 deletions(-)

diff --git a/pkg/controller/integration/build_kit.go 
b/pkg/controller/integration/build_kit.go
index 005ed45..8c2b6a0 100644
--- a/pkg/controller/integration/build_kit.go
+++ b/pkg/controller/integration/build_kit.go
@@ -93,12 +93,9 @@ func (action *buildKitAction) Handle(ctx context.Context, 
integration *v1.Integr
 
                if kit.Status.Phase == v1.IntegrationKitPhaseReady {
                        integration.Status.Image = kit.Status.Image
+                       integration.Status.Phase = v1.IntegrationPhaseDeploying
                        integration.SetIntegrationKit(kit)
 
-                       if _, err := trait.Apply(ctx, action.client, 
integration, kit); err != nil {
-                               return nil, err
-                       }
-
                        return integration, nil
                }
 
diff --git a/pkg/controller/integration/deploy.go 
b/pkg/controller/integration/deploy.go
deleted file mode 100644
index fee22ae..0000000
--- a/pkg/controller/integration/deploy.go
+++ /dev/null
@@ -1,64 +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 integration
-
-import (
-       "context"
-
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-       "github.com/apache/camel-k/pkg/trait"
-       "github.com/apache/camel-k/pkg/util/kubernetes"
-       "github.com/pkg/errors"
-)
-
-// NewDeployAction create an action that handles integration deploy
-func NewDeployAction() Action {
-       return &deployAction{}
-}
-
-type deployAction struct {
-       baseAction
-}
-
-func (action *deployAction) Name() string {
-       return "deploy"
-}
-
-func (action *deployAction) CanHandle(integration *v1.Integration) bool {
-       return integration.Status.Phase == v1.IntegrationPhaseDeploying
-}
-
-func (action *deployAction) Handle(ctx context.Context, integration 
*v1.Integration) (*v1.Integration, error) {
-       if integration.Status.IntegrationKit == nil {
-               return nil, errors.Errorf("no kit set on integration %s", 
integration.Name)
-       }
-
-       kit, err := kubernetes.GetIntegrationKit(ctx, action.client, 
integration.Status.IntegrationKit.Name, 
integration.Status.IntegrationKit.Namespace)
-       if err != nil {
-               return nil, errors.Wrapf(err, "unable to find integration kit 
%s/%s, %s", integration.Status.IntegrationKit.Namespace, 
integration.Status.IntegrationKit.Name, err)
-       }
-
-       _, err = trait.Apply(ctx, action.client, integration, kit)
-       if err != nil {
-               return nil, err
-       }
-
-       integration.Status.Phase = v1.IntegrationPhaseRunning
-
-       return integration, nil
-}
diff --git a/pkg/controller/integration/error.go 
b/pkg/controller/integration/error.go
deleted file mode 100644
index a7f490c..0000000
--- a/pkg/controller/integration/error.go
+++ /dev/null
@@ -1,97 +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 integration
-
-import (
-       "context"
-
-       appsv1 "k8s.io/api/apps/v1"
-       corev1 "k8s.io/api/core/v1"
-
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-       "github.com/apache/camel-k/pkg/util/digest"
-       "github.com/apache/camel-k/pkg/util/kubernetes"
-       k8serrors "k8s.io/apimachinery/pkg/api/errors"
-)
-
-// NewErrorAction creates a new error action for an integration
-func NewErrorAction() Action {
-       return &errorAction{}
-}
-
-type errorAction struct {
-       baseAction
-}
-
-func (action *errorAction) Name() string {
-       return "error"
-}
-
-func (action *errorAction) CanHandle(integration *v1.Integration) bool {
-       return integration.Status.Phase == v1.IntegrationPhaseError
-}
-
-func (action *errorAction) Handle(ctx context.Context, integration 
*v1.Integration) (*v1.Integration, error) {
-       hash, err := digest.ComputeForIntegration(integration)
-       if err != nil {
-               return nil, err
-       }
-
-       if hash != integration.Status.Digest {
-               action.L.Info("Integration needs a rebuild")
-
-               integration.Initialize()
-               integration.Status.Digest = hash
-
-               return integration, nil
-       }
-
-       if kubernetes.IsConditionTrue(integration, 
v1.IntegrationConditionDeploymentAvailable) {
-               deployment, err := kubernetes.GetDeployment(ctx, action.client, 
integration.Name, integration.Namespace)
-               if err != nil && k8serrors.IsNotFound(err) {
-                       return nil, err
-               }
-
-               // if the integration is in error phase, check if the 
corresponding pod is running ok, the user may have updated the integration.
-               deployAvailable := false
-               progressingOk := false
-               for _, c := range deployment.Status.Conditions {
-                       // first, check if the container is in available state
-                       if c.Type == appsv1.DeploymentAvailable {
-                               deployAvailable = c.Status == 
corev1.ConditionTrue
-                       }
-                       // second, check the progressing and the reasons
-                       if c.Type == appsv1.DeploymentProgressing {
-                               progressingOk = c.Status == 
corev1.ConditionTrue && (c.Reason == "NewReplicaSetAvailable" || c.Reason == 
"ReplicaSetUpdated")
-                       }
-               }
-               if deployAvailable && progressingOk {
-                       availableCondition := v1.IntegrationCondition{
-                               Type:   v1.IntegrationConditionReady, 
-                               Status: corev1.ConditionTrue,
-                               Reason: 
v1.IntegrationConditionReplicaSetReadyReason,
-                       }
-                       integration.Status.SetConditions(availableCondition)
-                       integration.Status.Phase = v1.IntegrationPhaseRunning
-                       return integration, nil
-               }
-       }
-
-       // TODO check also if deployment matches (e.g. replicas)
-       return nil, nil
-}
diff --git a/pkg/controller/integration/integration_controller.go 
b/pkg/controller/integration/integration_controller.go
index 0a4df39..719318a 100644
--- a/pkg/controller/integration/integration_controller.go
+++ b/pkg/controller/integration/integration_controller.go
@@ -309,9 +309,7 @@ func (r *reconcileIntegration) Reconcile(ctx 
context.Context, request reconcile.
                NewPlatformSetupAction(),
                NewInitializeAction(),
                newBuildKitAction(),
-               NewDeployAction(),
                NewMonitorAction(),
-               NewErrorAction(),
        }
 
        for _, a := range actions {
diff --git a/pkg/controller/integration/monitor.go 
b/pkg/controller/integration/monitor.go
index 515d2d4..96d1f5a 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -20,6 +20,8 @@ package integration
 import (
        "context"
 
+       "github.com/pkg/errors"
+
        appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
 
@@ -45,10 +47,18 @@ func (action *monitorAction) Name() string {
 }
 
 func (action *monitorAction) CanHandle(integration *v1.Integration) bool {
-       return integration.Status.Phase == v1.IntegrationPhaseRunning
+       return integration.Status.Phase == v1.IntegrationPhaseDeploying ||
+               integration.Status.Phase == v1.IntegrationPhaseRunning ||
+               integration.Status.Phase == v1.IntegrationPhaseError
 }
 
 func (action *monitorAction) Handle(ctx context.Context, integration 
*v1.Integration) (*v1.Integration, error) {
+       // At that staged the Integration must have a Kit
+       if integration.Status.IntegrationKit == nil {
+               return nil, errors.Errorf("no kit set on integration %s", 
integration.Name)
+       }
+
+       // Check if the Integration requires a rebuild
        hash, err := digest.ComputeForIntegration(integration)
        if err != nil {
                return nil, err
@@ -94,14 +104,18 @@ func (action *monitorAction) Handle(ctx context.Context, 
integration *v1.Integra
                }
        }
 
-       // Mirror ready condition from the owned resource (e.g.ReplicaSet, 
Deployment, CronJob, ...)
+       // Reconcile Integration phase
+       if integration.Status.Phase == v1.IntegrationPhaseDeploying {
+               integration.Status.Phase = v1.IntegrationPhaseRunning
+       }
+
+       // Mirror ready condition from the owned resource (e.g., Deployment, 
CronJob, KnativeService ...)
        // into the owning integration
        previous := 
integration.Status.GetCondition(v1.IntegrationConditionReady)
        kubernetes.MirrorReadyCondition(ctx, action.client, integration)
 
-       if next := 
integration.Status.GetCondition(v1.IntegrationConditionReady);
-               (previous == nil || previous.FirstTruthyTime == nil || 
previous.FirstTruthyTime.IsZero()) &&
-                       next != nil && next.Status == corev1.ConditionTrue && 
!(next.FirstTruthyTime == nil || next.FirstTruthyTime.IsZero()) {
+       if next := 
integration.Status.GetCondition(v1.IntegrationConditionReady); (previous == nil 
|| previous.FirstTruthyTime == nil || previous.FirstTruthyTime.IsZero()) &&
+               next != nil && next.Status == corev1.ConditionTrue && 
!(next.FirstTruthyTime == nil || next.FirstTruthyTime.IsZero()) {
                // Observe the time to first readiness metric
                duration := 
next.FirstTruthyTime.Time.Sub(integration.Status.InitializationTimestamp.Time)
                action.L.Infof("First readiness after %s", duration)
@@ -116,29 +130,57 @@ func (action *monitorAction) Handle(ctx context.Context, 
integration *v1.Integra
                        return nil, err
                }
 
-               deployUnavailable := false
-               progressingFailing := false
-               for _, c := range deployment.Status.Conditions {
-                       // first, check if the container status is not available
-                       if c.Type == appsv1.DeploymentAvailable {
-                               deployUnavailable = c.Status == 
corev1.ConditionFalse
+               switch integration.Status.Phase {
+               case v1.IntegrationPhaseRunning:
+                       deployUnavailable := false
+                       progressingFailing := false
+                       for _, c := range deployment.Status.Conditions {
+                               // first, check if the container status is not 
available
+                               if c.Type == appsv1.DeploymentAvailable {
+                                       deployUnavailable = c.Status == 
corev1.ConditionFalse
+                               }
+                               // second, check when it is progressing and 
reason is the replicas are available but the number of replicas are zero
+                               // in this case, the container integration is 
failing
+                               if c.Type == appsv1.DeploymentProgressing {
+                                       progressingFailing = c.Status == 
corev1.ConditionTrue && c.Reason == "NewReplicaSetAvailable" && 
deployment.Status.AvailableReplicas < 1
+                               }
                        }
-                       // second, check when it is progressing and reason is 
the replicas are available but the number of replicas are zero
-                       // in this case, the container integration is failing
-                       if c.Type == appsv1.DeploymentProgressing {
-                               progressingFailing = c.Status == 
corev1.ConditionTrue && c.Reason == "NewReplicaSetAvailable" && 
deployment.Status.AvailableReplicas < 1
+                       if deployUnavailable && progressingFailing {
+                               notAvailableCondition := 
v1.IntegrationCondition{
+                                       Type:    v1.IntegrationConditionReady,
+                                       Status:  corev1.ConditionFalse,
+                                       Reason:  
v1.IntegrationConditionErrorReason,
+                                       Message: "The corresponding pod(s) may 
be in error state, look at the pod status or log for errors",
+                               }
+                               
integration.Status.SetConditions(notAvailableCondition)
+                               integration.Status.Phase = 
v1.IntegrationPhaseError
+                               return integration, nil
                        }
-               }
-               if deployUnavailable && progressingFailing {
-                       notAvailableCondition := v1.IntegrationCondition{
-                               Type:   v1.IntegrationConditionReady, 
-                               Status: corev1.ConditionFalse,
-                               Reason: v1.IntegrationConditionErrorReason,
-                               Message: "The corresponding pod(s) may be in 
error state, look at the pod status or log for errors",
+
+               case v1.IntegrationPhaseError:
+                       // if the integration is in error phase, check if the 
corresponding pod is running ok, the user may have updated the integration.
+                       deployAvailable := false
+                       progressingOk := false
+                       for _, c := range deployment.Status.Conditions {
+                               // first, check if the container is in 
available state
+                               if c.Type == appsv1.DeploymentAvailable {
+                                       deployAvailable = c.Status == 
corev1.ConditionTrue
+                               }
+                               // second, check the progressing and the reasons
+                               if c.Type == appsv1.DeploymentProgressing {
+                                       progressingOk = c.Status == 
corev1.ConditionTrue && (c.Reason == "NewReplicaSetAvailable" || c.Reason == 
"ReplicaSetUpdated")
+                               }
+                       }
+                       if deployAvailable && progressingOk {
+                               availableCondition := v1.IntegrationCondition{
+                                       Type:   v1.IntegrationConditionReady,
+                                       Status: corev1.ConditionTrue,
+                                       Reason: 
v1.IntegrationConditionReplicaSetReadyReason,
+                               }
+                               
integration.Status.SetConditions(availableCondition)
+                               integration.Status.Phase = 
v1.IntegrationPhaseRunning
+                               return integration, nil
                        }
-                       integration.Status.SetConditions(notAvailableCondition)
-                       integration.Status.Phase = v1.IntegrationPhaseError
-                       return integration, nil
                }
        }
 
diff --git a/pkg/trait/affinity.go b/pkg/trait/affinity.go
index 330bd58..bd27846 100644
--- a/pkg/trait/affinity.go
+++ b/pkg/trait/affinity.go
@@ -68,7 +68,7 @@ func (t *affinityTrait) Configure(e *Environment) (bool, 
error) {
                return false, fmt.Errorf("both pod affinity and pod 
anti-affinity can't be set simultaneously")
        }
 
-       return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+       return e.IntegrationInRunningPhases(), nil
 }
 
 func (t *affinityTrait) Apply(e *Environment) (err error) {
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index a553410..4358ea2 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -22,7 +22,6 @@ import (
        "path"
        "sort"
 
-       "github.com/apache/camel-k/pkg/util/kubernetes"
        appsv1 "k8s.io/api/apps/v1"
        "k8s.io/api/batch/v1beta1"
        corev1 "k8s.io/api/core/v1"
@@ -34,6 +33,7 @@ import (
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util"
        "github.com/apache/camel-k/pkg/util/envvar"
+       "github.com/apache/camel-k/pkg/util/kubernetes"
 )
 
 const (
@@ -130,7 +130,7 @@ func (t *containerTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -157,16 +157,12 @@ func (t *containerTrait) Apply(e *Environment) error {
                if err := t.configureDependencies(e); err != nil {
                        return err
                }
+       } else {
+               return t.configureContainer(e)
        }
 
-       if e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
-               if err := t.configureImageIntegrationKit(e); err != nil {
-                       return err
-               }
-       }
-
-       if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
-               return t.configureContainer(e)
+       if err := t.configureImageIntegrationKit(e); err != nil {
+               return err
        }
 
        return nil
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index 45a325e..b851a79 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -125,7 +125,7 @@ func (t *cronTrait) Configure(e *Environment) (bool, error) 
{
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -234,7 +234,7 @@ func (t *cronTrait) Apply(e *Environment) error {
                }
        }
 
-       if IsNilOrFalse(t.Fallback) && 
e.IntegrationInPhase(v1.IntegrationPhaseDeploying) {
+       if IsNilOrFalse(t.Fallback) && e.IntegrationInRunningPhases() {
                if e.ApplicationProperties == nil {
                        e.ApplicationProperties = make(map[string]string)
                }
@@ -260,13 +260,8 @@ func (t *cronTrait) Apply(e *Environment) error {
 }
 
 func (t *cronTrait) getCronJobFor(e *Environment) *v1beta1.CronJob {
-       labels := map[string]string{
-               v1.IntegrationLabel: e.Integration.Name,
-       }
-
-       annotations := make(map[string]string)
-
        // Copy annotations from the integration resource
+       annotations := make(map[string]string)
        if e.Integration.Annotations != nil {
                for k, v := range 
filterTransferableAnnotations(e.Integration.Annotations) {
                        annotations[k] = v
@@ -279,9 +274,11 @@ func (t *cronTrait) getCronJobFor(e *Environment) 
*v1beta1.CronJob {
                        APIVersion: v1beta1.SchemeGroupVersion.String(),
                },
                ObjectMeta: metav1.ObjectMeta{
-                       Name:        e.Integration.Name,
-                       Namespace:   e.Integration.Namespace,
-                       Labels:      labels,
+                       Name:      e.Integration.Name,
+                       Namespace: e.Integration.Namespace,
+                       Labels: map[string]string{
+                               v1.IntegrationLabel: e.Integration.Name,
+                       },
                        Annotations: e.Integration.Annotations,
                },
                Spec: v1beta1.CronJobSpec{
@@ -292,7 +289,9 @@ func (t *cronTrait) getCronJobFor(e *Environment) 
*v1beta1.CronJob {
                                Spec: batchv1.JobSpec{
                                        Template: corev1.PodTemplateSpec{
                                                ObjectMeta: metav1.ObjectMeta{
-                                                       Labels:      labels,
+                                                       Labels: 
map[string]string{
+                                                               
v1.IntegrationLabel: e.Integration.Name,
+                                                       },
                                                        Annotations: 
annotations,
                                                },
                                                Spec: corev1.PodSpec{
diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go
index 301d7d0..ac9d2d8 100644
--- a/pkg/trait/deployer.go
+++ b/pkg/trait/deployer.go
@@ -29,7 +29,6 @@ import (
 
        ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util/patch"
 )
 
@@ -54,61 +53,37 @@ func newDeployerTrait() Trait {
 }
 
 func (t *deployerTrait) Configure(e *Environment) (bool, error) {
-       return e.IntegrationInPhase(
-               v1.IntegrationPhaseNone,
-               v1.IntegrationPhaseWaitingForBindings,
-               v1.IntegrationPhaseWaitingForPlatform,
-               v1.IntegrationPhaseInitialization,
-               v1.IntegrationPhaseBuildingKit,
-               v1.IntegrationPhaseResolvingKit,
-               v1.IntegrationPhaseDeploying,
-               v1.IntegrationPhaseRunning,
-       ), nil
+       return e.Integration != nil && IsNilOrTrue(t.Enabled), nil
 }
 
 func (t *deployerTrait) Apply(e *Environment) error {
-       switch e.Integration.Status.Phase {
-
-       case v1.IntegrationPhaseBuildingKit, v1.IntegrationPhaseResolvingKit:
-               if e.IntegrationKitInPhase(v1.IntegrationKitPhaseReady) {
-                       e.PostProcessors = append(e.PostProcessors, 
func(environment *Environment) error {
-                               // trigger integration deploy
-                               e.Integration.Status.Phase = 
v1.IntegrationPhaseDeploying
-                               return nil
-                       })
-               }
-
-       case v1.IntegrationPhaseNone, v1.IntegrationPhaseInitialization,
-               v1.IntegrationPhaseWaitingForPlatform, 
v1.IntegrationPhaseWaitingForBindings,
-               v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning:
-               // Register a post action that patches the resources generated 
by the traits
-               e.PostActions = append(e.PostActions, func(env *Environment) 
error {
-                       for _, resource := range env.Resources.Items() {
-                               // We assume that server-side apply is enabled 
by default.
-                               // It is currently convoluted to check 
pro-actively whether server-side apply
-                               // is enabled. This is possible to fetch the 
OpenAPI endpoint, which returns
-                               // the entire server API document, then lookup 
the resource PATCH endpoint, and
-                               // check its list of accepted MIME types.
-                               // As a simpler solution, we fallback to 
client-side apply at the first
-                               // 415 error, and assume server-side apply is 
not available globally.
-                               if hasServerSideApply {
-                                       if err := t.serverSideApply(env, 
resource); err == nil {
-                                               continue
-                                       } else if 
isIncompatibleServerError(err) {
-                                               t.L.Info("Fallback to 
client-side apply to patch resources")
-                                               hasServerSideApply = false
-                                       } else {
-                                               // Keep server-side apply 
unless server is incompatible with it
-                                               return err
-                                       }
-                               }
-                               if err := t.clientSideApply(env, resource); err 
!= nil {
+       // Register a post action that patches the resources generated by the 
traits
+       e.PostActions = append(e.PostActions, func(env *Environment) error {
+               for _, resource := range env.Resources.Items() {
+                       // We assume that server-side apply is enabled by 
default.
+                       // It is currently convoluted to check pro-actively 
whether server-side apply
+                       // is enabled. This is possible to fetch the OpenAPI 
endpoint, which returns
+                       // the entire server API document, then lookup the 
resource PATCH endpoint, and
+                       // check its list of accepted MIME types.
+                       // As a simpler solution, we fallback to client-side 
apply at the first
+                       // 415 error, and assume server-side apply is not 
available globally.
+                       if hasServerSideApply {
+                               if err := t.serverSideApply(env, resource); err 
== nil {
+                                       continue
+                               } else if isIncompatibleServerError(err) {
+                                       t.L.Info("Fallback to client-side apply 
to patch resources")
+                                       hasServerSideApply = false
+                               } else {
+                                       // Keep server-side apply unless server 
is incompatible with it
                                        return err
                                }
                        }
-                       return nil
-               })
-       }
+                       if err := t.clientSideApply(env, resource); err != nil {
+                               return err
+                       }
+               }
+               return nil
+       })
 
        return nil
 }
diff --git a/pkg/trait/deployer_test.go b/pkg/trait/deployer_test.go
index d5ffb97..58c8b73 100644
--- a/pkg/trait/deployer_test.go
+++ b/pkg/trait/deployer_test.go
@@ -42,7 +42,7 @@ func TestConfigureDeployerTraitInWrongPhaseDoesNotSucceed(t 
*testing.T) {
 
        configured, err := deployerTrait.Configure(environment)
 
-       assert.False(t, configured)
+       assert.True(t, configured)
        assert.Nil(t, err)
 }
 
@@ -65,16 +65,6 @@ func 
TestApplyDeployerTraitInInitializationPhaseDoesSucceed(t *testing.T) {
        assert.Len(t, environment.PostActions, 1)
 }
 
-func TestApplyDeployerTraitInResolvingKitPhaseSkipPostActions(t *testing.T) {
-       deployerTrait, environment := createNominalDeployerTest()
-       environment.Integration.Status.Phase = v1.IntegrationPhaseResolvingKit
-
-       err := deployerTrait.Apply(environment)
-
-       assert.Nil(t, err)
-       assert.Len(t, environment.PostActions, 0)
-}
-
 func createNominalDeployerTest() (*deployerTrait, *Environment) {
        trait := newDeployerTrait().(*deployerTrait)
 
diff --git a/pkg/trait/deployment.go b/pkg/trait/deployment.go
index cf788e7..34369fb 100644
--- a/pkg/trait/deployment.go
+++ b/pkg/trait/deployment.go
@@ -55,7 +55,7 @@ func (t *deploymentTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if e.IntegrationInPhase(v1.IntegrationPhaseRunning) {
+       if e.IntegrationInPhase(v1.IntegrationPhaseRunning, 
v1.IntegrationPhaseError) {
                condition := 
e.Integration.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable)
                return condition != nil && condition.Status == 
corev1.ConditionTrue, nil
        }
@@ -98,34 +98,18 @@ func (t *deploymentTrait) ControllerStrategySelectorOrder() 
int {
 }
 
 func (t *deploymentTrait) Apply(e *Environment) error {
-       if e.InPhase(v1.IntegrationKitPhaseReady, v1.IntegrationPhaseDeploying) 
||
-               e.InPhase(v1.IntegrationKitPhaseReady, 
v1.IntegrationPhaseRunning) {
-               maps := e.computeConfigMaps()
-               deployment := t.getDeploymentFor(e)
+       maps := e.computeConfigMaps()
+       deployment := t.getDeploymentFor(e)
 
-               e.Resources.AddAll(maps)
-               e.Resources.Add(deployment)
+       e.Resources.AddAll(maps)
+       e.Resources.Add(deployment)
 
-               e.Integration.Status.SetCondition(
-                       v1.IntegrationConditionDeploymentAvailable,
-                       corev1.ConditionTrue,
-                       v1.IntegrationConditionDeploymentAvailableReason,
-                       fmt.Sprintf("deployment name is %s", deployment.Name),
-               )
-
-               if e.IntegrationInPhase(v1.IntegrationPhaseRunning) {
-                       // Reconcile the deployment replicas
-                       replicas := e.Integration.Spec.Replicas
-                       // Deployment replicas defaults to 1, so we avoid 
forcing
-                       // an update to nil that will result to another update 
cycle
-                       // back to that default value by the Deployment 
controller.
-                       if replicas == nil {
-                               one := int32(1)
-                               replicas = &one
-                       }
-                       deployment.Spec.Replicas = replicas
-               }
-       }
+       e.Integration.Status.SetCondition(
+               v1.IntegrationConditionDeploymentAvailable,
+               corev1.ConditionTrue,
+               v1.IntegrationConditionDeploymentAvailableReason,
+               fmt.Sprintf("deployment name is %s", deployment.Name),
+       )
 
        return nil
 }
@@ -178,5 +162,16 @@ func (t *deploymentTrait) getDeploymentFor(e *Environment) 
*appsv1.Deployment {
                },
        }
 
+       // Reconcile the deployment replicas
+       replicas := e.Integration.Spec.Replicas
+       // Deployment replicas defaults to 1, so we avoid forcing
+       // an update to nil that will result to another update cycle
+       // back to that default value by the Deployment controller.
+       if replicas == nil {
+               one := int32(1)
+               replicas = &one
+       }
+       deployment.Spec.Replicas = replicas
+
        return &deployment
 }
diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go
index 6ea9e9b..ed5ee41 100644
--- a/pkg/trait/environment.go
+++ b/pkg/trait/environment.go
@@ -18,7 +18,6 @@ limitations under the License.
 package trait
 
 import (
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util/defaults"
        "github.com/apache/camel-k/pkg/util/envvar"
 )
@@ -59,7 +58,7 @@ func newEnvironmentTrait() Trait {
 
 func (t *environmentTrait) Configure(e *Environment) (bool, error) {
        if IsNilOrTrue(t.Enabled) {
-               return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+               return e.IntegrationInRunningPhases(), nil
        }
 
        return false, nil
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index dfb4799..571e4ec 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -21,9 +21,10 @@ import (
        "fmt"
        "strings"
 
+       "gopkg.in/yaml.v2"
+
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-       "gopkg.in/yaml.v2"
 )
 
 // The error-handler is a platform trait used to inject Error Handler source 
into the integration runtime.
@@ -52,7 +53,7 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -65,7 +66,7 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, 
error) {
 
 func (t *errorHandlerTrait) Apply(e *Environment) error {
        if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-               // If the user configure directly the URI, we need to 
autodiscover the underlying component
+               // If the user configure directly the URI, we need to 
auto-discover the underlying component
                // and add the related dependency
                defaultErrorHandlerURI := 
e.Integration.Spec.GetConfigurationProperty(
                        fmt.Sprintf("%s.deadLetterUri", 
v1alpha1.ErrorHandlerAppPropertiesPrefix))
diff --git a/pkg/trait/gc.go b/pkg/trait/gc.go
index 59210ea..92b61dd 100644
--- a/pkg/trait/gc.go
+++ b/pkg/trait/gc.go
@@ -82,17 +82,14 @@ func (t *garbageCollectorTrait) Configure(e *Environment) 
(bool, error) {
                t.DiscoveryCache = &s
        }
 
-       return e.IntegrationInPhase(
-                       v1.IntegrationPhaseInitialization,
-                       v1.IntegrationPhaseDeploying,
-                       v1.IntegrationPhaseRunning),
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization) || 
e.IntegrationInRunningPhases(),
                nil
 }
 
 func (t *garbageCollectorTrait) Apply(e *Environment) error {
        switch e.Integration.Status.Phase {
 
-       case v1.IntegrationPhaseRunning:
+       case v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning, 
v1.IntegrationPhaseError:
                // Register a post action that deletes the existing resources 
that are labelled
                // with the previous integration generations.
                // TODO: this should be refined so that it's run when all the 
replicas for the newer generation
diff --git a/pkg/trait/ingress.go b/pkg/trait/ingress.go
index dd0d565..24115fa 100644
--- a/pkg/trait/ingress.go
+++ b/pkg/trait/ingress.go
@@ -65,7 +65,7 @@ func (t *ingressTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInRunningPhases() {
                return false, nil
        }
 
diff --git a/pkg/trait/ingress_test.go b/pkg/trait/ingress_test.go
index a0fb217..923a639 100644
--- a/pkg/trait/ingress_test.go
+++ b/pkg/trait/ingress_test.go
@@ -60,7 +60,7 @@ func TestConfigureIngressTraitInWrongPhaseDoesNotSucceed(t 
*testing.T) {
 
        configured, err := ingressTrait.Configure(environment)
 
-       assert.False(t, configured)
+       assert.True(t, configured)
        assert.Nil(t, err)
        assert.Len(t, environment.Integration.Status.Conditions, 0)
 }
diff --git a/pkg/trait/init.go b/pkg/trait/init.go
index 466c24e..3cf8472 100644
--- a/pkg/trait/init.go
+++ b/pkg/trait/init.go
@@ -29,7 +29,6 @@ import (
 
 const flowsInternalSourceName = "camel-k-embedded-flow.yaml"
 
-// Internal trait
 type initTrait struct {
        BaseTrait `property:",squash"`
 }
@@ -45,54 +44,47 @@ func (t *initTrait) Configure(e *Environment) (bool, error) 
{
                return false, errors.New("trait init cannot be disabled")
        }
 
-       return true, nil
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization), nil
 }
 
 func (t *initTrait) Apply(e *Environment) error {
-       if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-
-               // Flows need to be turned into a generated source
-               if len(e.Integration.Spec.Flows) > 0 {
-                       content, err := dsl.ToYamlDSL(e.Integration.Spec.Flows)
-                       if err != nil {
-                               return err
-                       }
-                       
e.Integration.Status.AddOrReplaceGeneratedSources(v1.SourceSpec{
-                               DataSpec: v1.DataSpec{
-                                       Name:    flowsInternalSourceName,
-                                       Content: string(content),
-                               },
-                       })
+       // Flows need to be turned into a generated source
+       if len(e.Integration.Spec.Flows) > 0 {
+               content, err := dsl.ToYamlDSL(e.Integration.Spec.Flows)
+               if err != nil {
+                       return err
                }
+               e.Integration.Status.AddOrReplaceGeneratedSources(v1.SourceSpec{
+                       DataSpec: v1.DataSpec{
+                               Name:    flowsInternalSourceName,
+                               Content: string(content),
+                       },
+               })
+       }
 
-               //
-               // Dependencies need to be recomputed in case of a trait 
declares a capability but as
-               // the dependencies trait runs earlier than some task such as 
the cron one, we need to
-               // register a post step processor that recompute the 
dependencies based on the declared
-               // capabilities
-               //
-               e.PostStepProcessors = append(e.PostStepProcessors, 
func(environment *Environment) error {
-                       //
-                       // The camel catalog is set-up by the camel trait so it 
may not be available for
-                       // traits executed before that one
-                       //
-                       if e.CamelCatalog != nil {
-                               // add runtime specific dependencies
-                               for _, capability := range 
e.Integration.Status.Capabilities {
-                                       for _, dependency := range 
e.CamelCatalog.Runtime.CapabilityDependencies(capability) {
-                                               
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, 
dependency.GetDependencyID())
-                                       }
+       // Dependencies need to be recomputed in case of a trait declares a 
capability but as
+       // the dependencies trait runs earlier than some task such as the cron 
one, we need to
+       // register a post step processor that recompute the dependencies based 
on the declared
+       // capabilities.
+       e.PostStepProcessors = append(e.PostStepProcessors, func(environment 
*Environment) error {
+               // The camel catalog is set up by the camel trait, so it may 
not be available for
+               // traits executed before that one.
+               if e.CamelCatalog != nil {
+                       // add runtime specific dependencies
+                       for _, capability := range 
e.Integration.Status.Capabilities {
+                               for _, dependency := range 
e.CamelCatalog.Runtime.CapabilityDependencies(capability) {
+                                       
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, 
dependency.GetDependencyID())
                                }
                        }
+               }
 
-                       if e.Integration.Status.Dependencies != nil {
-                               // sort the dependencies to get always the same 
list if they don't change
-                               sort.Strings(e.Integration.Status.Dependencies)
-                       }
+               if e.Integration.Status.Dependencies != nil {
+                       // sort the dependencies to get always the same list if 
they don't change
+                       sort.Strings(e.Integration.Status.Dependencies)
+               }
 
-                       return nil
-               })
-       }
+               return nil
+       })
 
        return nil
 }
diff --git a/pkg/trait/istio.go b/pkg/trait/istio.go
index f6fc951..fd48559 100644
--- a/pkg/trait/istio.go
+++ b/pkg/trait/istio.go
@@ -23,11 +23,9 @@ import (
        appsv1 "k8s.io/api/apps/v1"
 
        servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-// The Istio trait allows to configure properties related to the Istio service 
mesh,
+// The Istio trait allows configuring properties related to the Istio service 
mesh,
 // such as sidecar injection and outbound IP ranges.
 //
 // +camel-k:trait=istio
@@ -53,7 +51,7 @@ func newIstioTrait() Trait {
 
 func (t *istioTrait) Configure(e *Environment) (bool, error) {
        if IsTrue(t.Enabled) {
-               return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+               return e.IntegrationInRunningPhases(), nil
        }
 
        return false, nil
diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go
index 9579d7c..ebfbb46 100644
--- a/pkg/trait/jolokia.go
+++ b/pkg/trait/jolokia.go
@@ -75,11 +75,11 @@ func newJolokiaTrait() Trait {
 }
 
 func (t *jolokiaTrait) Configure(e *Environment) (bool, error) {
-       return IsTrue(t.Enabled) && e.IntegrationInPhase(
-               v1.IntegrationPhaseInitialization,
-               v1.IntegrationPhaseDeploying,
-               v1.IntegrationPhaseRunning,
-       ), nil
+       if IsNilOrFalse(t.Enabled) {
+               return false, nil
+       }
+
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization) || 
e.IntegrationInRunningPhases(), nil
 }
 
 func (t *jolokiaTrait) Apply(e *Environment) (err error) {
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index b31bca6..a857e7d 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -71,8 +71,11 @@ func (t *jvmTrait) Configure(e *Environment) (bool, error) {
                return false, nil
        }
 
-       return e.InPhase(v1.IntegrationKitPhaseReady, 
v1.IntegrationPhaseDeploying) ||
-               e.InPhase(v1.IntegrationKitPhaseReady, 
v1.IntegrationPhaseRunning), nil
+       if !e.IntegrationKitInPhase(v1.IntegrationKitPhaseReady) || 
!e.IntegrationInRunningPhases() {
+               return false, nil
+       }
+
+       return true, nil
 }
 
 func (t *jvmTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index 343b25d..0eeb0f3 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -54,7 +54,7 @@ func 
TestConfigureJvmTraitInWrongIntegrationPhaseDoesNotSucceed(t *testing.T) {
 
        configured, err := trait.Configure(environment)
        assert.Nil(t, err)
-       assert.False(t, configured)
+       assert.True(t, configured)
 }
 
 func TestConfigureJvmTraitInWrongIntegrationKitPhaseDoesNotSucceed(t 
*testing.T) {
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 6b0b2a8..db68bf2 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -25,7 +25,8 @@ import (
        "strconv"
        "strings"
 
-       "github.com/apache/camel-k/pkg/util/source"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -37,8 +38,7 @@ import (
        "github.com/apache/camel-k/pkg/util/digest"
        "github.com/apache/camel-k/pkg/util/dsl"
        "github.com/apache/camel-k/pkg/util/kubernetes"
-       corev1 "k8s.io/api/core/v1"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "github.com/apache/camel-k/pkg/util/source"
 )
 
 // The kamelets trait is a platform trait used to inject Kamelets into the 
integration runtime.
@@ -92,7 +92,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -126,15 +126,14 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, 
error) {
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
-       if e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseRunning) {
+       if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) || 
e.IntegrationInRunningPhases() {
                if err := t.addKamelets(e); err != nil {
                        return err
                }
        }
-
        if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
                return t.addConfigurationSecrets(e)
-       } else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       } else if e.IntegrationInRunningPhases() {
                return t.configureApplicationProperties(e)
        }
 
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index a76ae57..30d214f 100644
--- a/pkg/trait/knative.go
+++ b/pkg/trait/knative.go
@@ -108,7 +108,7 @@ func (t *knativeTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -216,7 +216,7 @@ func (t *knativeTrait) Apply(e *Environment) error {
                util.StringSliceUniqueAdd(&e.Integration.Status.Capabilities, 
v1.CapabilityPlatformHTTP)
        }
 
-       if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       if e.IntegrationInRunningPhases() {
                env := knativeapi.NewCamelEnvironment()
                if t.Configuration != "" {
                        if err := env.Deserialize(t.Configuration); err != nil {
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index a86e7bd..c7a3186 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -102,7 +102,7 @@ func (t *knativeServiceTrait) Configure(e *Environment) 
(bool, error) {
                return false, nil
        }
 
-       if !e.InPhase(v1.IntegrationKitPhaseReady, 
v1.IntegrationPhaseDeploying) && 
!e.IntegrationInPhase(v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -161,7 +161,7 @@ func (t *knativeServiceTrait) Configure(e *Environment) 
(bool, error) {
                }
        }
 
-       if e.IntegrationInPhase(v1.IntegrationPhaseRunning) {
+       if e.IntegrationInPhase(v1.IntegrationPhaseRunning, 
v1.IntegrationPhaseError) {
                condition := 
e.Integration.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable)
                return condition != nil && condition.Status == 
corev1.ConditionTrue, nil
        }
@@ -170,7 +170,10 @@ func (t *knativeServiceTrait) Configure(e *Environment) 
(bool, error) {
 }
 
 func (t *knativeServiceTrait) Apply(e *Environment) error {
-       ksvc := t.getServiceFor(e)
+       ksvc, err := t.getServiceFor(e)
+       if err != nil {
+               return err
+       }
        maps := e.computeConfigMaps()
 
        e.Resources.AddAll(maps)
@@ -183,56 +186,6 @@ func (t *knativeServiceTrait) Apply(e *Environment) error {
                fmt.Sprintf("Knative service name is %s", ksvc.Name),
        )
 
-       if e.IntegrationInPhase(v1.IntegrationPhaseRunning) {
-               replicas := e.Integration.Spec.Replicas
-
-               isUpdateRequired := false
-               minScale, ok := 
ksvc.Spec.Template.Annotations[knativeServingMinScaleAnnotation]
-               if ok {
-                       min, err := strconv.Atoi(minScale)
-                       if err != nil {
-                               return err
-                       }
-                       if replicas == nil || min != int(*replicas) {
-                               isUpdateRequired = true
-                       }
-               } else if replicas != nil {
-                       isUpdateRequired = true
-               }
-
-               maxScale, ok := 
ksvc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation]
-               if ok {
-                       max, err := strconv.Atoi(maxScale)
-                       if err != nil {
-                               return err
-                       }
-                       if replicas == nil || max != int(*replicas) {
-                               isUpdateRequired = true
-                       }
-               } else if replicas != nil {
-                       isUpdateRequired = true
-               }
-
-               if isUpdateRequired {
-                       if replicas == nil {
-                               if t.MinScale != nil && *t.MinScale > 0 {
-                                       
ksvc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = 
strconv.Itoa(*t.MinScale)
-                               } else {
-                                       delete(ksvc.Spec.Template.Annotations, 
knativeServingMinScaleAnnotation)
-                               }
-                               if t.MaxScale != nil && *t.MaxScale > 0 {
-                                       
ksvc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = 
strconv.Itoa(*t.MaxScale)
-                               } else {
-                                       delete(ksvc.Spec.Template.Annotations, 
knativeServingMaxScaleAnnotation)
-                               }
-                       } else {
-                               scale := strconv.Itoa(int(*replicas))
-                               
ksvc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = scale
-                               
ksvc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = scale
-                       }
-               }
-       }
-
        return nil
 }
 
@@ -262,23 +215,16 @@ func (t *knativeServiceTrait) 
ControllerStrategySelectorOrder() int {
        return 100
 }
 
-func (t *knativeServiceTrait) getServiceFor(e *Environment) *serving.Service {
-       labels := map[string]string{
-               v1.IntegrationLabel: e.Integration.Name,
-       }
-
-       annotations := make(map[string]string)
-
+func (t *knativeServiceTrait) getServiceFor(e *Environment) (*serving.Service, 
error) {
        // Copy annotations from the integration resource
+       annotations := make(map[string]string)
        if e.Integration.Annotations != nil {
                for k, v := range 
filterTransferableAnnotations(e.Integration.Annotations) {
                        annotations[k] = v
                }
        }
 
-       //
-       // Set Knative Scaling behavior
-       //
+       // Set Knative auto-scaling behavior
        if t.Class != "" {
                annotations[knativeServingClassAnnotation] = t.Class
        }
@@ -301,16 +247,20 @@ func (t *knativeServiceTrait) getServiceFor(e 
*Environment) *serving.Service {
                        APIVersion: serving.SchemeGroupVersion.String(),
                },
                ObjectMeta: metav1.ObjectMeta{
-                       Name:        e.Integration.Name,
-                       Namespace:   e.Integration.Namespace,
-                       Labels:      labels,
+                       Name:      e.Integration.Name,
+                       Namespace: e.Integration.Namespace,
+                       Labels: map[string]string{
+                               v1.IntegrationLabel: e.Integration.Name,
+                       },
                        Annotations: e.Integration.Annotations,
                },
                Spec: serving.ServiceSpec{
                        ConfigurationSpec: serving.ConfigurationSpec{
                                Template: serving.RevisionTemplateSpec{
                                        ObjectMeta: metav1.ObjectMeta{
-                                               Labels:      labels,
+                                               Labels: map[string]string{
+                                                       v1.IntegrationLabel: 
e.Integration.Name,
+                                               },
                                                Annotations: annotations,
                                        },
                                        Spec: serving.RevisionSpec{
@@ -323,5 +273,53 @@ func (t *knativeServiceTrait) getServiceFor(e 
*Environment) *serving.Service {
                },
        }
 
-       return &svc
+       replicas := e.Integration.Spec.Replicas
+
+       isUpdateRequired := false
+       minScale, ok := 
svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation]
+       if ok {
+               min, err := strconv.Atoi(minScale)
+               if err != nil {
+                       return nil, err
+               }
+               if replicas == nil || min != int(*replicas) {
+                       isUpdateRequired = true
+               }
+       } else if replicas != nil {
+               isUpdateRequired = true
+       }
+
+       maxScale, ok := 
svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation]
+       if ok {
+               max, err := strconv.Atoi(maxScale)
+               if err != nil {
+                       return nil, err
+               }
+               if replicas == nil || max != int(*replicas) {
+                       isUpdateRequired = true
+               }
+       } else if replicas != nil {
+               isUpdateRequired = true
+       }
+
+       if isUpdateRequired {
+               if replicas == nil {
+                       if t.MinScale != nil && *t.MinScale > 0 {
+                               
svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = 
strconv.Itoa(*t.MinScale)
+                       } else {
+                               delete(svc.Spec.Template.Annotations, 
knativeServingMinScaleAnnotation)
+                       }
+                       if t.MaxScale != nil && *t.MaxScale > 0 {
+                               
svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = 
strconv.Itoa(*t.MaxScale)
+                       } else {
+                               delete(svc.Spec.Template.Annotations, 
knativeServingMaxScaleAnnotation)
+                       }
+               } else {
+                       scale := strconv.Itoa(int(*replicas))
+                       
svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = scale
+                       
svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = scale
+               }
+       }
+
+       return &svc, nil
 }
diff --git a/pkg/trait/logging.go b/pkg/trait/logging.go
index 0c97dcc..1f14e2c 100644
--- a/pkg/trait/logging.go
+++ b/pkg/trait/logging.go
@@ -18,7 +18,6 @@ limitations under the License.
 package trait
 
 import (
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util/envvar"
 )
 
@@ -61,7 +60,7 @@ func (l loggingTrait) Configure(environment *Environment) 
(bool, error) {
                return false, nil
        }
 
-       return environment.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+       return environment.IntegrationInRunningPhases(), nil
 }
 
 func (l loggingTrait) Apply(environment *Environment) error {
diff --git a/pkg/trait/owner.go b/pkg/trait/owner.go
index baf3b45..3a95b77 100644
--- a/pkg/trait/owner.go
+++ b/pkg/trait/owner.go
@@ -20,6 +20,7 @@ package trait
 import (
        appsv1 "k8s.io/api/apps/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
        serving "knative.dev/serving/pkg/apis/serving/v1"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
@@ -52,7 +53,7 @@ func (t *ownerTrait) Configure(e *Environment) (bool, error) {
                return false, nil
        }
 
-       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning), nil
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization) || 
e.IntegrationInRunningPhases(), nil
 }
 
 func (t *ownerTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/pdb.go b/pkg/trait/pdb.go
index f862dae..4a334c5 100644
--- a/pkg/trait/pdb.go
+++ b/pkg/trait/pdb.go
@@ -66,10 +66,7 @@ func (t *pdbTrait) Configure(e *Environment) (bool, error) {
                return false, fmt.Errorf("both minAvailable and maxUnavailable 
can't be set simultaneously")
        }
 
-       return e.IntegrationInPhase(
-               v1.IntegrationPhaseDeploying,
-               v1.IntegrationPhaseRunning,
-       ), nil
+       return e.IntegrationInRunningPhases(), nil
 }
 
 func (t *pdbTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/platform.go b/pkg/trait/platform.go
index 525d9cd..560de1c 100644
--- a/pkg/trait/platform.go
+++ b/pkg/trait/platform.go
@@ -18,10 +18,11 @@ limitations under the License.
 package trait
 
 import (
+       k8serrors "k8s.io/apimachinery/pkg/api/errors"
+
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/platform"
        "github.com/apache/camel-k/pkg/util/openshift"
-       k8serrors "k8s.io/apimachinery/pkg/api/errors"
 )
 
 // The platform trait is a base trait that is used to assign an integration 
platform to an integration.
diff --git a/pkg/trait/pod.go b/pkg/trait/pod.go
index e45edc0..8ce9aed 100644
--- a/pkg/trait/pod.go
+++ b/pkg/trait/pod.go
@@ -58,7 +58,7 @@ func (t *podTrait) Configure(e *Environment) (bool, error) {
                return false, nil
        }
 
-       return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+       return e.IntegrationInRunningPhases(), nil
 }
 
 func (t *podTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go
index bf192f6..6db5c51 100644
--- a/pkg/trait/prometheus.go
+++ b/pkg/trait/prometheus.go
@@ -57,11 +57,11 @@ func newPrometheusTrait() Trait {
 }
 
 func (t *prometheusTrait) Configure(e *Environment) (bool, error) {
-       return IsTrue(t.Enabled) && e.IntegrationInPhase(
-               v1.IntegrationPhaseInitialization,
-               v1.IntegrationPhaseDeploying,
-               v1.IntegrationPhaseRunning,
-       ), nil
+       if IsNilOrFalse(t.Enabled) {
+               return false, nil
+       }
+
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization) || 
e.IntegrationInRunningPhases(), nil
 }
 
 func (t *prometheusTrait) Apply(e *Environment) (err error) {
diff --git a/pkg/trait/pull_secret.go b/pkg/trait/pull_secret.go
index 005cdae..d7e9ee4 100644
--- a/pkg/trait/pull_secret.go
+++ b/pkg/trait/pull_secret.go
@@ -20,15 +20,17 @@ package trait
 import (
        "fmt"
 
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-       "github.com/apache/camel-k/pkg/platform"
-       "github.com/apache/camel-k/pkg/util/kubernetes"
-       "github.com/apache/camel-k/pkg/util/openshift"
        "github.com/pkg/errors"
+
        corev1 "k8s.io/api/core/v1"
        rbacv1 "k8s.io/api/rbac/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-       "sigs.k8s.io/controller-runtime/pkg/client"
+
+       ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+       "github.com/apache/camel-k/pkg/platform"
+       "github.com/apache/camel-k/pkg/util/kubernetes"
+       "github.com/apache/camel-k/pkg/util/openshift"
 )
 
 // The Pull Secret trait sets a pull secret on the pod,
@@ -64,7 +66,7 @@ func (t *pullSecretTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -72,7 +74,7 @@ func (t *pullSecretTrait) Configure(e *Environment) (bool, 
error) {
                if t.SecretName == "" {
                        secret := e.Platform.Status.Build.Registry.Secret
                        if secret != "" {
-                               key := client.ObjectKey{Namespace: 
e.Platform.Namespace, Name: secret}
+                               key := ctrl.ObjectKey{Namespace: 
e.Platform.Namespace, Name: secret}
                                obj := corev1.Secret{}
                                if err := t.Client.Get(t.Ctx, key, &obj); err 
!= nil {
                                        return false, err
@@ -119,7 +121,7 @@ func (t *pullSecretTrait) Apply(e *Environment) error {
 }
 
 func (t *pullSecretTrait) delegateImagePuller(e *Environment) error {
-       // Applying the rolebinding directly because it's a resource in the 
operator namespace
+       // Applying the RoleBinding directly because it's a resource in the 
operator namespace
        // (different from the integration namespace when delegation is 
enabled).
        rb := t.newImagePullerRoleBinding(e)
        if err := kubernetes.ReplaceResource(e.C, e.Client, rb); err != nil {
diff --git a/pkg/trait/route.go b/pkg/trait/route.go
index 20f0c43..3583ee9 100644
--- a/pkg/trait/route.go
+++ b/pkg/trait/route.go
@@ -120,7 +120,7 @@ func (t *routeTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInRunningPhases() {
                return false, nil
        }
 
@@ -278,9 +278,9 @@ func (t *routeTrait) readContentIfExists(secretName string) 
(string, error) {
        if len(key) > 0 {
                content := string(secret.Data[key])
                if len(content) == 0 {
-                       return "", fmt.Errorf("Could not find key %s in secret 
%s in namespace %s", key, secretName, t.service.Namespace)
+                       return "", fmt.Errorf("could not find key %s in secret 
%s in namespace %s", key, secretName, t.service.Namespace)
                }
                return content, nil
        }
        return "", nil
-}
\ No newline at end of file
+}
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index dc710e7..640445f 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -66,7 +66,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool, 
error) {
                return false, nil
        }
 
-       if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       if !e.IntegrationInRunningPhases() {
                return false, nil
        }
 
diff --git a/pkg/trait/service_binding.go b/pkg/trait/service_binding.go
index 5012050..421633a 100644
--- a/pkg/trait/service_binding.go
+++ b/pkg/trait/service_binding.go
@@ -20,16 +20,16 @@ package trait
 import (
        "fmt"
 
-       "github.com/apache/camel-k/pkg/util/reference"
        corev1 "k8s.io/api/core/v1"
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
-       k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
+       ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
        sb "github.com/redhat-developer/service-binding-operator/api/v1alpha1"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/pkg/util/reference"
 )
 
 // The Service Binding trait allows users to connect to Provisioned Services 
and ServiceBindings in Kubernetes:
@@ -57,12 +57,8 @@ func (t *serviceBindingTrait) Configure(e *Environment) 
(bool, error) {
                return false, nil
        }
 
-       return e.IntegrationInPhase(
-               v1.IntegrationPhaseInitialization,
-               v1.IntegrationPhaseWaitingForBindings,
-               v1.IntegrationPhaseDeploying,
-               v1.IntegrationPhaseRunning,
-       ), nil
+       return e.IntegrationInPhase(v1.IntegrationPhaseInitialization, 
v1.IntegrationPhaseWaitingForBindings) ||
+               e.IntegrationInRunningPhases(), nil
 }
 
 func (t *serviceBindingTrait) Apply(e *Environment) error {
@@ -121,7 +117,7 @@ func (t *serviceBindingTrait) Apply(e *Environment) error {
                                e.Resources.Add(&request)
                        }
                }
-       } else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning) {
+       } else if e.IntegrationInRunningPhases() {
                e.ServiceBindings = make(map[string]string)
                for _, name := range serviceBindings {
                        sb, err := t.getServiceBinding(e, name)
@@ -168,7 +164,7 @@ func isCollectionReady(sb sb.ServiceBinding) bool {
 
 func (t *serviceBindingTrait) getServiceBinding(e *Environment, name string) 
(sb.ServiceBinding, error) {
        serviceBinding := sb.ServiceBinding{}
-       key := k8sclient.ObjectKey{
+       key := ctrl.ObjectKey{
                Namespace: e.Integration.Namespace,
                Name:      name,
        }
diff --git a/pkg/trait/toleration.go b/pkg/trait/toleration.go
index add1428..dc5c1cb 100644
--- a/pkg/trait/toleration.go
+++ b/pkg/trait/toleration.go
@@ -22,7 +22,6 @@ import (
 
        corev1 "k8s.io/api/core/v1"
 
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util/kubernetes"
 )
 
@@ -61,7 +60,7 @@ func (t *tolerationTrait) Configure(e *Environment) (bool, 
error) {
                return false, fmt.Errorf("no taint was provided")
        }
 
-       return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning), nil
+       return e.IntegrationInRunningPhases(), nil
 }
 
 func (t *tolerationTrait) Apply(e *Environment) (err error) {
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index fc6d0f0..89ec86b 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -246,7 +246,10 @@ func (e *Environment) IntegrationInPhase(phases 
...v1.IntegrationPhase) bool {
        return false
 }
 
-// IntegrationKitInPhase --
+func (e *Environment) IntegrationInRunningPhases() bool {
+       return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, 
v1.IntegrationPhaseRunning, v1.IntegrationPhaseError)
+}
+
 func (e *Environment) IntegrationKitInPhase(phases ...v1.IntegrationKitPhase) 
bool {
        if e.IntegrationKit == nil {
                return false

Reply via email to