From 23fbce44214e57d970c7e927505e23caa0b05834 Mon Sep 17 00:00:00 2001 From: Giovanni Liva Date: Mon, 24 Oct 2022 09:01:49 +0200 Subject: [PATCH] fix(operator): Fixed starting deployments, when no corresponding app-version is available (#210) Signed-off-by: Moritz Wiesinger --- examples/podtatohead-deployment/app.yaml | 2 +- .../keptnworkloadinstance/controller.go | 47 +++++++++++++++---- operator/go.mod | 1 + operator/go.sum | 1 + 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/examples/podtatohead-deployment/app.yaml b/examples/podtatohead-deployment/app.yaml index 42c56ecd720..fd4a26260f2 100644 --- a/examples/podtatohead-deployment/app.yaml +++ b/examples/podtatohead-deployment/app.yaml @@ -14,7 +14,7 @@ spec: version: 0.2.7 - name: podtato-head-right-arm version: 0.1.0 - - name: podtato-head-left-arm + - name: podtato-head-right-leg version: 0.2.7 - name: podtato-head-hat version: 0.1.0 diff --git a/operator/controllers/keptnworkloadinstance/controller.go b/operator/controllers/keptnworkloadinstance/controller.go index 3047e2fcb86..928e3854981 100644 --- a/operator/controllers/keptnworkloadinstance/controller.go +++ b/operator/controllers/keptnworkloadinstance/controller.go @@ -19,6 +19,7 @@ package keptnworkloadinstance import ( "context" "fmt" + "golang.org/x/mod/semver" "time" "github.com/keptn-sandbox/lifecycle-controller/operator/api/v1alpha1/semconv" @@ -101,15 +102,15 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr //Wait for pre-evaluation checks of App phase := common.PhaseAppPreEvaluation - appVersion, err := r.getAppVersion(ctx, types.NamespacedName{Namespace: req.Namespace, Name: workloadInstance.Spec.AppName}) - if errors.IsNotFound(err) { - r.recordEvent(phase, "Warning", workloadInstance, "AppVersionNotFound", "has failed since app could not be found") - r.Log.Error(err, "Related App Version not found") - return reconcile.Result{Requeue: true, RequeueAfter: 20 * time.Second}, nil - } else if err != nil { + found, appVersion, err := r.getAppVersionForWorkloadInstance(ctx, workloadInstance) + if err != nil { + span.SetStatus(codes.Error, err.Error()) r.recordEvent(phase, "Warning", workloadInstance, "GetAppVersionFailed", "has failed since app could not be retrieved") - r.Log.Error(err, "Could not retrieve App Version") - return reconcile.Result{}, fmt.Errorf("could not fetch AppVersion: %+v", err) + return reconcile.Result{Requeue: true, RequeueAfter: 10 * time.Second}, fmt.Errorf("could not fetch AppVersion for KeptnWorkloadInstance: %+v", err) + } else if !found { + span.SetStatus(codes.Error, err.Error()) + r.recordEvent(phase, "Warning", workloadInstance, "AppVersionNotFound", "has failed since app could not be found") + return reconcile.Result{Requeue: true, RequeueAfter: 10 * time.Second}, fmt.Errorf("could not find AppVersion for KeptnWorkloadInstance") } appPreEvalStatus := appVersion.Status.PreDeploymentEvaluationStatus @@ -276,3 +277,33 @@ func (r *KeptnWorkloadInstanceReconciler) getAppVersion(ctx context.Context, app err = r.Get(ctx, GetAppVersionName(appName.Namespace, appName.Name, app.Spec.Version), appVersion) return appVersion, err } + +func (r *KeptnWorkloadInstanceReconciler) getAppVersionForWorkloadInstance(ctx context.Context, wli *klcv1alpha1.KeptnWorkloadInstance) (bool, klcv1alpha1.KeptnAppVersion, error) { + apps := &klcv1alpha1.KeptnAppVersionList{} + if err := r.Client.List(ctx, apps, client.InNamespace(wli.Namespace)); err != nil { + return false, klcv1alpha1.KeptnAppVersion{}, err + } + latestVersion := klcv1alpha1.KeptnAppVersion{} + for _, app := range apps.Items { + if app.Spec.AppName == wli.Spec.AppName { + for _, appWorkload := range app.Spec.Workloads { + workloadName := fmt.Sprintf("%s-%s", app.Spec.AppName, appWorkload.Name) + if appWorkload.Version == wli.Spec.Version && workloadName == wli.Spec.WorkloadName { + if latestVersion.Spec.Version == "" { + latestVersion = app + } else { + if semver.Compare(latestVersion.Spec.Version, app.Spec.Version) < 0 { + latestVersion = app + } + } + } + } + } + } + + r.Log.Info("Selected Version " + latestVersion.Spec.Version + " for KeptnApp " + wli.Spec.AppName) + if latestVersion.Spec.Version == "" { + return false, klcv1alpha1.KeptnAppVersion{}, nil + } + return true, latestVersion, nil +} diff --git a/operator/go.mod b/operator/go.mod index 55a96d94bcd..59c9dd8e477 100644 --- a/operator/go.mod +++ b/operator/go.mod @@ -20,6 +20,7 @@ require ( go.opentelemetry.io/otel/sdk v1.10.0 go.opentelemetry.io/otel/sdk/metric v0.32.1 go.opentelemetry.io/otel/trace v1.10.0 + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 google.golang.org/grpc v1.46.2 k8s.io/api v0.24.2 k8s.io/apimachinery v0.24.2 diff --git a/operator/go.sum b/operator/go.sum index 3e85c558450..ba6e9e9da05 100644 --- a/operator/go.sum +++ b/operator/go.sum @@ -608,6 +608,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=