From 08bb23af1d27a7c290b2efdc4975e7df3999ac68 Mon Sep 17 00:00:00 2001 From: Erik Cederberg Date: Thu, 20 Feb 2025 08:23:01 +0100 Subject: [PATCH 1/2] feat(parameters): support complex types as parameter set values - Add support for numbers, objects, arrays and booleans in parameter set `value` sources. - Convert complex values to JSON string representation during parameter set unmarshalling. Signed-off-by: Erik Cederberg --- pkg/schema/parameter-set.schema.json | 4 +- pkg/secrets/strategy.go | 22 ++++ pkg/secrets/strategy_test.go | 108 ++++++++++++++++++ pkg/storage/schema.go | 4 +- .../parameters/create/parameter-set.json | 2 +- 5 files changed, 135 insertions(+), 5 deletions(-) diff --git a/pkg/schema/parameter-set.schema.json b/pkg/schema/parameter-set.schema.json index d355449e8..591e89c66 100644 --- a/pkg/schema/parameter-set.schema.json +++ b/pkg/schema/parameter-set.schema.json @@ -32,7 +32,7 @@ }, "value": { "description": "Hard-coded value", - "type": "string" + "type": ["string", "number", "object", "array", "boolean"] } }, "additionalProperties": true @@ -86,7 +86,7 @@ "schemaVersion": { "description": "Version of the parameter set schema to which this document adheres", "type": "string", - "default": "1.0.1" + "default": "1.1.0" } }, "required": [ diff --git a/pkg/secrets/strategy.go b/pkg/secrets/strategy.go index cbefefa92..2646b0c60 100644 --- a/pkg/secrets/strategy.go +++ b/pkg/secrets/strategy.go @@ -69,6 +69,13 @@ func (s *Source) UnmarshalRaw(raw map[string]interface{}) error { s.Strategy = k if value, ok := v.(string); ok { s.Hint = value + + } else if s.Strategy == "value" { + value, err := unmarshalRawValue(v) + if err != nil { + return err + } + s.Hint = value } else { s.Hint = fmt.Sprintf("%v", s.Hint) } @@ -79,6 +86,21 @@ func (s *Source) UnmarshalRaw(raw map[string]interface{}) error { } } +func unmarshalRawValue(rawValue interface{}) (string, error) { + switch value := rawValue.(type) { + case []interface{}, map[string]interface{}: + encodedValue, err := json.Marshal(value) + if err != nil { + return "", fmt.Errorf("unable to convert %T into a string: %w", value, err) + } + return string(encodedValue), nil + case nil: + return "", nil + default: + return fmt.Sprintf("%v", value), nil + } +} + var ( _ json.Marshaler = Source{} _ json.Unmarshaler = &Source{} diff --git a/pkg/secrets/strategy_test.go b/pkg/secrets/strategy_test.go index 8e5478fe9..686fdb82e 100644 --- a/pkg/secrets/strategy_test.go +++ b/pkg/secrets/strategy_test.go @@ -28,3 +28,111 @@ func TestSet_Merge(t *testing.T) { err = set.Merge(Set{"second": "bis"}) is.EqualError(err, `ambiguous value resolution: "second" is already present in base sets, cannot merge`) } + +func TestSource_UnmarshalRaw(t *testing.T) { + tests := []struct { + name string + raw map[string]interface{} + want Source + err string + }{ + { + name: "empty map", + raw: map[string]interface{}{}, + want: Source{}, + }, + { + name: "string", + raw: map[string]interface{}{ + "env": "SOME_VALUE", + }, + want: Source{ + Strategy: "env", + Hint: "SOME_VALUE", + }, + }, + { + name: "array value", + raw: map[string]interface{}{ + "value": []interface{}{1, 2, "3"}, + }, + want: Source{ + Strategy: "value", + Hint: "[1,2,\"3\"]", + }, + }, + { + name: "map value", + raw: map[string]interface{}{ + "value": map[string]interface{}{ + "abc": "def", + }, + }, + want: Source{ + Strategy: "value", + Hint: `{"abc":"def"}`, + }, + }, + { + name: "integer value", + raw: map[string]interface{}{ + "value": 10, + }, + want: Source{ + Strategy: "value", + Hint: "10", + }, + }, + { + name: "float value", + raw: map[string]interface{}{ + "value": 3.1415, + }, + want: Source{ + Strategy: "value", + Hint: "3.1415", + }, + }, + { + name: "boolean value", + raw: map[string]interface{}{ + "value": true, + }, + want: Source{ + Strategy: "value", + Hint: "true", + }, + }, + { + name: "null value", + raw: map[string]interface{}{ + "value": nil, + }, + want: Source{ + Strategy: "value", + Hint: "", + }, + }, + { + name: "multiple keys", + raw: map[string]interface{}{ + "env": "abc", + "value": "def", + }, + err: "multiple key/value pairs specified for source but only one may be defined", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + s := Source{} + err := s.UnmarshalRaw(tc.raw) + + if tc.err != "" { + assert.EqualError(t, err, tc.err) + } else if err != nil { + t.Errorf("unexpected error: %v", err) + } + assert.Equal(t, tc.want, s) + }) + } +} diff --git a/pkg/storage/schema.go b/pkg/storage/schema.go index 4ed8f49bf..fc748f848 100644 --- a/pkg/storage/schema.go +++ b/pkg/storage/schema.go @@ -28,7 +28,7 @@ const ( // DefaultParameterSetSchemaVersion represents the version associated with the schema // // for parameter set documents. - DefaultParameterSetSchemaVersion = cnab.SchemaVersion("1.0.1") + DefaultParameterSetSchemaVersion = cnab.SchemaVersion("1.1.0") ) var ( @@ -48,7 +48,7 @@ var ( SupportedInstallationSchemaVersions = schema.MustParseConstraint("1.0.2") // SupportedParameterSetSchemaVersions represents the set of allowed schema versions for ParameterSet documents. - SupportedParameterSetSchemaVersions = schema.MustParseConstraint("1.0.1") + SupportedParameterSetSchemaVersions = schema.MustParseConstraint("1.0.1 || 1.1.0") ) type Schema struct { diff --git a/pkg/templates/templates/parameters/create/parameter-set.json b/pkg/templates/templates/parameters/create/parameter-set.json index ca3ef13c8..b1a584681 100644 --- a/pkg/templates/templates/parameters/create/parameter-set.json +++ b/pkg/templates/templates/parameters/create/parameter-set.json @@ -38,4 +38,4 @@ } } ] -} \ No newline at end of file +} From e1e99864ffbe49443393cee1b96c609b21cec1cd Mon Sep 17 00:00:00 2001 From: Erik Cederberg Date: Thu, 20 Feb 2025 09:23:39 +0100 Subject: [PATCH 2/2] chore(templates): update parameter set templates Signed-off-by: Erik Cederberg --- pkg/templates/templates/parameters/create/parameter-set.json | 2 +- pkg/templates/templates/parameters/create/parameter-set.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/templates/templates/parameters/create/parameter-set.json b/pkg/templates/templates/parameters/create/parameter-set.json index b1a584681..8abbaa791 100644 --- a/pkg/templates/templates/parameters/create/parameter-set.json +++ b/pkg/templates/templates/parameters/create/parameter-set.json @@ -1,6 +1,6 @@ { "schemaType": "ParameterSet", - "schemaVersion": "1.0.1", + "schemaVersion": "1.1.0", "name": "NAME", "namespace": "NAMESPACE", "labels": { diff --git a/pkg/templates/templates/parameters/create/parameter-set.yaml b/pkg/templates/templates/parameters/create/parameter-set.yaml index 8234ec01e..235334939 100644 --- a/pkg/templates/templates/parameters/create/parameter-set.yaml +++ b/pkg/templates/templates/parameters/create/parameter-set.yaml @@ -1,6 +1,6 @@ # See the Parameter Set file format documentation at https://porter.sh/reference/file-formats/#parameter-set schemaType: ParameterSet -schemaVersion: 1.0.1 +schemaVersion: 1.1.0 # Name of the parameter set. name: NAME # The namespace in which the parameter set is defined. @@ -31,4 +31,4 @@ parameters: - name: parameter-secret source: # Resolve the parameter value from the secret store specified in your Porter configuration file. - secret: parameter-secret \ No newline at end of file + secret: parameter-secret