Skip to content

Commit

Permalink
fix(operator): look up latest AppVersion based on creation timestamp (#…
Browse files Browse the repository at this point in the history
…1186)

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
  • Loading branch information
bacherfl committed Apr 6, 2023
1 parent c164595 commit 45a96e7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 72 deletions.
26 changes: 7 additions & 19 deletions operator/controllers/lifecycle/keptnworkloadinstance/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"time"

"github.com/go-logr/logr"
version "github.com/hashicorp/go-version"
klcv1alpha3 "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha3"
apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha3/common"
controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common"
Expand Down Expand Up @@ -318,19 +317,16 @@ func (r *KeptnWorkloadInstanceReconciler) getTracer() controllercommon.ITracer {

func getLatestAppVersion(apps *klcv1alpha3.KeptnAppVersionList, wli *klcv1alpha3.KeptnWorkloadInstance) (bool, klcv1alpha3.KeptnAppVersion, error) {
latestVersion := klcv1alpha3.KeptnAppVersion{}
// ignore the potential error since this can not return an error with 0.0.0
oldVersion, _ := version.NewVersion("0.0.0")
var err error

workloadFound := false
for _, app := range apps.Items {
if app.Spec.AppName == wli.Spec.AppName {
for _, appWorkload := range app.Spec.Workloads {
if workloadMatchesApp(appWorkload, wli, app) {
workloadFound = true
latestVersion, oldVersion, err = setupLatestVersion(appWorkload, wli, app, latestVersion, oldVersion)
if err != nil {
return false, klcv1alpha3.KeptnAppVersion{}, err

if isNewer(app, latestVersion) {
latestVersion = app
}
}
}
Expand All @@ -339,18 +335,10 @@ func getLatestAppVersion(apps *klcv1alpha3.KeptnAppVersionList, wli *klcv1alpha3
return workloadFound, latestVersion, nil
}

func workloadMatchesApp(appWorkload klcv1alpha3.KeptnWorkloadRef, wli *klcv1alpha3.KeptnWorkloadInstance, app klcv1alpha3.KeptnAppVersion) bool {
return appWorkload.Version == wli.Spec.Version && app.GetWorkloadNameOfApp(appWorkload.Name) == wli.Spec.WorkloadName
func isNewer(app klcv1alpha3.KeptnAppVersion, latestVersion klcv1alpha3.KeptnAppVersion) bool {
return app.ObjectMeta.CreationTimestamp.Time.After(latestVersion.ObjectMeta.CreationTimestamp.Time) || latestVersion.CreationTimestamp.Time.IsZero()
}

func setupLatestVersion(appWorkload klcv1alpha3.KeptnWorkloadRef, wli *klcv1alpha3.KeptnWorkloadInstance, app klcv1alpha3.KeptnAppVersion, latestVersion klcv1alpha3.KeptnAppVersion, oldVersion *version.Version) (klcv1alpha3.KeptnAppVersion, *version.Version, error) {
newVersion, err := version.NewVersion(app.Spec.Version)
if err != nil {
return latestVersion, oldVersion, err
}
if newVersion.GreaterThan(oldVersion) {
return app, newVersion, nil
}

return latestVersion, oldVersion, nil
func workloadMatchesApp(appWorkload klcv1alpha3.KeptnWorkloadRef, wli *klcv1alpha3.KeptnWorkloadInstance, app klcv1alpha3.KeptnAppVersion) bool {
return appWorkload.Version == wli.Spec.Version && app.GetWorkloadNameOfApp(appWorkload.Name) == wli.Spec.WorkloadName
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"testing"
"time"

klcv1alpha3 "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha3"
apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha3/common"
Expand Down Expand Up @@ -364,6 +365,7 @@ func makeDaemonSet(name string, namespace string, wanted int32, available int32)
}

func Test_getAppVersionForWorkloadInstance(t *testing.T) {
now := time.Now()
tests := []struct {
name string
wli *klcv1alpha3.KeptnWorkloadInstance
Expand Down Expand Up @@ -411,8 +413,9 @@ func Test_getAppVersionForWorkloadInstance(t *testing.T) {
Items: []klcv1alpha3.KeptnAppVersion{
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
Namespace: "default",
Name: "my-app",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: now},
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Expand All @@ -429,8 +432,9 @@ func Test_getAppVersionForWorkloadInstance(t *testing.T) {
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app2",
Namespace: "default",
Name: "my-app2",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: now.Add(5 * time.Second)},
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Expand Down Expand Up @@ -605,12 +609,19 @@ func Test_getAppVersionForWorkloadInstance(t *testing.T) {
found, gotAppVersion, err := r.getAppVersionForWorkloadInstance(context.TODO(), tt.wli)
require.Equal(t, tt.wantErr, err != nil)
require.Equal(t, tt.wantFound, found)
if tt.wantFound {
// set the creation timestamp of the returned appVersion to the time zero value because this is
// set internally by the fake client
gotAppVersion.ObjectMeta.CreationTimestamp = metav1.Time{Time: time.Time{}}
}
require.Equal(t, tt.wantAppVersion, gotAppVersion)
})
}
}

func Test_getLatestAppVersion(t *testing.T) {

now := time.Now()
type args struct {
apps *klcv1alpha3.KeptnAppVersionList
wli *klcv1alpha3.KeptnWorkloadInstance
Expand All @@ -629,8 +640,9 @@ func Test_getLatestAppVersion(t *testing.T) {
Items: []klcv1alpha3.KeptnAppVersion{
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
Namespace: "default",
Name: "my-app",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: now},
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Expand All @@ -647,8 +659,9 @@ func Test_getLatestAppVersion(t *testing.T) {
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
Namespace: "default",
Name: "my-app",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: now.Add(5 * time.Second)},
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Expand Down Expand Up @@ -682,8 +695,9 @@ func Test_getLatestAppVersion(t *testing.T) {
wantFound: true,
wantAppVersion: klcv1alpha3.KeptnAppVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
Namespace: "default",
Name: "my-app",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: now.Add(5 * time.Second)},
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Expand Down Expand Up @@ -743,49 +757,6 @@ func Test_getLatestAppVersion(t *testing.T) {
wantAppVersion: klcv1alpha3.KeptnAppVersion{},
wantErr: false,
},
{
name: "app version with invalid version",
args: args{
apps: &klcv1alpha3.KeptnAppVersionList{
Items: []klcv1alpha3.KeptnAppVersion{
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
Namespace: "default",
},
Spec: klcv1alpha3.KeptnAppVersionSpec{
KeptnAppSpec: klcv1alpha3.KeptnAppSpec{
Version: "",
Workloads: []klcv1alpha3.KeptnWorkloadRef{
{
Name: "my-workload",
Version: "1.0",
},
},
},
AppName: "my-app",
},
},
},
},
wli: &klcv1alpha3.KeptnWorkloadInstance{
ObjectMeta: metav1.ObjectMeta{
Name: "my-workloadinstance",
Namespace: "default",
},
Spec: klcv1alpha3.KeptnWorkloadInstanceSpec{
KeptnWorkloadSpec: klcv1alpha3.KeptnWorkloadSpec{
AppName: "my-app",
Version: "1.0",
},
WorkloadName: "my-app-my-workload",
},
},
},
wantFound: false,
wantAppVersion: klcv1alpha3.KeptnAppVersion{},
wantErr: true,
},
{
name: "app version list empty",
args: args{
Expand Down

0 comments on commit 45a96e7

Please sign in to comment.