Skip to content

Commit

Permalink
Support pointers in pulumi.All (#9197)
Browse files Browse the repository at this point in the history
* Support pointers in pulumi.All

In awaitInputs we didn't correctly handle the case of the input value being a pointer and the resoled destination being `interface{}`. We now handle this by allocating a new pointer of the same type of the input, and assiging that to the resolved location if resolved.Type is `any`.

Else we expect resolved.Type() to be some pointer type that the exisiting logic can handle.

* Add to CHANGELOG
  • Loading branch information
Frassle committed Mar 16, 2022
1 parent e399987 commit ac0b4eb
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 6 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG_PENDING.md
@@ -1,6 +1,8 @@
### Improvements

- [area/cli] - Implement `pulumi stack unselect` [#9179](https://github.com/pulumi/pulumi/pull/9179)
- [area/cli] - Implement `pulumi stack unselect`.
[#9179](https://github.com/pulumi/pulumi/pull/9179)

- [language/dotnet] - Updated Pulumi dotnet packages to use grpc-dotnet instead of grpc.
[#9149](https://github.com/pulumi/pulumi/pull/9149)

Expand All @@ -15,5 +17,8 @@

### Bug Fixes

[sdk/nodejs] - Fix uncaught error "ENOENT: no such file or directory" when an error occurs during the stack up
- [sdk/nodejs] - Fix uncaught error "ENOENT: no such file or directory" when an error occurs during the stack up.
[#9065](https://github.com/pulumi/pulumi/issues/9065)

- [sdk/go] - Fix a panic in `pulumi.All` when using pointer inputs.
[#9197](https://github.com/pulumi/pulumi/issues/9197)
16 changes: 12 additions & 4 deletions sdk/go/pulumi/types.go
Expand Up @@ -718,10 +718,18 @@ func awaitInputs(ctx context.Context, v, resolved reflect.Value) (bool, bool, []
} else {
// Handle pointer inputs.
if v.Kind() == reflect.Ptr {
v, valueType = v.Elem(), valueType.Elem()

resolved.Set(reflect.New(resolved.Type().Elem()))
resolved = resolved.Elem()
v = v.Elem()
valueType = valueType.Elem()
if resolved.Type() != anyType {
// resolved should be some pointer type U such that value Type is convertable to U.
resolved.Set(reflect.New(resolved.Type().Elem()))
resolved = resolved.Elem()
} else {
// Allocate storage for a pointer and assign that to resolved, then continue below with resolved set to the inner value of the pointer just allocated
ptr := reflect.New(valueType)
resolved.Set(ptr)
resolved = ptr.Elem()
}
}
}
}
Expand Down
58 changes: 58 additions & 0 deletions sdk/go/pulumi/types_test.go
Expand Up @@ -718,3 +718,61 @@ func TestRegisterInputType(t *testing.T) {
RegisterInputType(reflect.TypeOf((*FooInput)(nil)).Elem(), FooArgs{})
})
}

func TestAll(t *testing.T) {
t.Parallel()

aStringInput := String("Test")
aStringPtrInput := StringPtr("Hello World")
aStringOutput := String("Frob").ToStringOutput()

a := All(aStringInput).ApplyT(func(args []interface{}) (string, error) {
a := args[0].(string)
return a, nil
}).(StringOutput)

v, known, secret, deps, err := await(a)
assert.Equal(t, "Test", v)
assert.True(t, known)
assert.False(t, secret)
assert.ElementsMatch(t, []Resource{}, deps)
assert.NoError(t, err)

a = All(aStringPtrInput).ApplyT(func(args []interface{}) (string, error) {
a := args[0].(*string)
return *a, nil
}).(StringOutput)

v, known, secret, deps, err = await(a)
assert.Equal(t, "Hello World", v)
assert.True(t, known)
assert.False(t, secret)
assert.ElementsMatch(t, []Resource{}, deps)
assert.NoError(t, err)

a = All(aStringOutput).ApplyT(func(args []interface{}) (string, error) {
a := args[0].(string)
return a, nil
}).(StringOutput)

v, known, secret, deps, err = await(a)
assert.Equal(t, "Frob", v)
assert.True(t, known)
assert.False(t, secret)
assert.ElementsMatch(t, []Resource{}, deps)
assert.NoError(t, err)

a = All(aStringInput, aStringPtrInput, aStringOutput).ApplyT(func(args []interface{}) (string, error) {
a := args[0].(string)
b := args[1].(*string)
c := args[2].(string)
return fmt.Sprintf("%s: %s: %s", a, *b, c), nil
}).(StringOutput)

v, known, secret, deps, err = await(a)
assert.Equal(t, "Test: Hello World: Frob", v)
assert.True(t, known)
assert.False(t, secret)
assert.ElementsMatch(t, []Resource{}, deps)
assert.NoError(t, err)
}

0 comments on commit ac0b4eb

Please sign in to comment.