diff --git a/dynamic/go.sum b/dynamic/go.sum index f826d2b74..9edb2805a 100644 --- a/dynamic/go.sum +++ b/dynamic/go.sum @@ -795,8 +795,8 @@ github.com/pulumi/esc v0.10.0 h1:jzBKzkLVW0mePeanDRfqSQoCJ5yrkux0jIwAkUxpRKE= github.com/pulumi/esc v0.10.0/go.mod h1:2Bfa+FWj/xl8CKqRTWbWgDX0SOD4opdQgvYSURTGK2c= github.com/pulumi/inflector v0.1.1 h1:dvlxlWtXwOJTUUtcYDvwnl6Mpg33prhK+7mzeF+SobA= github.com/pulumi/inflector v0.1.1/go.mod h1:HUFCjcPTz96YtTuUlwG3i3EZG4WlniBvR9bd+iJxCUY= -github.com/pulumi/providertest v0.1.2 h1:9pJS9MeNkMyGwyNeHmvh8QqLgJy39Nk2/ym5u7r13ng= -github.com/pulumi/providertest v0.1.2/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= +github.com/pulumi/providertest v0.1.3 h1:GpNKRy/haNjRHiUA9bi4diU4Op2zf3axYXbga5AepHg= +github.com/pulumi/providertest v0.1.3/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= github.com/pulumi/pulumi-java/pkg v0.16.1 h1:orHnDWFbpOERwaBLry9f+6nqPX7x0MsrIkaa5QDGAns= github.com/pulumi/pulumi-java/pkg v0.16.1/go.mod h1:QH0DihZkWYle9XFc+LJ76m4hUo+fA3RdyaM90pqOaSM= github.com/pulumi/pulumi-yaml v1.11.1 h1:ULUL9fpb2Bwgf3jJHx0FamKYm0ld0KxBQr/uSAslRLk= diff --git a/go.mod b/go.mod index d11f04b1b..e97b8e08f 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 github.com/pkg/errors v0.9.1 github.com/pulumi/inflector v0.1.1 - github.com/pulumi/providertest v0.1.2 + github.com/pulumi/providertest v0.1.3 github.com/pulumi/pulumi-java/pkg v0.16.1 github.com/pulumi/pulumi-yaml v1.11.1 github.com/pulumi/schema-tools v0.1.2 diff --git a/go.sum b/go.sum index 87a52d56a..7bf9cbbdb 100644 --- a/go.sum +++ b/go.sum @@ -1930,8 +1930,8 @@ github.com/pulumi/esc v0.10.0 h1:jzBKzkLVW0mePeanDRfqSQoCJ5yrkux0jIwAkUxpRKE= github.com/pulumi/esc v0.10.0/go.mod h1:2Bfa+FWj/xl8CKqRTWbWgDX0SOD4opdQgvYSURTGK2c= github.com/pulumi/inflector v0.1.1 h1:dvlxlWtXwOJTUUtcYDvwnl6Mpg33prhK+7mzeF+SobA= github.com/pulumi/inflector v0.1.1/go.mod h1:HUFCjcPTz96YtTuUlwG3i3EZG4WlniBvR9bd+iJxCUY= -github.com/pulumi/providertest v0.1.2 h1:9pJS9MeNkMyGwyNeHmvh8QqLgJy39Nk2/ym5u7r13ng= -github.com/pulumi/providertest v0.1.2/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= +github.com/pulumi/providertest v0.1.3 h1:GpNKRy/haNjRHiUA9bi4diU4Op2zf3axYXbga5AepHg= +github.com/pulumi/providertest v0.1.3/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= github.com/pulumi/pulumi-java/pkg v0.16.1 h1:orHnDWFbpOERwaBLry9f+6nqPX7x0MsrIkaa5QDGAns= github.com/pulumi/pulumi-java/pkg v0.16.1/go.mod h1:QH0DihZkWYle9XFc+LJ76m4hUo+fA3RdyaM90pqOaSM= github.com/pulumi/pulumi-yaml v1.11.1 h1:ULUL9fpb2Bwgf3jJHx0FamKYm0ld0KxBQr/uSAslRLk= diff --git a/pf/go.sum b/pf/go.sum index d02b9d021..b8a7b904c 100644 --- a/pf/go.sum +++ b/pf/go.sum @@ -712,8 +712,8 @@ github.com/pulumi/esc v0.10.0 h1:jzBKzkLVW0mePeanDRfqSQoCJ5yrkux0jIwAkUxpRKE= github.com/pulumi/esc v0.10.0/go.mod h1:2Bfa+FWj/xl8CKqRTWbWgDX0SOD4opdQgvYSURTGK2c= github.com/pulumi/inflector v0.1.1 h1:dvlxlWtXwOJTUUtcYDvwnl6Mpg33prhK+7mzeF+SobA= github.com/pulumi/inflector v0.1.1/go.mod h1:HUFCjcPTz96YtTuUlwG3i3EZG4WlniBvR9bd+iJxCUY= -github.com/pulumi/providertest v0.1.2 h1:9pJS9MeNkMyGwyNeHmvh8QqLgJy39Nk2/ym5u7r13ng= -github.com/pulumi/providertest v0.1.2/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= +github.com/pulumi/providertest v0.1.3 h1:GpNKRy/haNjRHiUA9bi4diU4Op2zf3axYXbga5AepHg= +github.com/pulumi/providertest v0.1.3/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= github.com/pulumi/pulumi-java/pkg v0.16.1 h1:orHnDWFbpOERwaBLry9f+6nqPX7x0MsrIkaa5QDGAns= github.com/pulumi/pulumi-java/pkg v0.16.1/go.mod h1:QH0DihZkWYle9XFc+LJ76m4hUo+fA3RdyaM90pqOaSM= github.com/pulumi/pulumi-yaml v1.11.1 h1:ULUL9fpb2Bwgf3jJHx0FamKYm0ld0KxBQr/uSAslRLk= diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index f37eb33e4..a2e15f709 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -17,6 +17,7 @@ import ( "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/pulcheck" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/tfcheck" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info" shimv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2" "github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview" "github.com/pulumi/pulumi/sdk/v3/go/auto/optrefresh" @@ -4159,3 +4160,428 @@ func TestMakeTerraformResultNilVsEmptyMap(t *testing.T) { assert.True(t, props["test"].DeepEquals(emptyMap)) }) } + +func TestUnknownCollectionForceNewDetailedDiff(t *testing.T) { + // TODO: Remove this once accurate bridge previews are rolled out + t.Setenv("PULUMI_TF_BRIDGE_ACCURATE_BRIDGE_PREVIEW", "false") + collectionForceNewResource := func(typ schema.ValueType) *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test": { + Type: typ, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + } + } + + propertyForceNewResource := func(typ schema.ValueType) *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test": { + Type: typ, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + }, + } + } + + auxResource := func(typ schema.ValueType) *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "aux": { + Type: typ, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prop": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("aux") + err := d.Set("aux", []map[string]interface{}{{"prop": "aux"}}) + require.NoError(t, err) + return nil + }, + } + } + + initialProgram := ` + name: test + runtime: yaml + resources: + mainRes: + type: prov:index:Test + properties: + tests: [{prop: 'value'}] +` + + program := ` + name: test + runtime: yaml + resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:Test + properties: + tests: %s +` + + runTest := func(t *testing.T, program2 string, bridgedProvider info.Provider, expectedOutput autogold.Value) { + pt := pulcheck.PulCheck(t, bridgedProvider, initialProgram) + pt.Up(t) + pt.WritePulumiYaml(t, program2) + + res := pt.Preview(t, optpreview.Diff()) + + expectedOutput.Equal(t, res.StdOut) + } + + t.Run("list force new", func(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": collectionForceNewResource(schema.TypeList), + "prov_aux": auxResource(schema.TypeList), + } + + tfp := &schema.Provider{ResourcesMap: resMap} + bridgedProvider := pulcheck.BridgedProvider(t, "prov", tfp) + runTest := func(t *testing.T, program2 string, expectedOutput autogold.Value) { + runTest(t, program2, bridgedProvider, expectedOutput) + } + + t.Run("unknown plain property", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[{prop: \"${auxRes.auxes[0].prop}\"}]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + ~ [0]: { + ~ prop: "value" => output + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown object", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[\"${auxRes.auxes[0]}\"]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + - [0]: { + - prop: "value" + } + + [0]: output + ] +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown collection", func(t *testing.T) { + program2 := fmt.Sprintf(program, "\"${auxRes.auxes}\"") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + - tests: [ + - [0]: { + - prop: "value" + } + ] + + tests: output +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + }) + + t.Run("list property force new", func(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": propertyForceNewResource(schema.TypeList), + "prov_aux": auxResource(schema.TypeList), + } + + tfp := &schema.Provider{ResourcesMap: resMap} + bridgedProvider := pulcheck.BridgedProvider(t, "prov", tfp) + runTest := func(t *testing.T, program2 string, expectedOutput autogold.Value) { + runTest(t, program2, bridgedProvider, expectedOutput) + } + + t.Run("unknown plain property", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[{prop: \"${auxRes.auxes[0].prop}\"}]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + ~ [0]: { + ~ prop: "value" => output + } + ] +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown object", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[\"${auxRes.auxes[0]}\"]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + - [0]: { + - prop: "value" + } + + [0]: output + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown collection", func(t *testing.T) { + program2 := fmt.Sprintf(program, "\"${auxRes.auxes}\"") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + - tests: [ + - [0]: { + - prop: "value" + } + ] + + tests: output +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + }) + + t.Run("set force new", func(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": collectionForceNewResource(schema.TypeSet), + "prov_aux": auxResource(schema.TypeSet), + } + + tfp := &schema.Provider{ResourcesMap: resMap} + bridgedProvider := pulcheck.BridgedProvider(t, "prov", tfp) + runTest := func(t *testing.T, program2 string, expectedOutput autogold.Value) { + runTest(t, program2, bridgedProvider, expectedOutput) + } + + t.Run("unknown plain property", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[{prop: \"${auxRes.auxes[0].prop}\"}]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + ~ [0]: { + ~ prop: "value" => output + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown object", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[\"${auxRes.auxes[0]}\"]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + - [0]: { + - prop: "value" + } + + [0]: output + ] +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown collection", func(t *testing.T) { + program2 := fmt.Sprintf(program, "\"${auxRes.auxes}\"") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + - tests: [ + - [0]: { + - prop: "value" + } + ] + + tests: output +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + }) + + t.Run("set property force new", func(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": propertyForceNewResource(schema.TypeSet), + "prov_aux": auxResource(schema.TypeSet), + } + + tfp := &schema.Provider{ResourcesMap: resMap} + bridgedProvider := pulcheck.BridgedProvider(t, "prov", tfp) + runTest := func(t *testing.T, program2 string, expectedOutput autogold.Value) { + runTest(t, program2, bridgedProvider, expectedOutput) + } + + t.Run("unknown plain property", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[{prop: \"${auxRes.auxes[0].prop}\"}]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + +-prov:index/test:Test: (replace) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + ~ [0]: { + ~ prop: "value" => output + } + ] +Resources: + + 1 to create + +-1 to replace + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown object", func(t *testing.T) { + program2 := fmt.Sprintf(program, "[\"${auxRes.auxes[0]}\"]") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + ~ tests: [ + - [0]: { + - prop: "value" + } + + [0]: output + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + + t.Run("unknown collection", func(t *testing.T) { + program2 := fmt.Sprintf(program, "\"${auxRes.auxes}\"") + runTest(t, program2, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + + prov:index/aux:Aux: (create) + [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + ~ prov:index/test:Test: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + - tests: [ + - [0]: { + - prop: "value" + } + ] + + tests: output +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`)) + }) + }) +} diff --git a/x/muxer/go.mod b/x/muxer/go.mod index 04324e372..eecb23ec5 100644 --- a/x/muxer/go.mod +++ b/x/muxer/go.mod @@ -7,7 +7,7 @@ toolchain go1.23.1 replace github.com/pulumi/pulumi-terraform-bridge/v3 => ../../ require ( - github.com/pulumi/providertest v0.1.2 + github.com/pulumi/providertest v0.1.3 github.com/pulumi/pulumi-terraform-bridge/v3 v3.0.0-00010101000000-000000000000 github.com/stretchr/testify v1.9.0 google.golang.org/protobuf v1.34.2 diff --git a/x/muxer/go.sum b/x/muxer/go.sum index 9c575a1e3..599fd9fff 100644 --- a/x/muxer/go.sum +++ b/x/muxer/go.sum @@ -154,8 +154,8 @@ github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435 github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE= github.com/pulumi/esc v0.10.0 h1:jzBKzkLVW0mePeanDRfqSQoCJ5yrkux0jIwAkUxpRKE= github.com/pulumi/esc v0.10.0/go.mod h1:2Bfa+FWj/xl8CKqRTWbWgDX0SOD4opdQgvYSURTGK2c= -github.com/pulumi/providertest v0.1.2 h1:9pJS9MeNkMyGwyNeHmvh8QqLgJy39Nk2/ym5u7r13ng= -github.com/pulumi/providertest v0.1.2/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= +github.com/pulumi/providertest v0.1.3 h1:GpNKRy/haNjRHiUA9bi4diU4Op2zf3axYXbga5AepHg= +github.com/pulumi/providertest v0.1.3/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= github.com/pulumi/pulumi/pkg/v3 v3.137.0 h1:/KPFQQaB5W0/GhVxSTGnEzv3ZW5uieGN5Q2q+Lsr+Zw= github.com/pulumi/pulumi/pkg/v3 v3.137.0/go.mod h1:ZQXJUTysDwq/mtilutRBKguH6DI+3b2WgNcOrs0whJ0= github.com/pulumi/pulumi/sdk/v3 v3.137.0 h1:bxhYpOY7Z4xt+VmezEpHuhjpOekkaMqOjzxFg/1OhCw=