Adding pulumi.IsSecret
and pulumi.Unsecret
to the Go SDK (#6085)
This commit is contained in:
parent
655418bbbf
commit
475250f82f
|
@ -6,6 +6,12 @@ CHANGELOG
|
|||
- [CLI] Add the ability to log out of all Pulumi backends at once.
|
||||
[#6101](https://github.com/pulumi/pulumi/pull/6101)
|
||||
|
||||
- [sdk/go] Added `pulumi.Unsecret` which will take an existing secret output and
|
||||
create a non-secret variant with an unwrapped secret value. Also adds,
|
||||
`pulumi.IsSecret` which will take an existing output and
|
||||
determine if an output has a secret within the output.
|
||||
[#6085](https://github.com/pulumi/pulumi/pull/6085)
|
||||
|
||||
## 2.17.2 (2021-01-14)
|
||||
|
||||
- .NET: Allow `IMock.NewResourceAsync` to return a null ID for component resources.
|
||||
|
@ -55,7 +61,7 @@ CHANGELOG
|
|||
- [sdk/dotnet] Moved urn value retrieval into if statement
|
||||
for MockMonitor
|
||||
[#6081](https://github.com/pulumi/pulumi/pull/6081)
|
||||
|
||||
|
||||
- [sdk/dotnet] Added `Pulumi.Output.Unsecret` which will
|
||||
take an existing secret output and
|
||||
create a non-secret variant with an unwrapped secret value.
|
||||
|
|
|
@ -45,7 +45,7 @@ type Output interface {
|
|||
resolve(value interface{}, known, secret bool, deps []Resource)
|
||||
reject(err error)
|
||||
await(ctx context.Context) (interface{}, bool, bool, []Resource, error)
|
||||
isSecret() bool
|
||||
IsSecret() bool
|
||||
}
|
||||
|
||||
var outputType = reflect.TypeOf((*Output)(nil)).Elem()
|
||||
|
@ -419,11 +419,26 @@ func (o *OutputState) ApplyTWithContext(ctx context.Context, applier interface{}
|
|||
return result
|
||||
}
|
||||
|
||||
// isSecret returns a bool representing the secretness of the Output
|
||||
func (o *OutputState) isSecret() bool {
|
||||
// IsSecret returns a bool representing the secretness of the Output
|
||||
func (o *OutputState) IsSecret() bool {
|
||||
return o.getState().secret
|
||||
}
|
||||
|
||||
// Unsecret will unwrap a secret output as a new output with a resolved value and no secretness
|
||||
func Unsecret(input Output) Output {
|
||||
return UnsecretWithContext(context.Background(), input)
|
||||
}
|
||||
|
||||
// UnsecretWithContext will unwrap a secret output as a new output with a resolved value and no secretness
|
||||
func UnsecretWithContext(ctx context.Context, input Output) Output {
|
||||
var x bool
|
||||
x = false
|
||||
o := toOutputWithContext(ctx, input, &x)
|
||||
// set immediate secretness ahead of resolution/fufillment
|
||||
o.getState().secret = false
|
||||
return o
|
||||
}
|
||||
|
||||
// ToSecret wraps the input in an Output marked as secret
|
||||
// that will resolve when all Inputs contained in the given value have resolved.
|
||||
func ToSecret(input interface{}) Output {
|
||||
|
@ -433,7 +448,9 @@ func ToSecret(input interface{}) Output {
|
|||
// ToSecretWithContext wraps the input in an Output marked as secret
|
||||
// that will resolve when all Inputs contained in the given value have resolved.
|
||||
func ToSecretWithContext(ctx context.Context, input interface{}) Output {
|
||||
o := toOutputWithContext(ctx, input, true)
|
||||
var x bool
|
||||
x = true
|
||||
o := toOutputWithContext(ctx, input, &x)
|
||||
// set immediate secretness ahead of resolution/fufillment
|
||||
o.getState().secret = true
|
||||
return o
|
||||
|
@ -738,10 +755,10 @@ func ToOutput(v interface{}) Output {
|
|||
// ToOutputWithContext returns an Output that will resolve when all Outputs contained in the given value have
|
||||
// resolved.
|
||||
func ToOutputWithContext(ctx context.Context, v interface{}) Output {
|
||||
return toOutputWithContext(ctx, v, false)
|
||||
return toOutputWithContext(ctx, v, nil)
|
||||
}
|
||||
|
||||
func toOutputWithContext(ctx context.Context, v interface{}, forceSecret bool) Output {
|
||||
func toOutputWithContext(ctx context.Context, v interface{}, forceSecretVal *bool) Output {
|
||||
resolvedType := reflect.TypeOf(v)
|
||||
if input, ok := v.(Input); ok {
|
||||
resolvedType = input.ElementType()
|
||||
|
@ -762,7 +779,9 @@ func toOutputWithContext(ctx context.Context, v interface{}, forceSecret bool) O
|
|||
element := reflect.New(resolvedType).Elem()
|
||||
|
||||
known, secret, deps, err := awaitInputs(ctx, reflect.ValueOf(v), element)
|
||||
secret = secret || forceSecret
|
||||
if forceSecretVal != nil {
|
||||
secret = *forceSecretVal
|
||||
}
|
||||
if err != nil || !known {
|
||||
result.fulfill(nil, known, secret, deps, err)
|
||||
return
|
||||
|
|
|
@ -396,11 +396,53 @@ func TestToOutputInputAny(t *testing.T) {
|
|||
}, v)
|
||||
}
|
||||
|
||||
// Test that Unsecret will return an Output that has an unwrapped secret
|
||||
func TestUnsecret(t *testing.T) {
|
||||
s := ToSecret(String("foo"))
|
||||
// assert that secret is immediately secret
|
||||
assert.True(t, s.IsSecret())
|
||||
|
||||
unS := Unsecret(s)
|
||||
// assert that we do not have a secret
|
||||
assert.False(t, unS.IsSecret())
|
||||
|
||||
errChan := make(chan error)
|
||||
resultChan := make(chan string)
|
||||
secretChan := make(chan bool)
|
||||
|
||||
unS.ApplyT(func(v interface{}) (string, error) {
|
||||
// assert secretness after the output resolves
|
||||
secretChan <- unS.IsSecret()
|
||||
val := v.(string)
|
||||
if val == "foo" {
|
||||
// validate the value
|
||||
resultChan <- val
|
||||
} else {
|
||||
errChan <- fmt.Errorf("Invalid result: %v", val)
|
||||
}
|
||||
return val, nil
|
||||
})
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
assert.Nil(t, err)
|
||||
break
|
||||
case r := <-resultChan:
|
||||
assert.Equal(t, "foo", r)
|
||||
break
|
||||
case isSecret := <-secretChan:
|
||||
assert.False(t, isSecret)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that SecretT sets appropriate internal state and that IsSecret appropriately reads it.
|
||||
func TestSecrets(t *testing.T) {
|
||||
s := ToSecret(String("foo"))
|
||||
// assert that secret is immediately secret
|
||||
assert.True(t, s.isSecret())
|
||||
assert.True(t, s.IsSecret())
|
||||
|
||||
errChan := make(chan error)
|
||||
resultChan := make(chan string)
|
||||
|
@ -408,7 +450,7 @@ func TestSecrets(t *testing.T) {
|
|||
|
||||
s.ApplyT(func(v interface{}) (string, error) {
|
||||
// assert secretness after the output resolves
|
||||
secretChan <- s.isSecret()
|
||||
secretChan <- s.IsSecret()
|
||||
val := v.(string)
|
||||
if val == "foo" {
|
||||
// validate the value
|
||||
|
@ -439,7 +481,7 @@ func TestSecrets(t *testing.T) {
|
|||
func TestSecretApply(t *testing.T) {
|
||||
s1 := ToSecret(String("foo"))
|
||||
// assert that secret is immediately secret
|
||||
assert.True(t, s1.isSecret())
|
||||
assert.True(t, s1.IsSecret())
|
||||
s2 := StringInput(String("bar"))
|
||||
|
||||
errChan := make(chan error)
|
||||
|
@ -452,7 +494,7 @@ func TestSecretApply(t *testing.T) {
|
|||
})
|
||||
s.ApplyT(func(v interface{}) (string, error) {
|
||||
// assert secretness after the output resolves
|
||||
secretChan <- s.isSecret()
|
||||
secretChan <- s.IsSecret()
|
||||
val := v.(string)
|
||||
if val == "foobar" {
|
||||
// validate the value
|
||||
|
|
Loading…
Reference in a new issue