From 64a8f3b48f02c7ea3279e96a0f5a618620a8d5c5 Mon Sep 17 00:00:00 2001 From: shinichitazawa Date: Fri, 13 Mar 2026 10:42:54 +0900 Subject: [PATCH] fix: improve error message when adoption-fields annotation is missing When using `adoption-policy: adopt` without the `adoption-fields` annotation, `ExtractAdoptionFields` calls `json.Unmarshal` on an empty string, producing a generic "unexpected end of JSON input" error that gives no indication of the actual problem. This change adds an explicit empty-string check that returns a descriptive error explaining that the `adoption-fields` annotation is required, and wraps JSON parse errors with context about which annotation failed. Fixes aws-controllers-k8s/community#2824 --- pkg/runtime/util.go | 9 ++++++++- pkg/runtime/util_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pkg/runtime/util.go b/pkg/runtime/util.go index 81faca5d..425ab181 100644 --- a/pkg/runtime/util.go +++ b/pkg/runtime/util.go @@ -209,11 +209,18 @@ func NeedAdoption(res acktypes.AWSResource) bool { func ExtractAdoptionFields(res acktypes.AWSResource) (map[string]string, error) { fields := getAdoptionFields(res) + if fields == "" { + return nil, fmt.Errorf( + "services.k8s.aws/adoption-fields annotation is required when " + + "adoption-policy is set to 'adopt'; please provide the resource " + + "identifier fields as a JSON object (e.g. '{\"name\": \"my-resource\"}')", + ) + } extractedFields := &map[string]string{} err := json.Unmarshal([]byte(fields), extractedFields) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to parse services.k8s.aws/adoption-fields annotation as JSON: %w", err) } return *extractedFields, nil diff --git a/pkg/runtime/util_test.go b/pkg/runtime/util_test.go index 52e7875d..4a8e8cdc 100644 --- a/pkg/runtime/util_test.go +++ b/pkg/runtime/util_test.go @@ -14,6 +14,7 @@ package runtime import ( + "strings" "testing" "github.com/stretchr/testify/require" @@ -118,3 +119,33 @@ func TestExtractAdoptionFields(t *testing.T) { require.NoError(err) require.Equal(expected, actual) } + +func TestExtractAdoptionFields_EmptyFields(t *testing.T) { + require := require.New(t) + + // No adoption-fields annotation at all + res := &mocks.AWSResource{} + res.On("MetaObject").Return(&metav1.ObjectMeta{ + Annotations: map[string]string{}, + }) + + _, err := ExtractAdoptionFields(res) + require.Error(err) + require.True(strings.Contains(err.Error(), "services.k8s.aws/adoption-fields annotation is required")) + require.True(strings.Contains(err.Error(), "adoption-policy is set to 'adopt'")) +} + +func TestExtractAdoptionFields_InvalidJSON(t *testing.T) { + require := require.New(t) + + res := &mocks.AWSResource{} + res.On("MetaObject").Return(&metav1.ObjectMeta{ + Annotations: map[string]string{ + ackv1alpha1.AnnotationAdoptionFields: `not valid json`, + }, + }) + + _, err := ExtractAdoptionFields(res) + require.Error(err) + require.True(strings.Contains(err.Error(), "failed to parse services.k8s.aws/adoption-fields annotation as JSON")) +}