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