mirror of https://github.com/pulumi/pulumi.git
273 lines
8.3 KiB
Go
273 lines
8.3 KiB
Go
// Copyright 2020-2024, Pulumi Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package pulumi
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestStackReference(t *testing.T) {
|
|
t.Parallel()
|
|
var resName string
|
|
outputs := map[string]interface{}{
|
|
"foo": "bar",
|
|
"baz": []interface{}{"qux"},
|
|
"zed": map[string]interface{}{
|
|
"alpha": "beta",
|
|
},
|
|
"numf": 123.4,
|
|
"numi": 567.0,
|
|
}
|
|
mocks := &testMonitor{
|
|
NewResourceF: func(args MockResourceArgs) (string, resource.PropertyMap, error) {
|
|
assert.Equal(t, "pulumi:pulumi:StackReference", args.TypeToken)
|
|
assert.Equal(t, resName, args.Name)
|
|
assert.True(t, args.Inputs.DeepEquals(resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
"name": "stack",
|
|
})))
|
|
assert.Equal(t, "", args.Provider)
|
|
assert.Equal(t, args.Inputs["name"].StringValue(), args.ID)
|
|
return args.Inputs["name"].StringValue(), resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
"name": "stack",
|
|
"outputs": outputs,
|
|
}), nil
|
|
},
|
|
}
|
|
err := RunErr(func(ctx *Context) error {
|
|
resName = "stack"
|
|
ref0, err := NewStackReference(ctx, resName, nil)
|
|
assert.NoError(t, err)
|
|
_, _, _, _, err = await(ref0.ID())
|
|
assert.NoError(t, err)
|
|
resName = "stack2"
|
|
ref1, err := NewStackReference(ctx, resName, &StackReferenceArgs{Name: String("stack")})
|
|
assert.NoError(t, err)
|
|
outs0, _, _, _, err := await(ref0.Outputs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, outputs, outs0)
|
|
zed0, _, _, _, err := await(ref0.GetOutput(String("zed")))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, outputs["zed"], zed0)
|
|
outs1, _, _, _, err := await(ref1.Outputs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, outputs, outs1)
|
|
zed1, _, _, _, err := await(ref1.GetOutput(String("zed")))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, outputs["zed"], zed1)
|
|
nonexistant, _, _, _, err := await(ref0.GetOutput(String("nonexistant")))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, nil, nonexistant)
|
|
numf, _, _, _, err := await(ref1.GetFloat64Output(String("numf")))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, outputs["numf"], numf)
|
|
_, _, _, _, err = await(ref1.GetFloat64Output(String("foo")))
|
|
assert.EqualError(t, err, fmt.Sprintf(
|
|
"getting stack reference output \"foo\" on stack \"stack2\", failed to convert %T to float64",
|
|
outputs["foo"]))
|
|
numi, _, _, _, err := await(ref1.GetIntOutput(String("numi")))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int(outputs["numi"].(float64)), numi)
|
|
_, _, _, _, err = await(ref1.GetIntOutput(String("foo")))
|
|
assert.EqualError(t, err, fmt.Sprintf(
|
|
"getting stack reference output \"foo\" on stack \"stack2\", failed to convert %T to int",
|
|
outputs["foo"]))
|
|
_, _, _, _, err = await(ref1.GetStringOutput(String("doesnotexist")))
|
|
assert.EqualError(t, err,
|
|
"stack reference output \"doesnotexist\" does not exist on stack \"stack2\"")
|
|
_, _, _, _, err = await(ref1.GetIntOutput(String("doesnotexist")))
|
|
assert.EqualError(t, err,
|
|
"stack reference output \"doesnotexist\" does not exist on stack \"stack2\"")
|
|
_, _, _, _, err = await(ref1.GetFloat64Output(String("doesnotexist")))
|
|
assert.EqualError(t, err,
|
|
"stack reference output \"doesnotexist\" does not exist on stack \"stack2\"")
|
|
return nil
|
|
}, WithMocks("project", "stack", mocks))
|
|
assert.NoError(t, err)
|
|
|
|
err = RunErr(func(ctx *Context) error {
|
|
ref0, err := NewStackReference(ctx, resName, nil)
|
|
assert.NoError(t, err)
|
|
_, known, _, _, err := await(ref0.GetIntOutput(String("does-not-exist")))
|
|
assert.NoError(t, err)
|
|
assert.False(t, known)
|
|
|
|
return nil
|
|
}, WithDryRun(true), WithMocks("project", "stack", &testMonitor{
|
|
NewResourceF: func(args MockResourceArgs) (string, resource.PropertyMap, error) {
|
|
return args.Inputs["name"].StringValue(), resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
"name": "stack",
|
|
"outputs": outputs,
|
|
}), nil
|
|
},
|
|
}))
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestStackReferenceSecrets(t *testing.T) {
|
|
t.Parallel()
|
|
var resName string
|
|
|
|
expected := map[string]interface{}{
|
|
"foo": "bar",
|
|
"baz": []interface{}{"qux"},
|
|
"zed": map[string]interface{}{
|
|
"alpha": "beta",
|
|
},
|
|
"numf": 123.4,
|
|
"numi": 567.0,
|
|
|
|
"secret-foo": "bar",
|
|
"secret-baz": []interface{}{"qux"},
|
|
"secret-zed": map[string]interface{}{
|
|
"alpha": "beta",
|
|
},
|
|
"secret-numf": 123.4,
|
|
"secret-numi": 567.0,
|
|
}
|
|
|
|
properties := resource.PropertyMap{}
|
|
for k, v := range expected {
|
|
v := resource.NewPropertyValue(v)
|
|
if strings.HasPrefix(k, "secret-") {
|
|
v = resource.MakeSecret(v)
|
|
}
|
|
properties[resource.PropertyKey(k)] = v
|
|
}
|
|
|
|
outputs := resource.NewObjectProperty(properties)
|
|
|
|
mocks := &testMonitor{
|
|
NewResourceF: func(args MockResourceArgs) (string, resource.PropertyMap, error) {
|
|
assert.Equal(t, "pulumi:pulumi:StackReference", args.TypeToken)
|
|
assert.Equal(t, resName, args.Name)
|
|
assert.True(t, args.Inputs.DeepEquals(resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
"name": "stack",
|
|
})))
|
|
assert.Equal(t, "", args.Provider)
|
|
assert.Equal(t, args.Inputs["name"].StringValue(), args.ID)
|
|
return args.Inputs["name"].StringValue(), resource.PropertyMap{
|
|
"name": resource.NewStringProperty("stack"),
|
|
"outputs": outputs,
|
|
}, nil
|
|
},
|
|
}
|
|
err := RunErr(func(ctx *Context) error {
|
|
resName = "stack"
|
|
ref0, err := NewStackReference(ctx, resName, nil)
|
|
assert.NoError(t, err)
|
|
_, _, _, _, err = await(ref0.ID())
|
|
assert.NoError(t, err)
|
|
resName = "stack2"
|
|
ref1, err := NewStackReference(ctx, resName, &StackReferenceArgs{Name: String("stack")})
|
|
assert.NoError(t, err)
|
|
|
|
outs0, _, _, _, err := await(ref0.Outputs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, outs0)
|
|
outs1, _, _, _, err := await(ref1.Outputs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, outs1)
|
|
|
|
for _, ref := range []*StackReference{ref0, ref1} {
|
|
for k, v := range expected {
|
|
shouldSecret := strings.HasPrefix(k, "secret-")
|
|
|
|
outputV, known, secret, _, err := await(ref.GetOutput(String(k)))
|
|
assert.NoError(t, err)
|
|
assert.True(t, known)
|
|
assert.Equal(t, shouldSecret, secret)
|
|
assert.Equal(t, v, outputV)
|
|
}
|
|
|
|
outputV, known, secret, _, err := await(ref.GetOutput(String("nonexistant-key")))
|
|
assert.NoError(t, err)
|
|
assert.True(t, known)
|
|
assert.Equal(t, false, secret)
|
|
assert.Equal(t, nil, outputV)
|
|
}
|
|
|
|
return nil
|
|
}, WithMocks("project", "stack", mocks))
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestStackReference_GetOutputDetails(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
outputs := resource.PropertyMap{
|
|
"bucket": resource.NewStringProperty("mybucket-1234"),
|
|
"password": resource.NewSecretProperty(&resource.Secret{
|
|
Element: resource.NewStringProperty("supersecretpassword"),
|
|
}),
|
|
}
|
|
mocks := testMonitor{
|
|
NewResourceF: func(args MockResourceArgs) (string, resource.PropertyMap, error) {
|
|
assert.Equal(t, "pulumi:pulumi:StackReference", args.TypeToken)
|
|
assert.Equal(t, "ref", args.Name)
|
|
return args.Name, resource.PropertyMap{
|
|
"name": resource.NewStringProperty(args.Name),
|
|
"outputs": resource.NewObjectProperty(outputs),
|
|
}, nil
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
desc string
|
|
name string
|
|
want StackReferenceOutputDetails
|
|
}{
|
|
{
|
|
desc: "non secret",
|
|
name: "bucket",
|
|
want: StackReferenceOutputDetails{Value: "mybucket-1234"},
|
|
},
|
|
{
|
|
desc: "secret",
|
|
name: "password",
|
|
want: StackReferenceOutputDetails{SecretValue: "supersecretpassword"},
|
|
},
|
|
{
|
|
desc: "unknown",
|
|
name: "does-not-exist",
|
|
// want empty struct
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := RunErr(func(ctx *Context) error {
|
|
ref, err := NewStackReference(ctx, "ref", nil /* args */)
|
|
require.NoError(t, err)
|
|
|
|
got, err := ref.GetOutputDetails(tt.name)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, &tt.want, got)
|
|
|
|
return nil
|
|
}, WithMocks("proj", "stack", &mocks))
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|