From 75340a82b47b8c5080a0f30c639d9c4bf8309b9a Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:40:50 -0500 Subject: [PATCH] fix: truncate agent pod annotation so scheduler doesn't fail when annoation limit is exceeded (#3314) Signed-off-by: Austin Abro --- src/internal/agent/hooks/pods.go | 23 +++++++++++---- src/internal/agent/hooks/pods_test.go | 28 +++++++++++++++++++ .../packages/36-health-checks/ready-pod.yaml | 2 +- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/internal/agent/hooks/pods.go b/src/internal/agent/hooks/pods.go index 1ee02f899a..428b5fe9b7 100644 --- a/src/internal/agent/hooks/pods.go +++ b/src/internal/agent/hooks/pods.go @@ -8,6 +8,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/zarf-dev/zarf/src/config" "github.com/zarf-dev/zarf/src/config/lang" @@ -42,8 +43,20 @@ func parsePod(object []byte) (*corev1.Pod, error) { return &pod, nil } -func getImageAnnotationKey(containerName string) string { - return fmt.Sprintf("%s/original-image-%s", annotationPrefix, containerName) +func getImageAnnotationKey(ctx context.Context, containerName string) string { + annotationName := fmt.Sprintf("original-image-%s", containerName) + // The name segment is required and must be 63 characters or less, beginning and ending with + // an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between. + // https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set + if len(annotationName) > 63 { + logger.From(ctx).Debug("truncating container name to fit Kubernetes 63 character annotation name limit", "container", containerName) + annotationName = annotationName[:63] + } + // container names follow RFC 1123 which allows only lowercase alphanumeric characters and hyphens + // this ensures we don't end with a hyphen + annotationName = strings.TrimRight(annotationName, "-") + key := fmt.Sprintf("%s/%s", annotationPrefix, annotationName) + return key } func mutatePod(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Cluster) (*operations.Result, error) { @@ -88,7 +101,7 @@ func mutatePod(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Clu if err != nil { return nil, err } - updatedAnnotations[getImageAnnotationKey(container.Name)] = container.Image + updatedAnnotations[getImageAnnotationKey(ctx, container.Name)] = container.Image patches = append(patches, operations.ReplacePatchOperation(path, replacement)) } @@ -99,7 +112,7 @@ func mutatePod(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Clu if err != nil { return nil, err } - updatedAnnotations[getImageAnnotationKey(container.Name)] = container.Image + updatedAnnotations[getImageAnnotationKey(ctx, container.Name)] = container.Image patches = append(patches, operations.ReplacePatchOperation(path, replacement)) } @@ -110,7 +123,7 @@ func mutatePod(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Clu if err != nil { return nil, err } - updatedAnnotations[getImageAnnotationKey(container.Name)] = container.Image + updatedAnnotations[getImageAnnotationKey(ctx, container.Name)] = container.Image patches = append(patches, operations.ReplacePatchOperation(path, replacement)) } diff --git a/src/internal/agent/hooks/pods_test.go b/src/internal/agent/hooks/pods_test.go index 42ddaab8fa..7fd8de60bf 100644 --- a/src/internal/agent/hooks/pods_test.go +++ b/src/internal/agent/hooks/pods_test.go @@ -154,3 +154,31 @@ func TestPodMutationWebhook(t *testing.T) { }) } } +func TestGetImageAnnotationKey(t *testing.T) { + t.Parallel() + tests := []struct { + containerName string + expectedKey string + }{ + { + containerName: "nginx", + expectedKey: "zarf.dev/original-image-nginx", + }, + { + containerName: "a-very-long-container-name-that-exceeds-sixty-three-characters", + expectedKey: "zarf.dev/original-image-a-very-long-container-name-that-exceeds-sixty-th", + }, + { + containerName: "remove-trailing-hyphen----", + expectedKey: "zarf.dev/original-image-remove-trailing-hyphen", + }, + } + + for _, tt := range tests { + t.Run(tt.containerName, func(t *testing.T) { + t.Parallel() + key := getImageAnnotationKey(context.Background(), tt.containerName) + require.Equal(t, tt.expectedKey, key) + }) + } +} diff --git a/src/test/packages/36-health-checks/ready-pod.yaml b/src/test/packages/36-health-checks/ready-pod.yaml index 836ce373a6..ae2d6c5f41 100644 --- a/src/test/packages/36-health-checks/ready-pod.yaml +++ b/src/test/packages/36-health-checks/ready-pod.yaml @@ -9,5 +9,5 @@ spec: image: ghcr.io/stefanprodan/podinfo:6.4.0 command: ["sh", "-c", "sleep 3"] containers: - - name: podinfo + - name: ready-pod-with-long-name-to-test-agent-truncate-annotation-name image: ghcr.io/stefanprodan/podinfo:6.4.0