Skip to content

Commit

Permalink
feat: tracking method for annotations should be in another format (ar…
Browse files Browse the repository at this point in the history
…goproj#7316)

feat: tracking method for annotations should be in another format (argoproj#7316)

Signed-off-by: pashavictorovich <[email protected]>
  • Loading branch information
pasha-codefresh authored Sep 29, 2021
1 parent 20313ad commit 0d68194
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 10 deletions.
2 changes: 1 addition & 1 deletion reposerver/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ func GenerateManifests(appPath, repoRoot, revision string, q *apiclient.Manifest

for _, target := range targets {
if q.AppLabelKey != "" && q.AppName != "" && !kube.IsCRD(target) {
err = resourceTracking.SetAppInstance(target, q.AppLabelKey, q.AppName, v1alpha1.TrackingMethod(q.TrackingMethod))
err = resourceTracking.SetAppInstance(target, q.AppLabelKey, q.AppName, q.Namespace, v1alpha1.TrackingMethod(q.TrackingMethod))
if err != nil {
return nil, err
}
Expand Down
9 changes: 6 additions & 3 deletions test/e2e/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func TestDeploymentWithAnnotationTrackingMode(t *testing.T) {
out, err := RunCli("app", "manifests", app.Name)
assert.NoError(t, err)
assert.Contains(t, out, fmt.Sprintf(`annotations:
app.kubernetes.io/instance: %s`, Name()))
app.kubernetes.io/instance: %s;apps/Deployment/%s/nginx-deployment
`, Name(), DeploymentNamespace()))
})
}

Expand All @@ -80,7 +81,8 @@ func TestDeploymentWithLabelTrackingMode(t *testing.T) {
assert.NoError(t, err)
assert.Contains(t, out, fmt.Sprintf(`labels:
app: nginx
app.kubernetes.io/instance: %s`, Name()))
app.kubernetes.io/instance: %s
`, Name()))
})
}

Expand All @@ -101,6 +103,7 @@ func TestDeploymentWithoutTrackingMode(t *testing.T) {
assert.NoError(t, err)
assert.Contains(t, out, fmt.Sprintf(`labels:
app: nginx
app.kubernetes.io/instance: %s`, Name()))
app.kubernetes.io/instance: %s
`, Name()))
})
}
65 changes: 61 additions & 4 deletions util/argo/resource_tracking.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package argo

import (
"fmt"
"strings"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"github.com/argoproj/argo-cd/v2/util/settings"
Expand All @@ -16,10 +19,23 @@ const (
TrackingMethodAnnotationAndLabel v1alpha1.TrackingMethod = "annotation+label"
)

var WrongResourceTrackingFormat = fmt.Errorf("wrong resource tracking format, should be <application-name>;<group>/<kind>/<namespace>/<name>")

// ResourceTracking defines methods which allow setup and retrieve tracking information to resource
type ResourceTracking interface {
GetAppName(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod) string
SetAppInstance(un *unstructured.Unstructured, key, val string, trackingMethod v1alpha1.TrackingMethod) error
SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod) error
BuildAppInstanceValue(value AppInstanceValue) string
ParseAppInstanceValue(value string) (*AppInstanceValue, error)
}

//AppInstanceValue store information about resource tracking info
type AppInstanceValue struct {
ApplicationName string
Group string
Kind string
Namespace string
Name string
}

type resourceTracking struct {
Expand All @@ -44,20 +60,61 @@ func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string
case TrackingMethodLabel:
return argokube.GetAppInstanceLabel(un, key)
case TrackingMethodAnnotation:
return argokube.GetAppInstanceAnnotation(un, key)
appInstanceAnnotation := argokube.GetAppInstanceAnnotation(un, key)
value, err := rt.ParseAppInstanceValue(appInstanceAnnotation)
if err != nil {
return ""
}
return value.ApplicationName
default:
return argokube.GetAppInstanceLabel(un, key)
}
}

// SetAppInstance set label/annotation base on tracking method
func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, val string, trackingMethod v1alpha1.TrackingMethod) error {
func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod) error {
switch trackingMethod {
case TrackingMethodLabel:
return argokube.SetAppInstanceLabel(un, key, val)
case TrackingMethodAnnotation:
return argokube.SetAppInstanceAnnotation(un, key, val)
ns := un.GetNamespace()
if ns == "" {
ns = namespace
}
gvk := un.GetObjectKind().GroupVersionKind()
appInstanceValue := AppInstanceValue{
ApplicationName: val,
Group: gvk.Group,
Kind: gvk.Kind,
Namespace: ns,
Name: un.GetName(),
}
return argokube.SetAppInstanceAnnotation(un, key, rt.BuildAppInstanceValue(appInstanceValue))
default:
return argokube.SetAppInstanceLabel(un, key, val)
}
}

//BuildAppInstanceValue build resource tracking id in format <application-name>;<group>/<kind>/<namespace>/<name>
func (rt *resourceTracking) BuildAppInstanceValue(value AppInstanceValue) string {
return fmt.Sprintf("%s;%s/%s/%s/%s", value.ApplicationName, value.Group, value.Kind, value.Namespace, value.Name)
}

//ParseAppInstanceValue parse resource tracking id from format <application-name>;<group>/<kind>/<namespace>/<name> to struct
func (rt *resourceTracking) ParseAppInstanceValue(value string) (*AppInstanceValue, error) {
var appInstanceValue AppInstanceValue
parts := strings.Split(value, ";")
appInstanceValue.ApplicationName = parts[0]
if len(parts) == 1 {
return nil, WrongResourceTrackingFormat
}
newParts := strings.Split(parts[1], "/")
if len(newParts) != 4 {
return nil, WrongResourceTrackingFormat
}
appInstanceValue.Group = newParts[0]
appInstanceValue.Kind = newParts[1]
appInstanceValue.Namespace = newParts[2]
appInstanceValue.Name = newParts[3]
return &appInstanceValue, nil
}
27 changes: 25 additions & 2 deletions util/argo/resource_tracking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestSetAppInstanceLabel(t *testing.T) {

resourceTracking := NewResourceTracking()

err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", TrackingMethodLabel)
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel)
assert.Nil(t, err)

app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodLabel)
Expand All @@ -38,7 +38,7 @@ func TestSetAppInstanceAnnotation(t *testing.T) {

resourceTracking := NewResourceTracking()

err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", TrackingMethodAnnotation)
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodAnnotation)
assert.Nil(t, err)

app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotation)
Expand All @@ -58,3 +58,26 @@ func TestSetAppInstanceAnnotationNotFound(t *testing.T) {
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotation)
assert.Equal(t, "", app)
}

func TestParseAppInstanceValue(t *testing.T) {
resourceTracking := NewResourceTracking()
appInstanceValue, err := resourceTracking.ParseAppInstanceValue("app;<group>/<kind>/<namespace>/<name>")
assert.NoError(t, err)
assert.Equal(t, appInstanceValue.ApplicationName, "app")
assert.Equal(t, appInstanceValue.Group, "<group>")
assert.Equal(t, appInstanceValue.Kind, "<kind>")
assert.Equal(t, appInstanceValue.Namespace, "<namespace>")
assert.Equal(t, appInstanceValue.Name, "<name>")
}

func TestParseAppInstanceValueWrongFormat1(t *testing.T) {
resourceTracking := NewResourceTracking()
_, err := resourceTracking.ParseAppInstanceValue("app")
assert.Error(t, err, WrongResourceTrackingFormat)
}

func TestParseAppInstanceValueWrongFormat2(t *testing.T) {
resourceTracking := NewResourceTracking()
_, err := resourceTracking.ParseAppInstanceValue("app;group/kind/ns")
assert.Error(t, err, WrongResourceTrackingFormat)
}

0 comments on commit 0d68194

Please sign in to comment.