* Make `async:true` the default for `invoke` calls (#3750) * Switch away from native grpc impl. (#3728) * Remove usage of the 'deasync' library from @pulumi/pulumi. (#3752) * Only retry as long as we get unavailable back. Anything else continues. (#3769) * Handle all errors for now. (#3781) * Do not assume --yes was present when using pulumi in non-interactive mode (#3793) * Upgrade all paths for sdk and pkg to v2 * Backport C# invoke classes and other recent gen changes (#4288) Adjust C# generation * Replace IDeployment with a sealed class (#4318) Replace IDeployment with a sealed class * .NET: default to args subtype rather than Args.Empty (#4320) * Adding system namespace for Dotnet code gen This is required for using Obsolute attributes for deprecations ``` Iam/InstanceProfile.cs(142,10): error CS0246: The type or namespace name 'ObsoleteAttribute' could not be found (are you missing a using directive or an assembly reference?) [/Users/stack72/code/go/src/github.com/pulumi/pulumi-aws/sdk/dotnet/Pulumi.Aws.csproj] Iam/InstanceProfile.cs(142,10): error CS0246: The type or namespace name 'Obsolete' could not be found (are you missing a using directive or an assembly reference?) [/Users/stack72/code/go/src/github.com/pulumi/pulumi-aws/sdk/dotnet/Pulumi.Aws.csproj] ``` * Fix the nullability of config type properties in C# codegen (#4379)
287 lines
9.7 KiB
Go
287 lines
9.7 KiB
Go
// Copyright 2016-2018, 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 plugin
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
|
|
structpb "github.com/golang/protobuf/ptypes/struct"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/resource"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
|
|
)
|
|
|
|
func setProperty(s *structpb.Value, k string, v interface{}) {
|
|
marshaled, err := MarshalPropertyValue(resource.NewPropertyValue(v), MarshalOptions{})
|
|
contract.Assert(err == nil)
|
|
s.GetStructValue().Fields[k] = marshaled
|
|
}
|
|
|
|
func TestAssetSerialize(t *testing.T) {
|
|
// Ensure that asset and archive serialization round trips.
|
|
text := "a test asset"
|
|
asset, err := resource.NewTextAsset(text)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, text, asset.Text)
|
|
assert.Equal(t, "e34c74529110661faae4e121e57165ff4cb4dbdde1ef9770098aa3695e6b6704", asset.Hash)
|
|
assetProps, err := MarshalPropertyValue(resource.NewAssetProperty(asset), MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
fmt.Printf("%v\n", assetProps)
|
|
assetValue, err := UnmarshalPropertyValue(assetProps, MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
assert.True(t, assetValue.IsAsset())
|
|
assetDes := assetValue.AssetValue()
|
|
assert.True(t, assetDes.IsText())
|
|
assert.Equal(t, text, assetDes.Text)
|
|
assert.Equal(t, "e34c74529110661faae4e121e57165ff4cb4dbdde1ef9770098aa3695e6b6704", assetDes.Hash)
|
|
|
|
// Ensure that an invalid asset produces an error.
|
|
setProperty(assetProps, resource.AssetHashProperty, 0)
|
|
_, err = UnmarshalPropertyValue(assetProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(assetProps, resource.AssetHashProperty, asset.Hash)
|
|
|
|
setProperty(assetProps, resource.AssetTextProperty, 0)
|
|
_, err = UnmarshalPropertyValue(assetProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(assetProps, resource.AssetTextProperty, "")
|
|
|
|
setProperty(assetProps, resource.AssetPathProperty, 0)
|
|
_, err = UnmarshalPropertyValue(assetProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(assetProps, resource.AssetPathProperty, "")
|
|
|
|
setProperty(assetProps, resource.AssetURIProperty, 0)
|
|
_, err = UnmarshalPropertyValue(assetProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(assetProps, resource.AssetURIProperty, "")
|
|
|
|
arch, err := resource.NewAssetArchive(map[string]interface{}{"foo": asset})
|
|
assert.Nil(t, err)
|
|
switch runtime.Version() {
|
|
case "go1.9":
|
|
assert.Equal(t, "d8ce0142b3b10300c7c76487fad770f794c1e84e1b0c73a4b2e1503d4fbac093", arch.Hash)
|
|
default:
|
|
// Go 1.10 introduced breaking changes to archive/zip and archive/tar headers
|
|
assert.Equal(t, "27ab4a14a617df10cff3e1cf4e30cf510302afe56bf4cc91f84041c9f7b62fd8", arch.Hash)
|
|
}
|
|
archProps, err := MarshalPropertyValue(resource.NewArchiveProperty(arch), MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
archValue, err := UnmarshalPropertyValue(archProps, MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
assert.True(t, archValue.IsArchive())
|
|
archDes := archValue.ArchiveValue()
|
|
assert.True(t, archDes.IsAssets())
|
|
assert.Equal(t, 1, len(archDes.Assets))
|
|
assert.True(t, archDes.Assets["foo"].(*resource.Asset).IsText())
|
|
assert.Equal(t, text, archDes.Assets["foo"].(*resource.Asset).Text)
|
|
switch runtime.Version() {
|
|
case "go1.9":
|
|
assert.Equal(t, "d8ce0142b3b10300c7c76487fad770f794c1e84e1b0c73a4b2e1503d4fbac093", archDes.Hash)
|
|
default:
|
|
// Go 1.10 introduced breaking changes to archive/zip and archive/tar headers
|
|
assert.Equal(t, "27ab4a14a617df10cff3e1cf4e30cf510302afe56bf4cc91f84041c9f7b62fd8", archDes.Hash)
|
|
}
|
|
|
|
// Ensure that an invalid archive produces an error.
|
|
setProperty(archProps, resource.ArchiveHashProperty, 0)
|
|
_, err = UnmarshalPropertyValue(archProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(archProps, resource.ArchiveHashProperty, arch.Hash)
|
|
|
|
setProperty(archProps, resource.ArchiveAssetsProperty, 0)
|
|
_, err = UnmarshalPropertyValue(archProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(archProps, resource.ArchiveAssetsProperty, nil)
|
|
|
|
setProperty(archProps, resource.ArchivePathProperty, 0)
|
|
_, err = UnmarshalPropertyValue(archProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(archProps, resource.ArchivePathProperty, "")
|
|
|
|
setProperty(archProps, resource.ArchiveURIProperty, 0)
|
|
_, err = UnmarshalPropertyValue(archProps, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
setProperty(archProps, resource.ArchiveURIProperty, "")
|
|
}
|
|
|
|
func TestComputedSerialize(t *testing.T) {
|
|
// Ensure that computed properties survive round trips.
|
|
opts := MarshalOptions{KeepUnknowns: true}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewStringProperty("")}), opts)
|
|
assert.Nil(t, err)
|
|
cpropU, err := UnmarshalPropertyValue(cprop, opts)
|
|
assert.Nil(t, err)
|
|
assert.True(t, cpropU.IsComputed())
|
|
assert.True(t, cpropU.Input().Element.IsString())
|
|
}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewNumberProperty(0)}), opts)
|
|
assert.Nil(t, err)
|
|
cpropU, err := UnmarshalPropertyValue(cprop, opts)
|
|
assert.Nil(t, err)
|
|
assert.True(t, cpropU.IsComputed())
|
|
assert.True(t, cpropU.Input().Element.IsNumber())
|
|
}
|
|
}
|
|
|
|
func TestComputedSkip(t *testing.T) {
|
|
// Ensure that computed properties are skipped when KeepUnknowns == false.
|
|
opts := MarshalOptions{KeepUnknowns: false}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewStringProperty("")}), opts)
|
|
assert.Nil(t, err)
|
|
assert.Nil(t, cprop)
|
|
}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewNumberProperty(0)}), opts)
|
|
assert.Nil(t, err)
|
|
assert.Nil(t, cprop)
|
|
}
|
|
}
|
|
|
|
func TestComputedReject(t *testing.T) {
|
|
// Ensure that computed properties produce errors when RejectUnknowns == true.
|
|
opts := MarshalOptions{RejectUnknowns: true}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewStringProperty("")}), opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, cprop)
|
|
}
|
|
{
|
|
cprop, err := MarshalPropertyValue(
|
|
resource.NewComputedProperty(
|
|
resource.Computed{Element: resource.NewStringProperty("")}), MarshalOptions{KeepUnknowns: true})
|
|
assert.Nil(t, err)
|
|
cpropU, err := UnmarshalPropertyValue(cprop, opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, cpropU)
|
|
}
|
|
}
|
|
|
|
func TestAssetReject(t *testing.T) {
|
|
// Ensure that asset and archive properties produce errors when RejectAssets == true.
|
|
|
|
opts := MarshalOptions{RejectAssets: true}
|
|
|
|
text := "a test asset"
|
|
asset, err := resource.NewTextAsset(text)
|
|
assert.Nil(t, err)
|
|
{
|
|
assetProps, err := MarshalPropertyValue(resource.NewAssetProperty(asset), opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, assetProps)
|
|
}
|
|
{
|
|
assetProps, err := MarshalPropertyValue(resource.NewAssetProperty(asset), MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
assetPropU, err := UnmarshalPropertyValue(assetProps, opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, assetPropU)
|
|
}
|
|
|
|
arch, err := resource.NewAssetArchive(map[string]interface{}{"foo": asset})
|
|
assert.Nil(t, err)
|
|
{
|
|
archProps, err := MarshalPropertyValue(resource.NewArchiveProperty(arch), opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, archProps)
|
|
}
|
|
{
|
|
archProps, err := MarshalPropertyValue(resource.NewArchiveProperty(arch), MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
archValue, err := UnmarshalPropertyValue(archProps, opts)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, archValue)
|
|
}
|
|
|
|
}
|
|
|
|
func TestUnsupportedSecret(t *testing.T) {
|
|
rawProp := resource.NewObjectProperty(resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
resource.SigKey: resource.SecretSig,
|
|
"value": "foo",
|
|
}))
|
|
prop, err := MarshalPropertyValue(rawProp, MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
val, err := UnmarshalPropertyValue(prop, MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
assert.True(t, val.IsString())
|
|
assert.False(t, val.IsSecret())
|
|
assert.Equal(t, "foo", val.StringValue())
|
|
}
|
|
|
|
func TestSupportedSecret(t *testing.T) {
|
|
rawProp := resource.NewObjectProperty(resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
resource.SigKey: resource.SecretSig,
|
|
"value": "foo",
|
|
}))
|
|
prop, err := MarshalPropertyValue(rawProp, MarshalOptions{KeepSecrets: true})
|
|
assert.Nil(t, err)
|
|
val, err := UnmarshalPropertyValue(prop, MarshalOptions{KeepSecrets: true})
|
|
assert.Nil(t, err)
|
|
assert.False(t, val.IsString())
|
|
assert.True(t, val.IsSecret())
|
|
assert.Equal(t, "foo", val.SecretValue().Element.StringValue())
|
|
}
|
|
|
|
func TestUnknownSig(t *testing.T) {
|
|
rawProp := resource.NewObjectProperty(resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
resource.SigKey: "foobar",
|
|
}))
|
|
prop, err := MarshalPropertyValue(rawProp, MarshalOptions{})
|
|
assert.Nil(t, err)
|
|
_, err = UnmarshalPropertyValue(prop, MarshalOptions{})
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
func TestSkipInternalKeys(t *testing.T) {
|
|
opts := MarshalOptions{SkipInternalKeys: true}
|
|
expected := &structpb.Struct{
|
|
Fields: map[string]*structpb.Value{
|
|
"keepers": {
|
|
Kind: &structpb.Value_StructValue{
|
|
StructValue: &structpb.Struct{
|
|
Fields: map[string]*structpb.Value{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
props := resource.NewPropertyMapFromMap(map[string]interface{}{
|
|
"__defaults": []string{},
|
|
"keepers": map[string]interface{}{
|
|
"__defaults": []string{},
|
|
},
|
|
})
|
|
actual, err := MarshalProperties(props, opts)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
}
|