parent
a0f615ad09
commit
9e37741916
|
@ -2,8 +2,8 @@ CHANGELOG
|
|||
=========
|
||||
|
||||
## HEAD (unreleased)
|
||||
_(none)_
|
||||
|
||||
- Fix handling of `nil` values in Outputs in Go.
|
||||
[#4268](https://github.com/pulumi/pulumi/pull/4268)
|
||||
|
||||
## 1.14.0 (2020-04-01)
|
||||
- Fix error related to side-by-side versions of `@pulumi/pulumi`.
|
||||
|
|
|
@ -385,7 +385,11 @@ func (o *OutputState) ApplyTWithContext(ctx context.Context, applier interface{}
|
|||
}
|
||||
|
||||
// If we have a known value, run the applier to transform it.
|
||||
results := fn.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(v)})
|
||||
val := reflect.ValueOf(v)
|
||||
if !val.IsValid() {
|
||||
val = reflect.Zero(o.elementType())
|
||||
}
|
||||
results := fn.Call([]reflect.Value{reflect.ValueOf(ctx), val})
|
||||
if len(results) == 2 && !results[1].IsNil() {
|
||||
result.reject(results[1].Interface().(error))
|
||||
return
|
||||
|
@ -432,6 +436,10 @@ func AllWithContext(ctx context.Context, inputs ...interface{}) ArrayOutput {
|
|||
}
|
||||
|
||||
func gatherDependencies(v interface{}) []Resource {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
depSet := make(map[Resource]struct{})
|
||||
gatherDependencySet(reflect.ValueOf(v), depSet)
|
||||
|
||||
|
@ -557,7 +565,11 @@ func awaitInputs(ctx context.Context, v, resolved reflect.Value) (bool, bool, er
|
|||
return known, secret, err
|
||||
}
|
||||
if !assignInput {
|
||||
resolved.Set(reflect.ValueOf(e))
|
||||
val := reflect.ValueOf(e)
|
||||
if !val.IsValid() {
|
||||
val = reflect.Zero(output.ElementType())
|
||||
}
|
||||
resolved.Set(val)
|
||||
} else {
|
||||
resolved.Set(reflect.ValueOf(input))
|
||||
}
|
||||
|
@ -706,6 +718,11 @@ func toOutputWithContext(ctx context.Context, v interface{}, forceSecret bool) O
|
|||
|
||||
result := newOutput(resultType, gatherDependencies(v)...)
|
||||
go func() {
|
||||
if v == nil {
|
||||
result.fulfill(nil, true, false, nil)
|
||||
return
|
||||
}
|
||||
|
||||
element := reflect.New(resolvedType).Elem()
|
||||
|
||||
known, secret, err := awaitInputs(ctx, reflect.ValueOf(v), element)
|
||||
|
@ -794,6 +811,10 @@ func AnyWithContext(ctx context.Context, v interface{}) AnyOutput {
|
|||
// Return an output that resolves when all nested inputs have resolved.
|
||||
out := newOutput(anyOutputType, gatherDependencies(v)...)
|
||||
go func() {
|
||||
if v == nil {
|
||||
out.fulfill(nil, true, false, nil)
|
||||
return
|
||||
}
|
||||
var result interface{}
|
||||
known, secret, err := awaitInputs(ctx, reflect.ValueOf(v), reflect.ValueOf(&result).Elem())
|
||||
out.fulfill(result, known, secret, err)
|
||||
|
|
|
@ -393,3 +393,44 @@ func TestSecretApply(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNil(t *testing.T) {
|
||||
ao := Any(nil)
|
||||
v, known, secret, err := await(ao)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nil, v)
|
||||
|
||||
o := ToOutput(nil)
|
||||
v, known, secret, err = await(o)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nil, v)
|
||||
|
||||
o = ToOutput(ao)
|
||||
v, known, secret, err = await(o)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nil, v)
|
||||
|
||||
ao = ToOutput("").ApplyT(func(v string) interface{} {
|
||||
return nil
|
||||
}).(AnyOutput)
|
||||
v, known, secret, err = await(ao)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nil, v)
|
||||
|
||||
bo := ao.ApplyBool(func(x interface{}) bool {
|
||||
return x == nil
|
||||
})
|
||||
v, known, secret, err = await(bo)
|
||||
assert.True(t, known)
|
||||
assert.False(t, secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, v)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue