[sdk/go] Support maps in Invoke outputs and Read inputs (#6014)
* [sdk/go] Support maps in Invoke outputs and Read inputs These are already supported by the implementation, but were prevented by overzealous input validation in Invoke and ReadResource. Follow-up to #4522 and #4521. * Add CHANGELOG * PR feedback
This commit is contained in:
parent
e1ac01a9f2
commit
db14188526
|
@ -22,6 +22,9 @@ CHANGELOG
|
|||
give the user some information on how to resolve the problem
|
||||
[#6044](https://github.com/pulumi/pulumi/pull/6044)
|
||||
|
||||
- [sdk/go] Support maps in Invoke outputs and Read inputs
|
||||
[#6014](https://github.com/pulumi/pulumi/pull/6014)
|
||||
|
||||
## 2.16.2 (2020-12-23)
|
||||
|
||||
- Fix a bug in the core engine that could cause previews to fail if a resource with changes had
|
||||
|
|
|
@ -171,8 +171,10 @@ func (ctx *Context) Invoke(tok string, args interface{}, result interface{}, opt
|
|||
}
|
||||
|
||||
resultV := reflect.ValueOf(result)
|
||||
if resultV.Kind() != reflect.Ptr || resultV.Elem().Kind() != reflect.Struct {
|
||||
return errors.New("result must be a pointer to a struct value")
|
||||
if !(resultV.Kind() == reflect.Ptr &&
|
||||
(resultV.Elem().Kind() == reflect.Struct ||
|
||||
(resultV.Elem().Kind() == reflect.Map && resultV.Elem().Type().Key().Kind() == reflect.String))) {
|
||||
return errors.New("result must be a pointer to a struct or map value")
|
||||
}
|
||||
|
||||
options := &invokeOptions{}
|
||||
|
@ -305,8 +307,9 @@ func (ctx *Context) ReadResource(
|
|||
if propsType.Kind() == reflect.Ptr {
|
||||
propsType = propsType.Elem()
|
||||
}
|
||||
if propsType.Kind() != reflect.Struct {
|
||||
return errors.New("props must be a struct or a pointer to a struct")
|
||||
if !(propsType.Kind() == reflect.Struct ||
|
||||
(propsType.Kind() == reflect.Map && propsType.Key().Kind() == reflect.String)) {
|
||||
return errors.New("props must be a struct or map or a pointer to a struct or map")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ func TestReadResource(t *testing.T) {
|
|||
}
|
||||
|
||||
err := RunErr(func(ctx *Context) error {
|
||||
// Test struct-tag-based marshaling.
|
||||
var res testResource2
|
||||
err := ctx.ReadResource("test:resource:type", "resA", ID("someID"), &testResource2Inputs{
|
||||
Foo: String("oof"),
|
||||
|
@ -203,6 +204,20 @@ func TestReadResource(t *testing.T) {
|
|||
assert.Equal(t, []Resource{&res}, deps)
|
||||
assert.Equal(t, "qux", foo)
|
||||
|
||||
// Test map marshaling.
|
||||
var res2 testResource2
|
||||
err = ctx.ReadResource("test:resource:type", "resA", ID("someID"), Map{
|
||||
"foo": String("oof"),
|
||||
}, &res2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
foo, known, secret, deps, err = await(res2.Foo)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.Equal(t, []Resource{&res2}, deps)
|
||||
assert.Equal(t, "qux", foo)
|
||||
|
||||
return nil
|
||||
}, WithMocks("project", "stack", mocks))
|
||||
assert.NoError(t, err)
|
||||
|
@ -224,16 +239,26 @@ func TestInvoke(t *testing.T) {
|
|||
}
|
||||
|
||||
err := RunErr(func(ctx *Context) error {
|
||||
// Test struct unmarshaling.
|
||||
var result invokeResult
|
||||
err := ctx.Invoke("test:index:func", &invokeArgs{
|
||||
Bang: "gnab",
|
||||
Bar: "rab",
|
||||
}, &result)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "oof", result.Foo)
|
||||
assert.Equal(t, "zab", result.Baz)
|
||||
|
||||
// Test map unmarshaling.
|
||||
var result2 map[string]interface{}
|
||||
err = ctx.Invoke("test:index:func", &invokeArgs{
|
||||
Bang: "gnab",
|
||||
Bar: "rab",
|
||||
}, &result2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "oof", result2["foo"].(string))
|
||||
assert.Equal(t, "zab", result2["baz"].(string))
|
||||
|
||||
return nil
|
||||
}, WithMocks("project", "stack", mocks))
|
||||
assert.NoError(t, err)
|
||||
|
|
Loading…
Reference in a new issue