diff --git a/pkg/internal/tests/cross-tests/diff_cross_test.go b/pkg/internal/tests/cross-tests/diff_cross_test.go index f47850243a..7536ea629f 100644 --- a/pkg/internal/tests/cross-tests/diff_cross_test.go +++ b/pkg/internal/tests/cross-tests/diff_cross_test.go @@ -1625,6 +1625,14 @@ func TestBlockCollectionElementForceNew(t *testing.T) { }) } +type diffTestOutput struct { + initialValue cty.Value + changeValue cty.Value + tfOut string + pulumiOut string + detailedDiff map[string]any +} + func TestDetailedDiffReplacementComputedProperty(t *testing.T) { t.Parallel() @@ -1649,14 +1657,6 @@ func TestDetailedDiffReplacementComputedProperty(t *testing.T) { }, } - type testOutput struct { - initialValue cty.Value - changeValue cty.Value - tfOut string - pulumiOut string - detailedDiff map[string]any - } - t.Run("no change", func(t *testing.T) { t.Parallel() initialValue := cty.ObjectVal(map[string]cty.Value{}) @@ -1667,7 +1667,7 @@ func TestDetailedDiffReplacementComputedProperty(t *testing.T) { Config2: changeValue, }) - autogold.ExpectFile(t, testOutput{ + autogold.ExpectFile(t, diffTestOutput{ initialValue: initialValue, changeValue: changeValue, tfOut: diff.TFOut, @@ -1686,7 +1686,7 @@ func TestDetailedDiffReplacementComputedProperty(t *testing.T) { Config2: changeValue, }) - autogold.ExpectFile(t, testOutput{ + autogold.ExpectFile(t, diffTestOutput{ initialValue: initialValue, changeValue: changeValue, tfOut: diff.TFOut, @@ -1705,7 +1705,7 @@ func TestDetailedDiffReplacementComputedProperty(t *testing.T) { Config2: changeValue, }) - autogold.ExpectFile(t, testOutput{ + autogold.ExpectFile(t, diffTestOutput{ initialValue: initialValue, changeValue: changeValue, tfOut: diff.TFOut, @@ -1724,7 +1724,118 @@ func TestDetailedDiffReplacementComputedProperty(t *testing.T) { Config2: changeValue, }) - autogold.ExpectFile(t, testOutput{ + autogold.ExpectFile(t, diffTestOutput{ + initialValue: initialValue, + changeValue: changeValue, + tfOut: diff.TFOut, + pulumiOut: diff.PulumiOut, + detailedDiff: diff.PulumiDiff.DetailedDiff, + }) + }) +} + +func TestPropertyWithDot(t *testing.T) { + t.Parallel() + // TODO[pulumi/pulumi-terraform-bridge#2669] + t.Skip("We currently fail to return the correct detailed diff for this case") + + res := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prop": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foo": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + } + + t.Run("unchanged", func(t *testing.T) { + t.Parallel() + initialValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{"foo.bar": cty.StringVal("baz")}), + }), + }) + changeValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{"foo.bar": cty.StringVal("baz")}), + }), + }) + diff := runDiffCheck(t, diffTestCase{ + Resource: res, + Config1: initialValue, + Config2: changeValue, + }) + + autogold.ExpectFile(t, diffTestOutput{ + initialValue: initialValue, + changeValue: changeValue, + tfOut: diff.TFOut, + pulumiOut: diff.PulumiOut, + detailedDiff: diff.PulumiDiff.DetailedDiff, + }) + }) + + t.Run("added", func(t *testing.T) { + t.Parallel() + initialValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("bar")}), + }), + }) + changeValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + "foo.bar": cty.StringVal("baz"), + }), + }), + }) + diff := runDiffCheck(t, diffTestCase{ + Resource: res, + Config1: initialValue, + Config2: changeValue, + }) + + autogold.ExpectFile(t, diffTestOutput{ + initialValue: initialValue, + changeValue: changeValue, + tfOut: diff.TFOut, + pulumiOut: diff.PulumiOut, + detailedDiff: diff.PulumiDiff.DetailedDiff, + }) + }) + + t.Run("deleted", func(t *testing.T) { + t.Parallel() + initialValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + "foo.bar": cty.StringVal("baz"), + }), + }), + }) + changeValue := cty.ObjectVal(map[string]cty.Value{ + "prop": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("bar")}), + }), + }) + diff := runDiffCheck(t, diffTestCase{ + Resource: res, + Config1: initialValue, + Config2: changeValue, + }) + + autogold.ExpectFile(t, diffTestOutput{ initialValue: initialValue, changeValue: changeValue, tfOut: diff.TFOut, diff --git a/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/added.golden b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/added.golden new file mode 100644 index 0000000000..aab5c5c115 --- /dev/null +++ b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/added.golden @@ -0,0 +1,44 @@ +crosstests.diffTestOutput{ + initialValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{"prop": { + typeImpl: cty.typeList{ElementTypeT: cty.Type{ + typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{ + "foo": {typeImpl: cty.primitiveType{ + Kind: cty.primitiveTypeKind(83), + }}, + }}, + }}, + }}, + }}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{"foo": "bar"}}}, + }, + changeValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{"prop": {typeImpl: cty.typeList{ + ElementTypeT: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{ + "foo": { + typeImpl: cty.primitiveType{Kind: cty.primitiveTypeKind(83)}, + }, + "foo.bar": {typeImpl: cty.primitiveType{Kind: cty.primitiveTypeKind(83)}}, + }, + }}, + }}}}}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{ + "foo": "bar", + "foo.bar": "baz", + }}}, + }, + tfOut: ` +No changes. Your infrastructure matches the configuration. + +Terraform has compared your real infrastructure against your configuration +and found no differences, so no changes are needed. +`, + pulumiOut: `Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::project::pulumi:pulumi:Stack::project-test] +Resources: + 2 unchanged +`, +} diff --git a/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/deleted.golden b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/deleted.golden new file mode 100644 index 0000000000..bd3964402f --- /dev/null +++ b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/deleted.golden @@ -0,0 +1,42 @@ +crosstests.diffTestOutput{ + initialValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{"prop": { + typeImpl: cty.typeList{ElementTypeT: cty.Type{ + typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{ + "foo": {typeImpl: cty.primitiveType{ + Kind: cty.primitiveTypeKind(83), + }}, + "foo.bar": {typeImpl: cty.primitiveType{Kind: cty.primitiveTypeKind(83)}}, + }}, + }}, + }}, + }}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{ + "foo": "bar", + "foo.bar": "baz", + }}}, + }, + changeValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{"prop": {typeImpl: cty.typeList{ + ElementTypeT: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{"foo": { + typeImpl: cty.primitiveType{Kind: cty.primitiveTypeKind(83)}, + }}, + }}, + }}}}}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{"foo": "bar"}}}, + }, + tfOut: ` +No changes. Your infrastructure matches the configuration. + +Terraform has compared your real infrastructure against your configuration +and found no differences, so no changes are needed. +`, + pulumiOut: `Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::project::pulumi:pulumi:Stack::project-test] +Resources: + 2 unchanged +`, +} diff --git a/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/unchanged.golden b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/unchanged.golden new file mode 100644 index 0000000000..be541fbc79 --- /dev/null +++ b/pkg/internal/tests/cross-tests/testdata/TestPropertyWithDot/unchanged.golden @@ -0,0 +1,38 @@ +crosstests.diffTestOutput{ + initialValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{"prop": { + typeImpl: cty.typeList{ElementTypeT: cty.Type{ + typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{ + "foo.bar": {typeImpl: cty.primitiveType{ + Kind: cty.primitiveTypeKind(83), + }}, + }}, + }}, + }}, + }}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{"foo.bar": "baz"}}}, + }, + changeValue: cty.Value{ + ty: cty.Type{typeImpl: cty.typeObject{AttrTypes: map[string]cty.Type{"prop": {typeImpl: cty.typeList{ + ElementTypeT: cty.Type{typeImpl: cty.typeObject{ + AttrTypes: map[string]cty.Type{"foo.bar": { + typeImpl: cty.primitiveType{Kind: cty.primitiveTypeKind(83)}, + }}, + }}, + }}}}}, + v: map[string]interface{}{"prop": []interface{}{map[string]interface{}{"foo.bar": "baz"}}}, + }, + tfOut: ` +No changes. Your infrastructure matches the configuration. + +Terraform has compared your real infrastructure against your configuration +and found no differences, so no changes are needed. +`, + pulumiOut: `Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::project::pulumi:pulumi:Stack::project-test] +Resources: + 2 unchanged +`, +} diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 5cba5ec1b1..782dd78819 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -2173,6 +2173,7 @@ type diffTestCase struct { } func diffTest2(t *testing.T, tc diffTestCase) { + t.Helper() ctx := context.Background() res := &v2Schema.Resource{ Schema: tc.resourceSchema, @@ -2275,3 +2276,42 @@ func TestChangingMaxItems1FilterProperty(t *testing.T) { }, }) } + +func TestPropertyWithDot(t *testing.T) { + t.Parallel() + // TODO[pulumi/pulumi-terraform-bridge#2669] + t.Skip("We currently fail to return the correct detailed diff for this case") + + schema := map[string]*v2Schema.Schema{ + "prop": { + Type: v2Schema.TypeMap, + Optional: true, + Elem: &v2Schema.Schema{ + Type: v2Schema.TypeString, + }, + }, + } + + diffTest2(t, diffTestCase{ + resourceSchema: schema, + state: resource.PropertyMap{ + "prop": resource.NewObjectProperty(resource.PropertyMap{ + "foo": resource.NewStringProperty("bar"), + }), + }, + inputs: resource.PropertyMap{ + "prop": resource.NewObjectProperty(resource.PropertyMap{ + "foo.bar": resource.NewStringProperty("baz"), + }), + }, + expectedDiffChanges: pulumirpc.DiffResponse_DIFF_SOME, + expected: map[string]*pulumirpc.PropertyDiff{ + "prop.foo": { + Kind: pulumirpc.PropertyDiff_DELETE, + }, + "prop[\"foo.bar\"]": { + Kind: pulumirpc.PropertyDiff_ADD, + }, + }, + }) +}