Skip to content

Commit

Permalink
fix: app names with non-alphanumeric characters in position 63 break …
Browse files Browse the repository at this point in the history
…syncs (issue #18237) (#18256)

* Ensure truncated app label does not end in a special character

Signed-off-by: Zack Robinson <robinsoz@arcesium.com>

* Move regex to global variable and add out of bounds check

Signed-off-by: Zack Robinson <robinsoz@arcesium.com>

* Add test for out-of-bounds check

Signed-off-by: Zack Robinson <robinsoz@arcesium.com>

---------

Signed-off-by: Zack Robinson <robinsoz@arcesium.com>
  • Loading branch information
RobinsonZ committed May 22, 2024
1 parent 4606476 commit 59ce337
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
11 changes: 11 additions & 0 deletions util/argo/resource_tracking.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package argo

import (
"errors"
"fmt"
"regexp"
"strings"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand All @@ -21,6 +23,7 @@ const (

var WrongResourceTrackingFormat = fmt.Errorf("wrong resource tracking format, should be <application-name>:<group>/<kind>:<namespace>/<name>")
var LabelMaxLength = 63
var OkEndPattern = regexp.MustCompile("[a-zA-Z0-9]$")

// ResourceTracking defines methods which allow setup and retrieve tracking information to resource
type ResourceTracking interface {
Expand Down Expand Up @@ -155,6 +158,14 @@ func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, v
}
if len(val) > LabelMaxLength {
val = val[:LabelMaxLength]
// Prevent errors if the truncated name ends in a special character.
// See https://github.com/argoproj/argo-cd/issues/18237.
for !OkEndPattern.MatchString(val) {
if len(val) <= 1 {
return errors.New("failed to set app instance label: unable to truncate label to not end with a special character")
}
val = val[:len(val)-1]
}
}
err = argokube.SetAppInstanceLabel(un, key, val)
if err != nil {
Expand Down
54 changes: 54 additions & 0 deletions util/argo/resource_tracking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,60 @@ func TestSetAppInstanceAnnotationAndLabel(t *testing.T) {
assert.Equal(t, "my-app", app)
}

func TestSetAppInstanceAnnotationAndLabelLongName(t *testing.T) {
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
assert.Nil(t, err)
var obj unstructured.Unstructured
err = yaml.Unmarshal(yamlBytes, &obj)
assert.Nil(t, err)

resourceTracking := NewResourceTracking()

err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", TrackingMethodAnnotationAndLabel)
assert.Nil(t, err)

// the annotation should still work, so the name from GetAppName should not be truncated
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel)
assert.Equal(t, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", app)

// the label should be truncated to 63 characters
assert.Equal(t, obj.GetLabels()[common.LabelKeyAppInstance], "my-app-with-an-extremely-long-name-that-is-over-sixty-three-cha")
}

func TestSetAppInstanceAnnotationAndLabelLongNameBadEnding(t *testing.T) {
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
assert.Nil(t, err)
var obj unstructured.Unstructured
err = yaml.Unmarshal(yamlBytes, &obj)
assert.Nil(t, err)

resourceTracking := NewResourceTracking()

err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", TrackingMethodAnnotationAndLabel)
assert.Nil(t, err)

// the annotation should still work, so the name from GetAppName should not be truncated
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel)
assert.Equal(t, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", app)

// the label should be truncated to 63 characters, AND the hyphen should be removed
assert.Equal(t, obj.GetLabels()[common.LabelKeyAppInstance], "the-very-suspicious-name-with-precisely-sixty-three-characters")
}

func TestSetAppInstanceAnnotationAndLabelOutOfBounds(t *testing.T) {
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
assert.Nil(t, err)
var obj unstructured.Unstructured
err = yaml.Unmarshal(yamlBytes, &obj)
assert.Nil(t, err)

resourceTracking := NewResourceTracking()

err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", TrackingMethodAnnotationAndLabel)
// this should error because it can't truncate to a valid value
assert.EqualError(t, err, "failed to set app instance label: unable to truncate label to not end with a special character")
}

func TestSetAppInstanceAnnotationNotFound(t *testing.T) {
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
assert.Nil(t, err)
Expand Down

0 comments on commit 59ce337

Please sign in to comment.