From 0317aa152a0ee16fe4209d86cd83c68561e57c31 Mon Sep 17 00:00:00 2001 From: pawannn Date: Sat, 1 Nov 2025 19:47:33 +0530 Subject: [PATCH 1/2] Fix TypeKVPairs to handle multiple comma-separated pairs --- kvpairs_test.go | 85 +++++++++++++++++++++++++++++++++++++ sdk/framework/field_data.go | 14 ++++++ 2 files changed, 99 insertions(+) create mode 100644 kvpairs_test.go diff --git a/kvpairs_test.go b/kvpairs_test.go new file mode 100644 index 00000000000..6f143e55f61 --- /dev/null +++ b/kvpairs_test.go @@ -0,0 +1,85 @@ +package main + +import ( + "testing" + + "github.com/hashicorp/vault/sdk/framework" +) + +func TestTypeKVPairs(t *testing.T) { + fields := map[string]*framework.FieldSchema{ + "metadata": { + Type: framework.TypeKVPairs, + }, + } + + testCases := []struct { + name string + input string + expectedCount int + expectedPairs map[string]string + }{ + { + name: "Single pair", + input: "A=a", + expectedCount: 1, + expectedPairs: map[string]string{"A": "a"}, + }, + { + name: "Multiple pairs - THIS WILL FAIL", + input: "A=a,B=b,C=c", + expectedCount: 3, + expectedPairs: map[string]string{ + "A": "a", + "B": "b", + "C": "c", + }, + }, + { + name: "Two pairs", + input: "key1=value1,key2=value2", + expectedCount: 2, + expectedPairs: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + rawData := map[string]interface{}{ + "metadata": tc.input, + } + + fieldData := &framework.FieldData{ + Raw: rawData, + Schema: fields, + } + + result := fieldData.Get("metadata") + kvMap, ok := result.(map[string]string) + + if !ok { + t.Fatal("Failed to convert to map[string]string") + } + + if len(kvMap) != tc.expectedCount { + t.Errorf("Expected %d pairs, got %d", tc.expectedCount, len(kvMap)) + t.Logf("Actual map: %v", kvMap) + } + + for expectedKey, expectedValue := range tc.expectedPairs { + actualValue, exists := kvMap[expectedKey] + if !exists { + t.Errorf("Expected key '%s' not found in result", expectedKey) + } else if actualValue != expectedValue { + t.Errorf("For key '%s': expected value '%s', got '%s'", + expectedKey, expectedValue, actualValue) + + } + } + }) + } +} diff --git a/sdk/framework/field_data.go b/sdk/framework/field_data.go index a1a27a83b25..41124641928 100644 --- a/sdk/framework/field_data.go +++ b/sdk/framework/field_data.go @@ -347,9 +347,23 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo if err := mapstructure.WeakDecode(raw, &listResult); err != nil { return nil, false, err } + if len(listResult) == 1 { + // Try splitting by comma to see if there are multiple pairs + commaSplit := strings.Split(listResult[0], ",") + if len(commaSplit) > 1 { + // Multiple pairs found, use the comma-split version + listResult = commaSplit + } + } result := make(map[string]string, len(listResult)) for _, keyPair := range listResult { + // Trim whitespace from each pair + keyPair = strings.TrimSpace(keyPair) + if keyPair == "" { + continue + } + keyPairSlice := strings.SplitN(keyPair, "=", 2) if len(keyPairSlice) != 2 || keyPairSlice[0] == "" { return nil, false, fmt.Errorf("invalid key pair %q", keyPair) From b9f3bbe2d0eafe1c85799c4db9ad32f850f82af9 Mon Sep 17 00:00:00 2001 From: pawannn Date: Sun, 2 Nov 2025 02:09:05 +0530 Subject: [PATCH 2/2] chore: added test cases for TypeKVPairs --- kvpairs_test.go | 85 -------------------------------- sdk/framework/field_data_test.go | 78 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 85 deletions(-) delete mode 100644 kvpairs_test.go diff --git a/kvpairs_test.go b/kvpairs_test.go deleted file mode 100644 index 6f143e55f61..00000000000 --- a/kvpairs_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "testing" - - "github.com/hashicorp/vault/sdk/framework" -) - -func TestTypeKVPairs(t *testing.T) { - fields := map[string]*framework.FieldSchema{ - "metadata": { - Type: framework.TypeKVPairs, - }, - } - - testCases := []struct { - name string - input string - expectedCount int - expectedPairs map[string]string - }{ - { - name: "Single pair", - input: "A=a", - expectedCount: 1, - expectedPairs: map[string]string{"A": "a"}, - }, - { - name: "Multiple pairs - THIS WILL FAIL", - input: "A=a,B=b,C=c", - expectedCount: 3, - expectedPairs: map[string]string{ - "A": "a", - "B": "b", - "C": "c", - }, - }, - { - name: "Two pairs", - input: "key1=value1,key2=value2", - expectedCount: 2, - expectedPairs: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - - rawData := map[string]interface{}{ - "metadata": tc.input, - } - - fieldData := &framework.FieldData{ - Raw: rawData, - Schema: fields, - } - - result := fieldData.Get("metadata") - kvMap, ok := result.(map[string]string) - - if !ok { - t.Fatal("Failed to convert to map[string]string") - } - - if len(kvMap) != tc.expectedCount { - t.Errorf("Expected %d pairs, got %d", tc.expectedCount, len(kvMap)) - t.Logf("Actual map: %v", kvMap) - } - - for expectedKey, expectedValue := range tc.expectedPairs { - actualValue, exists := kvMap[expectedKey] - if !exists { - t.Errorf("Expected key '%s' not found in result", expectedKey) - } else if actualValue != expectedValue { - t.Errorf("For key '%s': expected value '%s', got '%s'", - expectedKey, expectedValue, actualValue) - - } - } - }) - } -} diff --git a/sdk/framework/field_data_test.go b/sdk/framework/field_data_test.go index 68fc57e316c..89233db9a08 100644 --- a/sdk/framework/field_data_test.go +++ b/sdk/framework/field_data_test.go @@ -1275,3 +1275,81 @@ func TestValidateStrict(t *testing.T) { }) } } + +func TestTypeKVPairs(t *testing.T) { + fields := map[string]*FieldSchema{ + "metadata": { + Type: TypeKVPairs, + }, + } + + testCases := []struct { + name string + input string + expectedCount int + expectedPairs map[string]string + }{ + { + name: "Single pair", + input: "key1=value1", + expectedCount: 1, + expectedPairs: map[string]string{"key1": "value1"}, + }, + { + name: "Multiple pairs", + input: "key1=value1,key2=value2,key3=value3", + expectedCount: 3, + expectedPairs: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + { + name: "Two pairs", + input: "key1=value1,key2=value2", + expectedCount: 2, + expectedPairs: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + rawData := map[string]interface{}{ + "metadata": tc.input, + } + + fieldData := &FieldData{ + Raw: rawData, + Schema: fields, + } + + result := fieldData.Get("metadata") + kvMap, ok := result.(map[string]string) + + if !ok { + t.Fatal("Failed to convert to map[string]string") + } + + if len(kvMap) != tc.expectedCount { + t.Errorf("Expected %d pairs, got %d", tc.expectedCount, len(kvMap)) + t.Logf("Actual map: %v", kvMap) + } + + for expectedKey, expectedValue := range tc.expectedPairs { + actualValue, exists := kvMap[expectedKey] + if !exists { + t.Errorf("Expected key '%s' not found in result", expectedKey) + } else if actualValue != expectedValue { + t.Errorf("For key '%s': expected value '%s', got '%s'", + expectedKey, expectedValue, actualValue) + + } + } + }) + } +}