Skip to content

Commit

Permalink
Add implementation for CloudFormation Custom Resource Emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
flostadler committed Nov 7, 2024
1 parent 6575dfa commit baf7ba4
Show file tree
Hide file tree
Showing 7 changed files with 2,205 additions and 3 deletions.
4 changes: 4 additions & 0 deletions provider/pkg/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ type CloudAPIFunction struct {
// ExtensionResourceToken is a Pulumi token for the resource to deploy
// custom third-party CloudFormation types.
const ExtensionResourceToken = "aws-native:index:ExtensionResource"

// CfnCustomResourceToken is a Pulumi token for the resource to deploy
// CloudFormation custom resources.
const CfnCustomResourceToken = "aws-native:cloudformation:CustomResourceEmulator"
41 changes: 41 additions & 0 deletions provider/pkg/naming/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,47 @@ func cfnValueToSdk(value interface{}) interface{} {
}
}

// ToStringifiedMap creates a copy of the input map with all primitive values converted to strings.
func ToStringifiedMap(value map[string]interface{}) map[string]interface{} {
if value == nil {
return nil
}

result := map[string]interface{}{}
for k, v := range value {
result[k] = primitivesToString(v)
}
return result
}

func primitivesToString(value interface{}) interface{} {
if value == nil {
return nil
}

switch reflect.TypeOf(value).Kind() {
case reflect.Map:
valueMap, ok := value.(map[string]interface{})
if !ok {
return value
}
result := map[string]interface{}{}
for k, v := range valueMap {
result[k] = primitivesToString(v)
}
return result
case reflect.Slice, reflect.Array:
s := reflect.ValueOf(value)
result := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
result[i] = primitivesToString(s.Index(i).Interface())
}
return result
default:
return fmt.Sprintf("%v", value)
}
}

type ConversionError struct {
Type string
Value interface{}
Expand Down
117 changes: 117 additions & 0 deletions provider/pkg/naming/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,120 @@ func TestSanitizeCfnString(t *testing.T) {
})
}
}

func TestToStringifiedMap(t *testing.T) {
t.Parallel()
tests := []struct {
name string
input map[string]interface{}
expected map[string]interface{}
}{
{
name: "Nil input",
input: nil,
expected: nil,
},
{
name: "Empty map",
input: map[string]interface{}{},
expected: map[string]interface{}{},
},
{
name: "Map with primitive values",
input: map[string]interface{}{
"string": "value",
"int": 42,
"float": 3.14,
"bool": true,
},
expected: map[string]interface{}{
"string": "value",
"int": "42",
"float": "3.14",
"bool": "true",
},
},
{
name: "Map with nested map",
input: map[string]interface{}{
"nested": map[string]interface{}{
"key": "value",
"num": 123,
},
},
expected: map[string]interface{}{
"nested": map[string]interface{}{
"key": "value",
"num": "123",
},
},
},
{
name: "Map with array",
input: map[string]interface{}{
"array": []interface{}{"a", 1, 2.5, false},
},
expected: map[string]interface{}{
"array": []interface{}{"a", "1", "2.5", "false"},
},
},
{
name: "Map with mixed nested structures",
input: map[string]interface{}{
"level1": map[string]interface{}{
"level2": []interface{}{
map[string]interface{}{
"key1": "value1",
"key2": 2,
},
3.14,
"string",
},
"anotherKey": true,
"arrayOfMaps": []interface{}{
map[string]interface{}{
"key1": "value1",
"key2": 2,
},
map[string]interface{}{
"key3": "value3",
"key4": 4,
},
},
},
},
expected: map[string]interface{}{
"level1": map[string]interface{}{
"level2": []interface{}{
map[string]interface{}{
"key1": "value1",
"key2": "2",
},
"3.14",
"string",
},
"anotherKey": "true",
"arrayOfMaps": []interface{}{
map[string]interface{}{
"key1": "value1",
"key2": "2",
},
map[string]interface{}{
"key3": "value3",
"key4": "4",
},
},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
actual := ToStringifiedMap(tt.input)
assert.Equal(t, tt.expected, actual)
})
}
}

Loading

0 comments on commit baf7ba4

Please sign in to comment.