From 63a9bffebc7218b59ad48218e77bfa9a99c78b34 Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 4 Jun 2024 17:08:42 +0100 Subject: [PATCH 01/52] unknown tests --- pkg/tfbridge/provider_test.go | 1043 +++++++++++++++++++++++++++++++++ 1 file changed, 1043 insertions(+) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 77ec0ee14..3519a6439 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -4535,3 +4535,1046 @@ func TestPlanResourceChangeStateUpgrade(t *testing.T) { } }`) } + +func UnknownsSchema() map[string]*schemav2.Resource { + return map[string]*schemav2.Resource{ + "example_resource": { + Schema: map[string]*schemav2.Schema{ + "set_prop": { + Type: schema.TypeSet, + Optional: true, + Elem: &schemav2.Schema{Type: schemav2.TypeString}, + }, + "set_block_prop": { + Type: schema.TypeSet, + Optional: true, + Elem: &schemav2.Resource{ + Schema: map[string]*schemav2.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "string_prop": { + Type: schema.TypeString, + Optional: true, + }, + "list_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Schema{Type: schemav2.TypeString}, + }, + "list_block_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Resource{ + Schema: map[string]*schemav2.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "nested_list_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Schema{Type: schemav2.TypeString}, + }, + }, + "nested_list_block_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Resource{ + Schema: map[string]*schemav2.Schema{ + "nested_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schemav2.Resource{ + Schema: map[string]*schemav2.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "max_items_one_prop": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schemav2.Schema{Type: schemav2.TypeString}, + }, + "max_items_one_block_prop": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schemav2.Resource{ + Schema: map[string]*schemav2.Schema{ + "prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + } +} + +func TestUnknowns(t *testing.T) { + // Related to [pulumi/pulumi-terraform-bridge#1885] + p := &schemav2.Provider{ + Schema: map[string]*schemav2.Schema{}, + ResourcesMap: UnknownsSchema(), + } + shimProv := shimv2.NewProvider(p, shimv2.WithPlanResourceChange(func(tfResourceType string) bool { return false })) + provider := &Provider{ + tf: shimProv, + config: shimv2.NewSchemaMap(p.Schema), + info: ProviderInfo{ + P: shimProv, + ResourcePrefix: "example", + Resources: map[string]*ResourceInfo{ + "example_resource": {Tok: "ExampleResource"}, + }, + }, + } + provider.initResourceMaps() + + t.Run("unknown for string prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "string_prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for set prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for set block prop subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for set block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for set block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "setBlockProps":[{"prop":""}] + } + } + }`) + }) + + t.Run("unknown for list prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id": "" + } + } + }`) + }) + + t.Run("unknown for list block prop subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "listBlockProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + } + } + }`) + }) + + t.Run("unknown for list block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for list block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "listBlockProps":[null] + } + } + }`) + }) + + t.Run("unknown for nested list prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListProps":[["04da6b54-80e4-46f7-96ec-b56ff0331ba9"]] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "nestedListProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + } + } + }`) + }) + + t.Run("unknown for nested list block prop nested subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}]}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "nestedListBlockProps":[{"nestedProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}]}] + } + } + }`) + }) + + t.Run("unknown for nested list block nested prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"]}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "nestedListBlockProps":[{"nestedProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + } + } + }`) + }) + + t.Run("unknown for nested list block prop nested collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "nestedListBlockProps":[{"nestedProps":[null]}] + } + } + }`) + }) + + t.Run("unknown for nested list block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for nested list block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "nestedListBlockProps":[null] + } + } + }`) + }) + + t.Run("unknown for max items one prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) + + t.Run("unknown for max items one block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneBlockProp":{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"} + }, + "preview":true + }, + "response": { + "properties":{ + "id":"", + "maxItemsOneBlockProp": {"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"} + } + } + }`) + }) + + t.Run("unknown for max items one block", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneBlockProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"" + } + } + }`) + }) +} + +func TestPlanResourceChangeUnknowns(t *testing.T) { + // Related to [pulumi/pulumi-terraform-bridge#1885] + p := &schemav2.Provider{ + Schema: map[string]*schemav2.Schema{}, + ResourcesMap: UnknownsSchema(), + } + shimProv := shimv2.NewProvider(p, shimv2.WithPlanResourceChange(func(tfResourceType string) bool { return true })) + provider := &Provider{ + tf: shimProv, + config: shimv2.NewSchemaMap(p.Schema), + info: ProviderInfo{ + P: shimProv, + ResourcePrefix: "example", + Resources: map[string]*ResourceInfo{ + "example_resource": {Tok: "ExampleResource"}, + }, + }, + } + provider.initResourceMaps() + + t.Run("unknown for string prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "string_prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for set prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for set block prop subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[{ + "prop": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for set block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[{"prop":""}], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for set block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[{"prop":""}], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for list prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "maxItemsOneProp":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for list block prop subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[{ + "prop": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for list block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for list block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "listBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[{ "prop": null }], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListProps":[["04da6b54-80e4-46f7-96ec-b56ff0331ba9"]] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "maxItemsOneProp":null, + "nestedListProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"], + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list block prop nested subprop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":[{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}]}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[{ + "nestedProps": [ + {"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"} + ] + }], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list block prop nested prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"]}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[{ + "nestedProps": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list block prop nested collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":[{"nestedProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[{ + "nestedProps": [{"prop":null}] + }], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for nested list block collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "nestedListBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[{"nestedProps":null}], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for max items one prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":null + } + } + }`) + }) + + t.Run("unknown for max items one block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneBlockProp":{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"} + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":{"prop":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"} + } + } + }`) + }) + + t.Run("unknown for max items one block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "properties":{ + "__defaults":[], + "maxItemsOneBlockProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "preview":true + }, + "response": { + "properties":{ + "id":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "stringProp":null, + "setProps":null, + "listProps":null, + "nestedListProps":null, + "maxItemsOneProp":null, + "setBlockProps":[], + "listBlockProps":[], + "nestedListBlockProps":[], + "maxItemsOneBlockProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + } + } + }`) + }) +} From 1c3797a73e5fc60532da91b055f94cbcd1b3f2c2 Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 4 Jun 2024 17:29:06 +0100 Subject: [PATCH 02/52] rename accidentally repeated test name --- pkg/tfbridge/provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 3519a6439..8d88e64f0 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5520,7 +5520,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }`) }) - t.Run("unknown for max items one block prop", func(t *testing.T) { + t.Run("unknown for max items one block subprop", func(t *testing.T) { testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", From 9cca15cb6de1437459fa9f22884d28bf585fb200 Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 4 Jun 2024 18:16:47 +0100 Subject: [PATCH 03/52] add description for the tests --- pkg/tfbridge/provider_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 8d88e64f0..c893d66ac 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -4633,6 +4633,19 @@ func UnknownsSchema() map[string]*schemav2.Resource { func TestUnknowns(t *testing.T) { // Related to [pulumi/pulumi-terraform-bridge#1885] + // This test is to ensure that we can handle unknowns in the schema. + // Note that the behaviour here might not match TF and can NOT match TF completely + // as HCL has no way of expressing unknown blocks. + // We currently have a workaround in makeTerraformInputs where we convert unknown blocks + // to blocks of unknown. + // + // The structure is that for each property we inject an unknown at every level. + // For the block tests: + // _subprop is an unknown for the subproperty in the block object + // _prop is an unknown for the whole block + // _collection is an unknown for the whole collection + // The nested match the above convention but also iterate over the nested object. + p := &schemav2.Provider{ Schema: map[string]*schemav2.Schema{}, ResourcesMap: UnknownsSchema(), @@ -5023,6 +5036,19 @@ func TestUnknowns(t *testing.T) { func TestPlanResourceChangeUnknowns(t *testing.T) { // Related to [pulumi/pulumi-terraform-bridge#1885] + // This test is to ensure that we can handle unknowns in the schema. + // Note that the behaviour here might not match TF and can NOT match TF completely + // as HCL has no way of expressing unknown blocks. + // We currently have a workaround in makeTerraformInputs where we convert unknown blocks + // to blocks of unknown. + // + // The structure is that for each property we inject an unknown at every level. + // For the block tests: + // _subprop is an unknown for the subproperty in the block object + // _prop is an unknown for the whole block + // _collection is an unknown for the whole collection + // The nested match the above convention but also iterate over the nested object. + p := &schemav2.Provider{ Schema: map[string]*schemav2.Schema{}, ResourcesMap: UnknownsSchema(), From 989d6f16b95b7e944107e9df55b8fafa9d62b1e5 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 12:09:11 +0100 Subject: [PATCH 04/52] correct test case --- pkg/tfbridge/provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index c893d66ac..4193f392c 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5194,7 +5194,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", "properties":{ "__defaults":[], - "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" }, "preview":true }, From d77e1a0cbb53b5877e0b44ae7f036de38148b5a5 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 12:10:09 +0100 Subject: [PATCH 05/52] fix proposed new unknown blocks --- pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go b/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go index 137ee6564..50c95c4a4 100755 --- a/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go +++ b/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go @@ -69,6 +69,9 @@ func PlannedDataResourceObject(schema *configschema.Block, config cty.Value) cty } func proposedNew(schema *configschema.Block, prior, config cty.Value) cty.Value { + if !config.IsKnown() { + return config + } if config.IsNull() || !config.IsKnown() { // A block config should never be null at this point. The only nullable // block type is NestingSingle, which will return early before coming From c76fba88ed0bfa3eaa7b7eac77950ff4b0b53a61 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 12:14:04 +0100 Subject: [PATCH 06/52] correct set test --- pkg/tfbridge/provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 4193f392c..90ae3bb83 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5177,7 +5177,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "listProps":null, "nestedListProps":null, "maxItemsOneProp":null, - "setBlockProps":[{"prop":""}], + "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", "listBlockProps":[], "nestedListBlockProps":[], "maxItemsOneBlockProp":null From 143b87b633cfb012192212ac7b8b2657cf30baf7 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 12:15:15 +0100 Subject: [PATCH 07/52] remove duplicated known check --- pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go b/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go index 50c95c4a4..65bed2c93 100755 --- a/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go +++ b/pkg/tfshim/sdk-v2/internal/tf/plans/objchange/objchange.go @@ -72,7 +72,7 @@ func proposedNew(schema *configschema.Block, prior, config cty.Value) cty.Value if !config.IsKnown() { return config } - if config.IsNull() || !config.IsKnown() { + if config.IsNull() { // A block config should never be null at this point. The only nullable // block type is NestingSingle, which will return early before coming // back here. We'll allow the null here anyway to free callers from From 8257844d9d0f4f3b917410b0e50576ea82648d4f Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 13:02:37 +0100 Subject: [PATCH 08/52] add check test --- pkg/tfbridge/provider_test.go | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 90ae3bb83..041a5910c 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5604,3 +5604,46 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }`) }) } + + +func TestCheckPlanResourceChangeUnknowns(t *testing.T) { + p := &schemav2.Provider{ + Schema: map[string]*schemav2.Schema{}, + ResourcesMap: UnknownsSchema(), + } + shimProv := shimv2.NewProvider(p, shimv2.WithPlanResourceChange(func(tfResourceType string) bool { return true })) + provider := &Provider{ + tf: shimProv, + config: shimv2.NewSchemaMap(p.Schema), + info: ProviderInfo{ + P: shimProv, + ResourcePrefix: "example", + Resources: map[string]*ResourceInfo{ + "example_resource": {Tok: "ExampleResource"}, + }, + }, + } + provider.initResourceMaps() + + t.Run("unknown for set block prop collection", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Check", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "olds": {}, + "news":{ + "__defaults":[], + "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" + }, + "response": { + "inputs":{ + "__defaults":[], + "setBlockProps":[{}] + } + } + }`) + }) +} From 2146474c05a47ac3010542bb9c9e5cdf67899cbf Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 13:55:57 +0100 Subject: [PATCH 09/52] fix unknown collection of obj --- pkg/tfbridge/provider_test.go | 56 +++++++++++++++++++++++++++++++---- pkg/tfbridge/schema.go | 10 +------ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 041a5910c..c1ec602a4 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5206,7 +5206,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "listProps":null, "nestedListProps":null, "maxItemsOneProp":null, - "setBlockProps":[{"prop":""}], + "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", "listBlockProps":[], "nestedListBlockProps":[], "maxItemsOneBlockProp":null @@ -5326,7 +5326,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "nestedListProps":null, "maxItemsOneProp":null, "setBlockProps":[], - "listBlockProps":[{ "prop": null }], + "listBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", "nestedListBlockProps":[], "maxItemsOneBlockProp":null } @@ -5451,7 +5451,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "setBlockProps":[], "listBlockProps":[], "nestedListBlockProps":[{ - "nestedProps": [{"prop":null}] + "nestedProps": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" }], "maxItemsOneBlockProp":null } @@ -5510,7 +5510,7 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { "maxItemsOneProp":null, "setBlockProps":[], "listBlockProps":[], - "nestedListBlockProps":[{"nestedProps":null}], + "nestedListBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9", "maxItemsOneBlockProp":null } } @@ -5605,7 +5605,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) } - func TestCheckPlanResourceChangeUnknowns(t *testing.T) { p := &schemav2.Provider{ Schema: map[string]*schemav2.Schema{}, @@ -5625,6 +5624,29 @@ func TestCheckPlanResourceChangeUnknowns(t *testing.T) { } provider.initResourceMaps() + // TODO Finish these, maybe add to above tests + t.Run("unknown for set block prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Check", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "olds": {}, + "news":{ + "__defaults":[], + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + }, + "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" + }, + "response": { + "inputs":{ + "__defaults":[], + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] + } + } + }`) + }) + t.Run("unknown for set block prop collection", func(t *testing.T) { testutils.Replay(t, provider, ` { @@ -5641,9 +5663,31 @@ func TestCheckPlanResourceChangeUnknowns(t *testing.T) { "response": { "inputs":{ "__defaults":[], - "setBlockProps":[{}] + "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] } } }`) }) + + // t.Run("unknown for string prop", func(t *testing.T) { + // testutils.Replay(t, provider, ` + // { + // "method": "/pulumirpc.ResourceProvider/Check", + // "request": { + // "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + // "olds": {}, + // "news":{ + // "__defaults":[], + // "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + // }, + // "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" + // }, + // "response": { + // "inputs":{ + // "__defaults":[], + // "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + // } + // } + // }`) + // }) } diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index c8eefa3d3..3f704e48e 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -972,15 +972,7 @@ func makeTerraformUnknownElement(elem interface{}) interface{} { // If the element uses a normal schema, defer to makeTerraformUnknown. return makeTerraformUnknown(e) case shim.Resource: - // If the element uses a resource schema, fill in unknown values for any required properties. - res := make(map[string]interface{}) - e.Schema().Range(func(k string, v shim.Schema) bool { - if v.Required() { - res[k] = makeTerraformUnknown(v) - } - return true - }) - return res + return TerraformUnknownVariableValue default: return TerraformUnknownVariableValue } From 6ae7900eedd4c14dfb403c32d2624832ba527d38 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 14:00:12 +0100 Subject: [PATCH 10/52] uncomment test --- pkg/tfbridge/provider_test.go | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index c1ec602a4..d8a06128f 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5669,25 +5669,25 @@ func TestCheckPlanResourceChangeUnknowns(t *testing.T) { }`) }) - // t.Run("unknown for string prop", func(t *testing.T) { - // testutils.Replay(t, provider, ` - // { - // "method": "/pulumirpc.ResourceProvider/Check", - // "request": { - // "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", - // "olds": {}, - // "news":{ - // "__defaults":[], - // "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" - // }, - // "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" - // }, - // "response": { - // "inputs":{ - // "__defaults":[], - // "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" - // } - // } - // }`) - // }) + t.Run("unknown for string prop", func(t *testing.T) { + testutils.Replay(t, provider, ` + { + "method": "/pulumirpc.ResourceProvider/Check", + "request": { + "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", + "olds": {}, + "news":{ + "__defaults":[], + "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" + }, + "response": { + "inputs":{ + "__defaults":[], + "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" + } + } + }`) + }) } From 9ebe3395b36f3b435990b41ba7e25cbac8e1528f Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 5 Jun 2024 14:02:58 +0100 Subject: [PATCH 11/52] fix non prc tests --- pkg/tfbridge/provider_test.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index d8a06128f..1960891fc 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -4758,8 +4758,7 @@ func TestUnknowns(t *testing.T) { }, "response": { "properties":{ - "id":"", - "setBlockProps":[{"prop":""}] + "id":"" } } }`) @@ -4840,8 +4839,7 @@ func TestUnknowns(t *testing.T) { }, "response": { "properties":{ - "id":"", - "listBlockProps":[null] + "id":"" } } }`) @@ -4925,7 +4923,7 @@ func TestUnknowns(t *testing.T) { "response": { "properties":{ "id":"", - "nestedListBlockProps":[{"nestedProps":[null]}] + "nestedListBlockProps":[{"nestedProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9"}] } } }`) @@ -4965,8 +4963,7 @@ func TestUnknowns(t *testing.T) { }, "response": { "properties":{ - "id":"", - "nestedListBlockProps":[null] + "id":"" } } }`) From f59612485b891161fab17d49e4142a8b54833c5d Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 25 Jun 2024 20:22:17 +0300 Subject: [PATCH 12/52] support all types of unknowns --- pkg/tests/schema_pulumi_test.go | 101 ++++++++++++++++++++++++++++++++ pkg/tfbridge/schema.go | 41 +------------ 2 files changed, 103 insertions(+), 39 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index aeeb70f32..315594d19 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -684,3 +684,104 @@ outputs: }) } } + +func TestUnknownBlocks(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": { + Schema: map[string]*schema.Schema{ + "test": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + "prov_aux": { + Schema: map[string]*schema.Schema{ + "aux": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("aux") + err := d.Set("aux", []map[string]interface{}{{"test_prop": "aux"}}) + require.NoError(t, err) + return nil + }, + }, + } + bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) + + t.Run("list of objects", func(t *testing.T) { + program := ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:Test + properties: + tests: ${auxRes.auxes} +outputs: + testOut: ${mainRes.tests} +` + pt := pulcheck.PulCheck(t, bridgedProvider, program) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + // Test that the test property is unknown at preview time. + // Note that the property is output instead of + // output> - this is due to an engine limitation. + require.Contains(t, res.StdOut, "tests : output") + resUp := pt.Up() + // assert that the property gets resolved + require.Equal(t, + []interface{}{map[string]interface{}{"testProp": "aux"}}, + resUp.Outputs["testOut"].Value, + ) + }) + + t.Run("unknown object", func(t *testing.T) { + program := ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:Test + properties: + tests: + - ${auxRes.auxes[0]} +outputs: + testOut: ${mainRes.tests[0]} +` + pt := pulcheck.PulCheck(t, bridgedProvider, program) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + // Test that the test property is unknown at preview time. + // Note that the property is output instead of + // output - this is due to an engine limitation. + require.Contains(t, res.StdOut, "[0]: output") + resUp := pt.Up() + // assert that the property gets resolved + require.Equal(t, map[string]interface{}{"testProp": "aux"}, resUp.Outputs["testOut"].Value) + }) +} diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index 3f704e48e..8fce7608a 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -959,49 +959,12 @@ func (ctx *conversionContext) applyDefaults( return nil } -// makeTerraformUnknownElement creates an unknown value to be used as an element of a list or set using the given -// element schema to guide the shape of the value. -func makeTerraformUnknownElement(elem interface{}) interface{} { - // If we have no element schema, just return a simple unknown. - if elem == nil { - return TerraformUnknownVariableValue - } - - switch e := elem.(type) { - case shim.Schema: - // If the element uses a normal schema, defer to makeTerraformUnknown. - return makeTerraformUnknown(e) - case shim.Resource: - return TerraformUnknownVariableValue - default: - return TerraformUnknownVariableValue - } -} - // makeTerraformUnknown creates an unknown value with the shape indicated by the given schema. // // It is important that we use the TF schema (if available) to decide what shape the unknown value should have: // e.g. TF does not play nicely with unknown lists, instead expecting a list of unknowns. -func makeTerraformUnknown(tfs shim.Schema) interface{} { - if tfs == nil { - return TerraformUnknownVariableValue - } - - switch tfs.Type() { - case shim.TypeList, shim.TypeSet: - // TF does not accept unknown lists or sets. Instead, it accepts lists or sets of unknowns. - count := 1 - if tfs.MinItems() > 0 { - count = tfs.MinItems() - } - arr := make([]interface{}, count) - for i := range arr { - arr[i] = makeTerraformUnknownElement(tfs.Elem()) - } - return arr - default: - return TerraformUnknownVariableValue - } +func makeTerraformUnknown(_ shim.Schema) interface{} { + return TerraformUnknownVariableValue } // metaKey is the key in a TF bridge result that is used to store a resource's meta-attributes. From a572732bef3e118f54702a94c38a3cdac2a0a82f Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 25 Jun 2024 20:31:14 +0300 Subject: [PATCH 13/52] use autogold for the cli output --- pkg/tests/schema_pulumi_test.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 315594d19..e86029d44 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hexops/autogold/v2" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/internal/pulcheck" "github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview" "github.com/pulumi/pulumi/sdk/v3/go/auto/optrefresh" @@ -749,7 +750,19 @@ outputs: // Test that the test property is unknown at preview time. // Note that the property is output instead of // output> - this is due to an engine limitation. - require.Contains(t, res.StdOut, "tests : output") + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : output + --outputs:-- + testOut: output +Resources: + + 3 to create +`).Equal(t, res.StdOut) resUp := pt.Up() // assert that the property gets resolved require.Equal(t, @@ -779,7 +792,21 @@ outputs: // Test that the test property is unknown at preview time. // Note that the property is output instead of // output - this is due to an engine limitation. - require.Contains(t, res.StdOut, "[0]: output") + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : [ + [0]: output + ] + --outputs:-- + testOut: output +Resources: + + 3 to create +`).Equal(t, res.StdOut) resUp := pt.Up() // assert that the property gets resolved require.Equal(t, map[string]interface{}{"testProp": "aux"}, resUp.Outputs["testOut"].Value) From e5f09089c2e6dd14e751a180ee8991c046af30b0 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 26 Jun 2024 16:47:08 +0300 Subject: [PATCH 14/52] lint --- pkg/tfbridge/provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index c4048f6a7..998194e5b 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5803,4 +5803,4 @@ func TestCheckPlanResourceChangeUnknowns(t *testing.T) { } }`) }) -} \ No newline at end of file +} From a322aac3cfaa3c8bbcce84ef04a31850805306eb Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 26 Jun 2024 16:54:22 +0300 Subject: [PATCH 15/52] add test with unknown and known in a list --- pkg/tests/schema_pulumi_test.go | 45 ++++++++++++++++ pkg/tfbridge/provider_test.go | 92 --------------------------------- 2 files changed, 45 insertions(+), 92 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index e86029d44..5147560d5 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -806,6 +806,51 @@ outputs: testOut: output Resources: + 3 to create +`).Equal(t, res.StdOut) + resUp := pt.Up() + // assert that the property gets resolved + require.Equal(t, map[string]interface{}{"testProp": "aux"}, resUp.Outputs["testOut"].Value) + }) + + t.Run("unknown object with others", func(t *testing.T) { + program := ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:Test + properties: + tests: + - ${auxRes.auxes[0]} + - {"testProp": "val"} +outputs: + testOut: ${mainRes.tests[0]} +` + pt := pulcheck.PulCheck(t, bridgedProvider, program) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + // Test that the test property is unknown at preview time. + // Note that the property is output instead of + // output - this is due to an engine limitation. + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : [ + [0]: output + [1]: { + testProp : "val" + } + ] + --outputs:-- + testOut: output +Resources: + + 3 to create `).Equal(t, res.StdOut) resUp := pt.Up() // assert that the property gets resolved diff --git a/pkg/tfbridge/provider_test.go b/pkg/tfbridge/provider_test.go index 998194e5b..2bce25a3f 100644 --- a/pkg/tfbridge/provider_test.go +++ b/pkg/tfbridge/provider_test.go @@ -5165,7 +5165,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) t.Run("unknown for set block prop", func(t *testing.T) { - // TODO[pulumi/pulumi-terraform-bridge#1885] testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", @@ -5195,7 +5194,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) t.Run("unknown for set block prop collection", func(t *testing.T) { - // TODO[pulumi/pulumi-terraform-bridge#1885] testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", @@ -5317,7 +5315,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) t.Run("unknown for list block prop collection", func(t *testing.T) { - // TODO[pulumi/pulumi-terraform-bridge#1885] testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", @@ -5442,7 +5439,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) t.Run("unknown for nested list block prop nested collection", func(t *testing.T) { - // TODO[pulumi/pulumi-terraform-bridge#1885] testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", @@ -5504,7 +5500,6 @@ func TestPlanResourceChangeUnknowns(t *testing.T) { }) t.Run("unknown for nested list block collection", func(t *testing.T) { - // TODO[pulumi/pulumi-terraform-bridge#1885] testutils.Replay(t, provider, ` { "method": "/pulumirpc.ResourceProvider/Create", @@ -5717,90 +5712,3 @@ func TestSetDuplicatedDiffEntries(t *testing.T) { } }`) } - -func TestCheckPlanResourceChangeUnknowns(t *testing.T) { - p := &schemav2.Provider{ - Schema: map[string]*schemav2.Schema{}, - ResourcesMap: UnknownsSchema(), - } - shimProv := shimv2.NewProvider(p, shimv2.WithPlanResourceChange(func(tfResourceType string) bool { return true })) - provider := &Provider{ - tf: shimProv, - config: shimv2.NewSchemaMap(p.Schema), - info: ProviderInfo{ - P: shimProv, - ResourcePrefix: "example", - Resources: map[string]*ResourceInfo{ - "example_resource": {Tok: "ExampleResource"}, - }, - }, - } - provider.initResourceMaps() - - // TODO Finish these, maybe add to above tests - t.Run("unknown for set block prop", func(t *testing.T) { - testutils.Replay(t, provider, ` - { - "method": "/pulumirpc.ResourceProvider/Check", - "request": { - "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", - "olds": {}, - "news":{ - "__defaults":[], - "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] - }, - "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" - }, - "response": { - "inputs":{ - "__defaults":[], - "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] - } - } - }`) - }) - - t.Run("unknown for set block prop collection", func(t *testing.T) { - testutils.Replay(t, provider, ` - { - "method": "/pulumirpc.ResourceProvider/Check", - "request": { - "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", - "olds": {}, - "news":{ - "__defaults":[], - "setBlockProps":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" - }, - "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" - }, - "response": { - "inputs":{ - "__defaults":[], - "setBlockProps":["04da6b54-80e4-46f7-96ec-b56ff0331ba9"] - } - } - }`) - }) - - t.Run("unknown for string prop", func(t *testing.T) { - testutils.Replay(t, provider, ` - { - "method": "/pulumirpc.ResourceProvider/Check", - "request": { - "urn": "urn:pulumi:dev::teststack::ExampleResource::exres", - "olds": {}, - "news":{ - "__defaults":[], - "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" - }, - "randomSeed": "ROwbJVHmCcN8pilnAHgl2qU626UEO6pWtcnBFUc63uY=" - }, - "response": { - "inputs":{ - "__defaults":[], - "stringProp":"04da6b54-80e4-46f7-96ec-b56ff0331ba9" - } - } - }`) - }) -} From d980b07a6299166fa3668861767bc9935649f7dc Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 26 Jun 2024 17:50:37 +0300 Subject: [PATCH 16/52] nested tests --- pkg/tests/schema_pulumi_test.go | 348 ++++++++++++++++++++++++++------ 1 file changed, 286 insertions(+), 62 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 5147560d5..34e66fbb9 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -704,6 +704,33 @@ func TestUnknownBlocks(t *testing.T) { }, }, }, + "prov_nested_test": { + Schema: map[string]*schema.Schema{ + "test": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, "prov_aux": { Schema: map[string]*schema.Schema{ "aux": { @@ -719,19 +746,59 @@ func TestUnknownBlocks(t *testing.T) { }, }, }, + "nested_aux": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_prop": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, }, CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { d.SetId("aux") err := d.Set("aux", []map[string]interface{}{{"test_prop": "aux"}}) require.NoError(t, err) + err = d.Set("nested_aux", []map[string]interface{}{ + { + "nested_prop": []map[string]interface{}{ + {"test_prop": []string{"aux"}}, + }, + }, + }) + require.NoError(t, err) return nil }, }, } bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) - t.Run("list of objects", func(t *testing.T) { - program := ` + for _, tc := range []struct { + name string + program string + expected autogold.Value + }{ + { + "list of objects", + ` name: test runtime: yaml resources: @@ -741,16 +808,8 @@ resources: type: prov:index:Test properties: tests: ${auxRes.auxes} -outputs: - testOut: ${mainRes.tests} -` - pt := pulcheck.PulCheck(t, bridgedProvider, program) - res := pt.Preview(optpreview.Diff()) - t.Logf(res.StdOut) - // Test that the test property is unknown at preview time. - // Note that the property is output instead of - // output> - this is due to an engine limitation. - autogold.Expect(`Previewing update (test): +`, + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + prov:index/aux:Aux: (create) @@ -758,21 +817,13 @@ outputs: + prov:index/test:Test: (create) [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] tests : output - --outputs:-- - testOut: output Resources: + 3 to create -`).Equal(t, res.StdOut) - resUp := pt.Up() - // assert that the property gets resolved - require.Equal(t, - []interface{}{map[string]interface{}{"testProp": "aux"}}, - resUp.Outputs["testOut"].Value, - ) - }) - - t.Run("unknown object", func(t *testing.T) { - program := ` +`), + }, + { + "unknown object", + ` name: test runtime: yaml resources: @@ -783,16 +834,8 @@ resources: properties: tests: - ${auxRes.auxes[0]} -outputs: - testOut: ${mainRes.tests[0]} -` - pt := pulcheck.PulCheck(t, bridgedProvider, program) - res := pt.Preview(optpreview.Diff()) - t.Logf(res.StdOut) - // Test that the test property is unknown at preview time. - // Note that the property is output instead of - // output - this is due to an engine limitation. - autogold.Expect(`Previewing update (test): +`, + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + prov:index/aux:Aux: (create) @@ -802,18 +845,13 @@ outputs: tests : [ [0]: output ] - --outputs:-- - testOut: output Resources: + 3 to create -`).Equal(t, res.StdOut) - resUp := pt.Up() - // assert that the property gets resolved - require.Equal(t, map[string]interface{}{"testProp": "aux"}, resUp.Outputs["testOut"].Value) - }) - - t.Run("unknown object with others", func(t *testing.T) { - program := ` +`), + }, + { + "unknown object with others", + ` name: test runtime: yaml resources: @@ -825,16 +863,8 @@ resources: tests: - ${auxRes.auxes[0]} - {"testProp": "val"} -outputs: - testOut: ${mainRes.tests[0]} -` - pt := pulcheck.PulCheck(t, bridgedProvider, program) - res := pt.Preview(optpreview.Diff()) - t.Logf(res.StdOut) - // Test that the test property is unknown at preview time. - // Note that the property is output instead of - // output - this is due to an engine limitation. - autogold.Expect(`Previewing update (test): +`, + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] + prov:index/aux:Aux: (create) @@ -847,13 +877,207 @@ outputs: testProp : "val" } ] - --outputs:-- - testOut: output Resources: + 3 to create -`).Equal(t, res.StdOut) - resUp := pt.Up() - // assert that the property gets resolved - require.Equal(t, map[string]interface{}{"testProp": "aux"}, resUp.Outputs["testOut"].Value) - }) +`), + }, + { + "unknown nested", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: ${auxRes.nestedAuxes} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : output +Resources: + + 3 to create +`), + }, + { + "unknown nested level 1", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: + - ${auxRes.nestedAuxes[0]} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: output + ] +Resources: + + 3 to create +`), + }, + // tests: [{nestedProps: [{testProps: ["val"]}] }] + { + "unknown nested level 2", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: ${auxRes.nestedAuxes[0].nestedProps} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: output + } + ] +Resources: + + 3 to create +`), + }, + { + "unknown nested level 3", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - ${auxRes.nestedAuxes[0].nestedProps[0]} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: output + ] + } + ] +Resources: + + 3 to create +`), + }, + { + "unknown nested level 4", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: ${auxRes.nestedAuxes[0].nestedProps[0].testProps} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: { + testProps : output + } + ] + } + ] +Resources: + + 3 to create +`), + }, + { + "unknown nested level 5", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: + - ${auxRes.nestedAuxes[0].nestedProps[0].testProps[0]} +`, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: { + testProps : [ + [0]: output + ] + } + ] + } + ] +Resources: + + 3 to create +`), + }, + } { + t.Run(tc.name, func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, tc.program) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + + tc.expected.Equal(t, res.StdOut) + }) + } } From 67e2baed742e2f4fe23cfd80a4d43c92ea1f7c47 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 15:29:15 +0300 Subject: [PATCH 17/52] add some more tests, debugging --- pkg/tests/internal/pulcheck/pulcheck.go | 24 ++- pkg/tests/schema_pulumi_test.go | 240 ++++++++++++++++++------ 2 files changed, 204 insertions(+), 60 deletions(-) diff --git a/pkg/tests/internal/pulcheck/pulcheck.go b/pkg/tests/internal/pulcheck/pulcheck.go index c041a6b83..e5e30bced 100644 --- a/pkg/tests/internal/pulcheck/pulcheck.go +++ b/pkg/tests/internal/pulcheck/pulcheck.go @@ -29,6 +29,20 @@ import ( "gotest.tools/assert" ) +func resNeedsUpdate(res *schema.Resource) bool { + for _, s := range res.Schema { + if s.Computed && !s.Optional { + continue + } + if s.ForceNew { + continue + } + + return res.UpdateContext == nil + } + return false +} + // This is an experimental API. func EnsureProviderValid(t T, tfp *schema.Provider) { for _, r := range tfp.ResourcesMap { @@ -54,10 +68,12 @@ func EnsureProviderValid(t T, tfp *schema.Provider) { } } - r.UpdateContext = func( - ctx context.Context, rd *schema.ResourceData, i interface{}, - ) diag.Diagnostics { - return diag.Diagnostics{} + if resNeedsUpdate(r) { + r.UpdateContext = func( + ctx context.Context, rd *schema.ResourceData, i interface{}, + ) diag.Diagnostics { + return diag.Diagnostics{} + } } } require.NoError(t, tfp.InternalValidate()) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 34e66fbb9..4c1a743cb 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -3,6 +3,8 @@ package tests import ( "context" "fmt" + "os" + "path/filepath" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -741,6 +743,7 @@ func TestUnknownBlocks(t *testing.T) { Schema: map[string]*schema.Schema{ "test_prop": { Type: schema.TypeString, + Computed: true, Optional: true, }, }, @@ -775,26 +778,31 @@ func TestUnknownBlocks(t *testing.T) { }, CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { d.SetId("aux") - err := d.Set("aux", []map[string]interface{}{{"test_prop": "aux"}}) - require.NoError(t, err) - err = d.Set("nested_aux", []map[string]interface{}{ - { - "nested_prop": []map[string]interface{}{ - {"test_prop": []string{"aux"}}, + if d.Get("aux") == nil { + err := d.Set("aux", []map[string]interface{}{{"test_prop": "aux"}}) + require.NoError(t, err) + } + if d.Get("nested_aux") == nil { + err := d.Set("nested_aux", []map[string]interface{}{ + { + "nested_prop": []map[string]interface{}{ + {"test_prop": []string{"aux"}}, + }, }, - }, - }) - require.NoError(t, err) + }) + require.NoError(t, err) + } return nil }, }, } bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) - for _, tc := range []struct { - name string - program string - expected autogold.Value + for i, tc := range []struct { + name string + program string + expectedInitial autogold.Value + expectedUpdate autogold.Value }{ { "list of objects", @@ -802,12 +810,15 @@ func TestUnknownBlocks(t *testing.T) { name: test runtime: yaml resources: - auxRes: - type: prov:index:Aux - mainRes: - type: prov:index:Test - properties: - tests: ${auxRes.auxes} + auxRes: + type: prov:index:Aux + properties: + %s + %s + mainRes: + type: prov:index:Test + properties: + tests: ${auxRes.auxes} `, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) @@ -819,6 +830,12 @@ resources: tests : output Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -829,6 +846,9 @@ runtime: yaml resources: auxRes: type: prov:index:Aux + properties: + %s + %s mainRes: type: prov:index:Test properties: @@ -847,6 +867,12 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -857,6 +883,9 @@ runtime: yaml resources: auxRes: type: prov:index:Aux + properties: + %s + %s mainRes: type: prov:index:Test properties: @@ -879,6 +908,12 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -889,6 +924,9 @@ runtime: yaml resources: auxRes: type: prov:index:Aux + properties: + %s + %s mainRes: type: prov:index:NestedTest properties: @@ -904,6 +942,12 @@ resources: tests : output Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -914,6 +958,9 @@ runtime: yaml resources: auxRes: type: prov:index:Aux + properties: + %s + %s mainRes: type: prov:index:NestedTest properties: @@ -932,22 +979,30 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, - // tests: [{nestedProps: [{testProps: ["val"]}] }] { "unknown nested level 2", ` name: test runtime: yaml resources: - auxRes: - type: prov:index:Aux - mainRes: - type: prov:index:NestedTest - properties: - tests: - - nestedProps: ${auxRes.nestedAuxes[0].nestedProps} + auxRes: + type: prov:index:Aux + properties: + %s + %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: ${auxRes.nestedAuxes[0].nestedProps} `, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) @@ -963,6 +1018,12 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -971,14 +1032,17 @@ Resources: name: test runtime: yaml resources: - auxRes: - type: prov:index:Aux - mainRes: - type: prov:index:NestedTest - properties: - tests: - - nestedProps: - - ${auxRes.nestedAuxes[0].nestedProps[0]} + auxRes: + type: prov:index:Aux + properties: + %s + %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - ${auxRes.nestedAuxes[0].nestedProps[0]} `, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) @@ -996,6 +1060,12 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -1004,14 +1074,17 @@ Resources: name: test runtime: yaml resources: - auxRes: - type: prov:index:Aux - mainRes: - type: prov:index:NestedTest - properties: - tests: - - nestedProps: - - testProps: ${auxRes.nestedAuxes[0].nestedProps[0].testProps} + auxRes: + type: prov:index:Aux + properties: + %s + %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: ${auxRes.nestedAuxes[0].nestedProps[0].testProps} `, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) @@ -1031,6 +1104,12 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, { @@ -1039,15 +1118,18 @@ Resources: name: test runtime: yaml resources: - auxRes: - type: prov:index:Aux - mainRes: - type: prov:index:NestedTest - properties: - tests: - - nestedProps: - - testProps: - - ${auxRes.nestedAuxes[0].nestedProps[0].testProps[0]} + auxRes: + type: prov:index:Aux + properties: + %s + %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: + - ${auxRes.nestedAuxes[0].nestedProps[0].testProps[0]} `, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) @@ -1069,15 +1151,61 @@ resources: ] Resources: + 3 to create +`), + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (same) + [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] +Resources: + 3 unchanged `), }, } { + if i != 0 { + continue + } + t.Run(tc.name, func(t *testing.T) { - pt := pulcheck.PulCheck(t, bridgedProvider, tc.program) - res := pt.Preview(optpreview.Diff()) - t.Logf(res.StdOut) + nonComputedProgram := fmt.Sprintf(tc.program, "auxes: [{testProp: \"val1\"}]", "nestedAuxes: [{nestedProps: [{testProps: [\"val1\"]}]}]") + computedProgram := fmt.Sprintf(tc.program, "{}", "") + + // t.Run("initial preview", func(t *testing.T) { + // pt := pulcheck.PulCheck(t, bridgedProvider, computedProgram) + // res := pt.Preview(optpreview.Diff()) + // t.Logf(res.StdOut) + + // tc.expectedInitial.Equal(t, res.StdOut) + // }) + + t.Run("update preview", func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, nonComputedProgram) + pt.Up() + + pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") + content, err := os.ReadFile(pulumiYamlPath) + require.NoError(t, err) + t.Logf("Pulumi.yaml: %s", string(content)) - tc.expected.Equal(t, res.StdOut) + err = os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0600) + require.NoError(t, err) + + content, err = os.ReadFile(pulumiYamlPath) + require.NoError(t, err) + t.Logf("Pulumi.yaml: %s", string(content)) + + pt.ClearGrpcLog() + res := pt.Preview(optpreview.Diff()) + for _, e := range pt.GrpcLog().Entries { + t.Logf("GRPC: %s", e.Method) + if e.Method == "/pulumirpc.ResourceProvider/Diff" || + e.Method == "/pulumirpc.ResourceProvider/Check" { + t.Logf("GRPC: %s", e.Request) + t.Logf("GRPC: %s", e.Response) + } + } + t.Logf(res.StdOut) + tc.expectedUpdate.Equal(t, res.StdOut) + panic("here!") + }) }) } } From ff51402aea2df505576835218b3fac65cafbbd93 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 16:40:57 +0300 Subject: [PATCH 18/52] add note about plugin sdk behaviour --- pkg/tests/go.mod | 4 ++- pkg/tests/go.sum | 4 +-- pkg/tests/schema_pulumi_test.go | 43 ++++++++++----------------------- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/pkg/tests/go.mod b/pkg/tests/go.mod index 95d72e636..4f211ca05 100644 --- a/pkg/tests/go.mod +++ b/pkg/tests/go.mod @@ -11,7 +11,7 @@ require ( github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hexops/autogold/v2 v2.2.1 github.com/hexops/valast v1.4.4 - github.com/pulumi/providertest v0.0.12 + github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-terraform-bridge/v3 v3.80.0 github.com/stretchr/testify v1.9.0 gotest.tools v2.2.0+incompatible @@ -65,6 +65,8 @@ require ( github.com/iancoleman/strcase v0.2.0 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/klauspost/compress v1.15.11 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-localereader v0.0.1 // indirect diff --git a/pkg/tests/go.sum b/pkg/tests/go.sum index 35c379756..6ada63733 100644 --- a/pkg/tests/go.sum +++ b/pkg/tests/go.sum @@ -1911,8 +1911,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.12 h1:UjcFQHHs4AGJyJqxhvC2q8yVQ7Li+UyCyP95HZcK03U= -github.com/pulumi/providertest v0.0.12/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-yaml v1.8.0 h1:bhmidiCMMuzsJao5FE0UR69iF3WVKPCFrRkzjotFNn4= diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 4c1a743cb..5c1570ad2 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -798,7 +798,7 @@ func TestUnknownBlocks(t *testing.T) { } bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) - for i, tc := range []struct { + for _, tc := range []struct { name string program string expectedInitial autogold.Value @@ -1160,51 +1160,34 @@ Resources: `), }, } { - if i != 0 { - continue - } - t.Run(tc.name, func(t *testing.T) { nonComputedProgram := fmt.Sprintf(tc.program, "auxes: [{testProp: \"val1\"}]", "nestedAuxes: [{nestedProps: [{testProps: [\"val1\"]}]}]") - computedProgram := fmt.Sprintf(tc.program, "{}", "") + computedProgram := fmt.Sprintf(tc.program, "null", "null") - // t.Run("initial preview", func(t *testing.T) { - // pt := pulcheck.PulCheck(t, bridgedProvider, computedProgram) - // res := pt.Preview(optpreview.Diff()) - // t.Logf(res.StdOut) + t.Run("initial preview", func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, computedProgram) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) - // tc.expectedInitial.Equal(t, res.StdOut) - // }) + tc.expectedInitial.Equal(t, res.StdOut) + }) t.Run("update preview", func(t *testing.T) { + t.Skipf("Skipping this test as it this case is not handled by the TF plugin sdk") + // The TF plugin SDK does not handle removing an input for a computed value, even if the provider implements it. + // The plugin SDK always fills an empty Computed property with the value from the state. + // Diff in these cases always returns no diff and the old state value is used. pt := pulcheck.PulCheck(t, bridgedProvider, nonComputedProgram) pt.Up() pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") - content, err := os.ReadFile(pulumiYamlPath) - require.NoError(t, err) - t.Logf("Pulumi.yaml: %s", string(content)) - err = os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0600) + err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0600) require.NoError(t, err) - content, err = os.ReadFile(pulumiYamlPath) - require.NoError(t, err) - t.Logf("Pulumi.yaml: %s", string(content)) - - pt.ClearGrpcLog() res := pt.Preview(optpreview.Diff()) - for _, e := range pt.GrpcLog().Entries { - t.Logf("GRPC: %s", e.Method) - if e.Method == "/pulumirpc.ResourceProvider/Diff" || - e.Method == "/pulumirpc.ResourceProvider/Check" { - t.Logf("GRPC: %s", e.Request) - t.Logf("GRPC: %s", e.Response) - } - } t.Logf(res.StdOut) tc.expectedUpdate.Equal(t, res.StdOut) - panic("here!") }) }) } From 6931e6ac1f768fe996810f42460752bb9be81be4 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 17:07:07 +0300 Subject: [PATCH 19/52] more tests for updating with computed --- pkg/tests/schema_pulumi_test.go | 270 ++++++++++++++++++++++++++++---- 1 file changed, 237 insertions(+), 33 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 5c1570ad2..09246e822 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -798,11 +798,35 @@ func TestUnknownBlocks(t *testing.T) { } bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) + provTestKnownProgram := ` +name: test +runtime: yaml +resources: + mainRes: + type: prov:index:Test + properties: + tests: + - testProp: "known_val" +` + nestedProvTestKnownProgram := ` +name: test +runtime: yaml +resources: + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: + - "known_val" +` + for _, tc := range []struct { - name string - program string - expectedInitial autogold.Value - expectedUpdate autogold.Value + name string + program string + initialKnownProgram string + expectedInitial autogold.Value + expectedUpdate autogold.Value }{ { "list of objects", @@ -813,13 +837,14 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:Test properties: tests: ${auxRes.auxes} `, + provTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -834,8 +859,21 @@ Resources: 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]: { + - testProp: "known_val" + } + ] + + tests: output Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -847,14 +885,16 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:Test properties: tests: - ${auxRes.auxes[0]} `, + provTestKnownProgram, + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -871,8 +911,21 @@ Resources: 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]: { + - testProp: "known_val" + } + + [0]: output + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -884,8 +937,8 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:Test properties: @@ -893,6 +946,8 @@ resources: - ${auxRes.auxes[0]} - {"testProp": "val"} `, + provTestKnownProgram, + autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -912,8 +967,24 @@ Resources: 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]: { + - testProp: "known_val" + } + + [0]: output + + [1]: { + + testProp : "val" + } + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -925,13 +996,14 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: tests: ${auxRes.nestedAuxes} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -946,8 +1018,27 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + - tests: [ + - [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + } + ] + + tests: output Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -959,14 +1050,15 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: tests: - ${auxRes.nestedAuxes[0]} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -983,8 +1075,27 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + - [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + } + + [0]: output + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -996,14 +1107,15 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: tests: - nestedProps: ${auxRes.nestedAuxes[0].nestedProps} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -1022,8 +1134,27 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + + nestedProps: output + } + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -1035,8 +1166,8 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: @@ -1044,6 +1175,7 @@ resources: - nestedProps: - ${auxRes.nestedAuxes[0].nestedProps[0]} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -1064,8 +1196,27 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + + [0]: output + ] + } + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -1077,8 +1228,8 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: @@ -1086,6 +1237,7 @@ resources: - nestedProps: - testProps: ${auxRes.nestedAuxes[0].nestedProps[0].testProps} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -1108,8 +1260,27 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + ~ [0]: { + - testProps: [ + - [0]: "known_val" + ] + + testProps: output + } + ] + } + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, { @@ -1121,8 +1292,8 @@ resources: auxRes: type: prov:index:Aux properties: - %s - %s + auxes: %s + nestedAuxes: %s mainRes: type: prov:index:NestedTest properties: @@ -1131,6 +1302,7 @@ resources: - testProps: - ${auxRes.nestedAuxes[0].nestedProps[0].testProps[0]} `, + nestedProvTestKnownProgram, autogold.Expect(`Previewing update (test): + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:test::test::pulumi:pulumi:Stack::test-test] @@ -1155,13 +1327,30 @@ Resources: 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + ~ [0]: { + ~ testProps: [ + ~ [0]: "known_val" => output + ] + } + ] + } + ] Resources: - 3 unchanged + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged `), }, } { t.Run(tc.name, func(t *testing.T) { - nonComputedProgram := fmt.Sprintf(tc.program, "auxes: [{testProp: \"val1\"}]", "nestedAuxes: [{nestedProps: [{testProps: [\"val1\"]}]}]") computedProgram := fmt.Sprintf(tc.program, "null", "null") t.Run("initial preview", func(t *testing.T) { @@ -1177,12 +1366,27 @@ Resources: // The TF plugin SDK does not handle removing an input for a computed value, even if the provider implements it. // The plugin SDK always fills an empty Computed property with the value from the state. // Diff in these cases always returns no diff and the old state value is used. + nonComputedProgram := fmt.Sprintf(tc.program, "[{testProp: \"val1\"}]", "[{nestedProps: [{testProps: [\"val1\"]}]}]") pt := pulcheck.PulCheck(t, bridgedProvider, nonComputedProgram) pt.Up() pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") - err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0600) + err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0o600) + require.NoError(t, err) + + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + tc.expectedUpdate.Equal(t, res.StdOut) + }) + + t.Run("update preview with computed", func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, tc.initialKnownProgram) + pt.Up() + + pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") + + err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0o600) require.NoError(t, err) res := pt.Preview(optpreview.Diff()) From 6524b9d82fafdd6f8b77014d303a75839deafe31 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 17:13:20 +0300 Subject: [PATCH 20/52] commit tests --- pkg/tests/schema_pulumi_test.go | 712 ++++++++++++++++++++++++++++++++ 1 file changed, 712 insertions(+) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index aeeb70f32..09246e822 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -3,10 +3,13 @@ package tests import ( "context" "fmt" + "os" + "path/filepath" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hexops/autogold/v2" "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/internal/pulcheck" "github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview" "github.com/pulumi/pulumi/sdk/v3/go/auto/optrefresh" @@ -684,3 +687,712 @@ outputs: }) } } + +func TestUnknownBlocks(t *testing.T) { + resMap := map[string]*schema.Resource{ + "prov_test": { + Schema: map[string]*schema.Schema{ + "test": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + "prov_nested_test": { + Schema: map[string]*schema.Schema{ + "test": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "prov_aux": { + Schema: map[string]*schema.Schema{ + "aux": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeString, + Computed: true, + Optional: true, + }, + }, + }, + }, + "nested_aux": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_prop": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "test_prop": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("aux") + if d.Get("aux") == nil { + err := d.Set("aux", []map[string]interface{}{{"test_prop": "aux"}}) + require.NoError(t, err) + } + if d.Get("nested_aux") == nil { + err := d.Set("nested_aux", []map[string]interface{}{ + { + "nested_prop": []map[string]interface{}{ + {"test_prop": []string{"aux"}}, + }, + }, + }) + require.NoError(t, err) + } + return nil + }, + }, + } + bridgedProvider := pulcheck.BridgedProvider(t, "prov", resMap) + + provTestKnownProgram := ` +name: test +runtime: yaml +resources: + mainRes: + type: prov:index:Test + properties: + tests: + - testProp: "known_val" +` + nestedProvTestKnownProgram := ` +name: test +runtime: yaml +resources: + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: + - "known_val" +` + + for _, tc := range []struct { + name string + program string + initialKnownProgram string + expectedInitial autogold.Value + expectedUpdate autogold.Value + }{ + { + "list of objects", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:Test + properties: + tests: ${auxRes.auxes} +`, + provTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : output +Resources: + + 3 to create +`), + 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]: { + - testProp: "known_val" + } + ] + + tests: output +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown object", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:Test + properties: + tests: + - ${auxRes.auxes[0]} +`, + provTestKnownProgram, + + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : [ + [0]: output + ] +Resources: + + 3 to create +`), + 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]: { + - testProp: "known_val" + } + + [0]: output + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown object with others", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:Test + properties: + tests: + - ${auxRes.auxes[0]} + - {"testProp": "val"} +`, + provTestKnownProgram, + + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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: (create) + [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] + tests : [ + [0]: output + [1]: { + testProp : "val" + } + ] +Resources: + + 3 to create +`), + 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]: { + - testProp: "known_val" + } + + [0]: output + + [1]: { + + testProp : "val" + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: ${auxRes.nestedAuxes} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : output +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + - tests: [ + - [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + } + ] + + tests: output +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested level 1", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - ${auxRes.nestedAuxes[0]} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: output + ] +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + - [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + } + + [0]: output + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested level 2", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: ${auxRes.nestedAuxes[0].nestedProps} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: output + } + ] +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + + nestedProps: output + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested level 3", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - ${auxRes.nestedAuxes[0].nestedProps[0]} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: output + ] + } + ] +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + + [0]: output + ] + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested level 4", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: ${auxRes.nestedAuxes[0].nestedProps[0].testProps} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: { + testProps : output + } + ] + } + ] +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + ~ [0]: { + - testProps: [ + - [0]: "known_val" + ] + + testProps: output + } + ] + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + { + "unknown nested level 5", + ` +name: test +runtime: yaml +resources: + auxRes: + type: prov:index:Aux + properties: + auxes: %s + nestedAuxes: %s + mainRes: + type: prov:index:NestedTest + properties: + tests: + - nestedProps: + - testProps: + - ${auxRes.nestedAuxes[0].nestedProps[0].testProps[0]} +`, + nestedProvTestKnownProgram, + autogold.Expect(`Previewing update (test): ++ pulumi:pulumi:Stack: (create) + [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/nestedTest:NestedTest: (create) + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + tests : [ + [0]: { + nestedProps: [ + [0]: { + testProps : [ + [0]: output + ] + } + ] + } + ] +Resources: + + 3 to create +`), + 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/nestedTest:NestedTest: (update) + [id=newid] + [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] + ~ tests: [ + ~ [0]: { + ~ nestedProps: [ + ~ [0]: { + ~ testProps: [ + ~ [0]: "known_val" => output + ] + } + ] + } + ] +Resources: + + 1 to create + ~ 1 to update + 2 changes. 1 unchanged +`), + }, + } { + t.Run(tc.name, func(t *testing.T) { + computedProgram := fmt.Sprintf(tc.program, "null", "null") + + t.Run("initial preview", func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, computedProgram) + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + + tc.expectedInitial.Equal(t, res.StdOut) + }) + + t.Run("update preview", func(t *testing.T) { + t.Skipf("Skipping this test as it this case is not handled by the TF plugin sdk") + // The TF plugin SDK does not handle removing an input for a computed value, even if the provider implements it. + // The plugin SDK always fills an empty Computed property with the value from the state. + // Diff in these cases always returns no diff and the old state value is used. + nonComputedProgram := fmt.Sprintf(tc.program, "[{testProp: \"val1\"}]", "[{nestedProps: [{testProps: [\"val1\"]}]}]") + pt := pulcheck.PulCheck(t, bridgedProvider, nonComputedProgram) + pt.Up() + + pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") + + err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0o600) + require.NoError(t, err) + + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + tc.expectedUpdate.Equal(t, res.StdOut) + }) + + t.Run("update preview with computed", func(t *testing.T) { + pt := pulcheck.PulCheck(t, bridgedProvider, tc.initialKnownProgram) + pt.Up() + + pulumiYamlPath := filepath.Join(pt.CurrentStack().Workspace().WorkDir(), "Pulumi.yaml") + + err := os.WriteFile(pulumiYamlPath, []byte(computedProgram), 0o600) + require.NoError(t, err) + + res := pt.Preview(optpreview.Diff()) + t.Logf(res.StdOut) + tc.expectedUpdate.Equal(t, res.StdOut) + }) + }) + } +} From 3e9a8a81ec7fec8ab42b5c20be14f0b5fe5689d6 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 17:14:26 +0300 Subject: [PATCH 21/52] update tests --- pkg/tests/schema_pulumi_test.go | 74 ++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/pkg/tests/schema_pulumi_test.go b/pkg/tests/schema_pulumi_test.go index 09246e822..3b17a109d 100644 --- a/pkg/tests/schema_pulumi_test.go +++ b/pkg/tests/schema_pulumi_test.go @@ -852,7 +852,9 @@ resources: [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + prov:index/test:Test: (create) [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] - tests : output + tests : [ + [0]: {} + ] Resources: + 3 to create `), @@ -864,12 +866,11 @@ Resources: ~ prov:index/test:Test: (update) [id=newid] [urn=urn:pulumi:test::test::prov:index/test:Test::mainRes] - - tests: [ - - [0]: { - - testProp: "known_val" - } + ~ tests: [ + ~ [0]: { + - testProp: "known_val" + } ] - + tests: output Resources: + 1 to create ~ 1 to update @@ -1011,7 +1012,9 @@ resources: [urn=urn:pulumi:test::test::prov:index/aux:Aux::auxRes] + prov:index/nestedTest:NestedTest: (create) [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] - tests : output + tests : [ + [0]: {} + ] Resources: + 3 to create `), @@ -1023,18 +1026,24 @@ Resources: ~ prov:index/nestedTest:NestedTest: (update) [id=newid] [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] - - tests: [ - - [0]: { - - nestedProps: [ - - [0]: { - - testProps: [ - - [0]: "known_val" - ] - } - ] - } + ~ tests: [ + ~ [0]: { + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + - nestedProps: [ + - [0]: { + - testProps: [ + - [0]: "known_val" + ] + } + ] + } ] - + tests: output Resources: + 1 to create ~ 1 to update @@ -1125,7 +1134,9 @@ resources: [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] tests : [ [0]: { - nestedProps: output + nestedProps: [ + [0]: {} + ] } ] Resources: @@ -1141,14 +1152,16 @@ Resources: [urn=urn:pulumi:test::test::prov:index/nestedTest:NestedTest::mainRes] ~ tests: [ ~ [0]: { - - nestedProps: [ - - [0]: { - - testProps: [ - - [0]: "known_val" - ] - } + ~ nestedProps: [ + ~ [0]: { + - testProps: [ + - [0]: "known_val" + ] + - testProps: [ + - [0]: "known_val" + ] + } ] - + nestedProps: output } ] Resources: @@ -1249,7 +1262,9 @@ resources: [0]: { nestedProps: [ [0]: { - testProps : output + testProps : [ + [0]: output + ] } ] } @@ -1269,10 +1284,9 @@ Resources: ~ [0]: { ~ nestedProps: [ ~ [0]: { - - testProps: [ - - [0]: "known_val" + ~ testProps: [ + ~ [0]: "known_val" => output ] - + testProps: output } ] } From ac7747f5b755606db3436ab647207be0aba49029 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 17:23:55 +0300 Subject: [PATCH 22/52] inline tf unknown --- pkg/tfbridge/schema.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index 93fed9ed4..ad48aab7e 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -531,7 +531,7 @@ func (ctx *conversionContext) makeTerraformInput( // If any variables are unknown, we need to mark them in the inputs so the config map treats it right. This // requires the use of the special UnknownVariableValue sentinel in Terraform, which is how it internally stores // interpolated variables whose inputs are currently unknown. - return makeTerraformUnknown(tfs), nil + return TerraformUnknownVariableValue, nil default: contract.Failf("Unexpected value marshaled: %v", v) return nil, nil @@ -959,14 +959,6 @@ func (ctx *conversionContext) applyDefaults( return nil } -// makeTerraformUnknown creates an unknown value with the shape indicated by the given schema. -// -// It is important that we use the TF schema (if available) to decide what shape the unknown value should have: -// e.g. TF does not play nicely with unknown lists, instead expecting a list of unknowns. -func makeTerraformUnknown(_ shim.Schema) interface{} { - return TerraformUnknownVariableValue -} - // metaKey is the key in a TF bridge result that is used to store a resource's meta-attributes. const metaKey = "__meta" From c4dde52c17f89786f457469c28529edd48303b98 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 18:09:19 +0300 Subject: [PATCH 23/52] update test --- pkg/tfbridge/diff.go | 4 ++++ pkg/tfbridge/diff_test.go | 26 ++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pkg/tfbridge/diff.go b/pkg/tfbridge/diff.go index 5ee359e12..a023e9b04 100644 --- a/pkg/tfbridge/diff.go +++ b/pkg/tfbridge/diff.go @@ -17,6 +17,7 @@ package tfbridge import ( "context" "fmt" + "q" "strconv" "strings" @@ -360,6 +361,7 @@ func makeDetailedDiffExtra( forceDiff := new(bool) diff := map[string]*pulumirpc.PropertyDiff{} collectionDiffs := map[string]*pulumirpc.PropertyDiff{} + q.Q("makeDetailedDiffExtra", olds, news) for k, v := range olds { en, etf, eps := getInfoFromPulumiName(k, tfs, ps) makePropertyDiff(ctx, en, string(k), v, tfDiff, diff, collectionDiffs, forceDiff, @@ -380,6 +382,8 @@ func makeDetailedDiffExtra( if len(diff) > 0 || *forceDiff { changes = pulumirpc.DiffResponse_DIFF_SOME } + + q.Q(changes, diff, collectionDiffs) return detailedDiffExtra{ changes: changes, diffs: diff, diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index eaf2d620e..4ca72b182 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -3,6 +3,7 @@ package tfbridge import ( "context" "fmt" + "q" "testing" "github.com/stretchr/testify/assert" @@ -201,7 +202,8 @@ func TestCustomizeDiff(t *testing.T) { func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*SchemaInfo, inputs, state map[string]interface{}, expected map[string]DiffKind, expectedDiffChanges pulumirpc.DiffResponse_DiffChanges, - ignoreChanges ...string) { + ignoreChanges ...string, +) { ctx := context.Background() inputsMap := resource.NewPropertyMapFromMap(inputs) @@ -243,8 +245,22 @@ func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*Sche // Convert the diff to a detailed diff and check the result. diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) expectedDiff := map[string]*pulumirpc.PropertyDiff{} + expectedCollectionDiff := map[string]*pulumirpc.PropertyDiff{} for k, v := range expected { - expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} + q.Q(sch) + q.Q(k) + propSchema, ok := sch.GetOk(k) + if ok && + (propSchema.Type() == shim.TypeList || + propSchema.Type() == shim.TypeMap || + propSchema.Type() == shim.TypeSet) { + expectedCollectionDiff[k] = &pulumirpc.PropertyDiff{Kind: v} + // TODO[pulumi/pulumi-terraform-bridge#2141]: We return diff kind ADD for collections with a diff. + // This is covered by integration tests so probably fine but we might still want to fix this. + expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: 0} + } else { + expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} + } } assert.Equal(t, expectedDiffChanges, changes) assert.Equal(t, expectedDiff, diff) @@ -1342,7 +1358,8 @@ func TestComputedListUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": U, + "prop": U, + "prop[0]": D, }, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1846,7 +1863,8 @@ func TestCollectionsWithMultipleItems(t *testing.T) { } runTestCase := func(t *testing.T, name string, typ schema.ValueType, inputs, state []interface{}, - expected map[string]DiffKind, expectedChanges pulumirpc.DiffResponse_DiffChanges) { + expected map[string]DiffKind, expectedChanges pulumirpc.DiffResponse_DiffChanges, + ) { t.Run(name, func(t *testing.T) { diffTest(t, map[string]*schema.Schema{ From a96ce40d61916938512294972769126e64861874 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 18:09:54 +0300 Subject: [PATCH 24/52] remove debug logging --- pkg/tfbridge/diff.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/tfbridge/diff.go b/pkg/tfbridge/diff.go index a023e9b04..b77ad91d7 100644 --- a/pkg/tfbridge/diff.go +++ b/pkg/tfbridge/diff.go @@ -17,7 +17,6 @@ package tfbridge import ( "context" "fmt" - "q" "strconv" "strings" @@ -361,7 +360,6 @@ func makeDetailedDiffExtra( forceDiff := new(bool) diff := map[string]*pulumirpc.PropertyDiff{} collectionDiffs := map[string]*pulumirpc.PropertyDiff{} - q.Q("makeDetailedDiffExtra", olds, news) for k, v := range olds { en, etf, eps := getInfoFromPulumiName(k, tfs, ps) makePropertyDiff(ctx, en, string(k), v, tfDiff, diff, collectionDiffs, forceDiff, @@ -383,7 +381,6 @@ func makeDetailedDiffExtra( changes = pulumirpc.DiffResponse_DIFF_SOME } - q.Q(changes, diff, collectionDiffs) return detailedDiffExtra{ changes: changes, diffs: diff, From 6b1e2bea485828862628d41bfa5451a4a43d41b5 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 18:11:08 +0300 Subject: [PATCH 25/52] remove debug logging --- pkg/tfbridge/diff_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 4ca72b182..0bf84ce62 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -3,7 +3,6 @@ package tfbridge import ( "context" "fmt" - "q" "testing" "github.com/stretchr/testify/assert" @@ -247,8 +246,6 @@ func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*Sche expectedDiff := map[string]*pulumirpc.PropertyDiff{} expectedCollectionDiff := map[string]*pulumirpc.PropertyDiff{} for k, v := range expected { - q.Q(sch) - q.Q(k) propSchema, ok := sch.GetOk(k) if ok && (propSchema.Type() == shim.TypeList || From 026a0dfeded75db53a198fa10373d7b792f4eaad Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 19:44:16 +0300 Subject: [PATCH 26/52] update resources --- pkg/tfbridge/diff_test.go | 10 ++++++---- pkg/tfbridge/schema_test.go | 3 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 0bf84ce62..fd1ff623c 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -254,7 +254,7 @@ func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*Sche expectedCollectionDiff[k] = &pulumirpc.PropertyDiff{Kind: v} // TODO[pulumi/pulumi-terraform-bridge#2141]: We return diff kind ADD for collections with a diff. // This is covered by integration tests so probably fine but we might still want to fix this. - expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: 0} + expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } else { expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } @@ -1355,7 +1355,7 @@ func TestComputedListUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": U, + "prop": A, "prop[0]": D, }, pulumirpc.DiffResponse_DIFF_SOME) @@ -1435,7 +1435,8 @@ func TestComputedSetUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": U, + "prop": A, + "prop[0]": D, }, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1573,7 +1574,8 @@ func TestComputedSetUpdateReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": UR, + "prop": AR, + "prop[0]": DR, }, pulumirpc.DiffResponse_DIFF_SOME) } diff --git a/pkg/tfbridge/schema_test.go b/pkg/tfbridge/schema_test.go index 7f7a96fe8..fc0bcb395 100644 --- a/pkg/tfbridge/schema_test.go +++ b/pkg/tfbridge/schema_test.go @@ -3085,9 +3085,8 @@ func Test_makeTerraformInputsNoDefaults(t *testing.T) { // The string property inside Computed is irrelevant. "unknownArrayValue": resource.Computed{Element: resource.NewStringProperty("")}, }), - // NOTE: is this the behavior we would want here? Why is the result [unk] instead of unk? //nolint:lll - expect: autogold.Expect(map[string]interface{}{"unknown_array_value": []interface{}{"74D93920-ED26-11E3-AC10-0800200C9A66"}}), + expect: autogold.Expect(map[string]interface{}{"unknown_array_value": "74D93920-ED26-11E3-AC10-0800200C9A66"}), }, { testCaseName: "unknown_object_value", From 2a6ebd3c537e39d961201b902a53cb77564497f5 Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 19:47:45 +0300 Subject: [PATCH 27/52] update test --- pkg/tfbridge/schema_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/tfbridge/schema_test.go b/pkg/tfbridge/schema_test.go index fc0bcb395..76cf6fde4 100644 --- a/pkg/tfbridge/schema_test.go +++ b/pkg/tfbridge/schema_test.go @@ -3085,7 +3085,6 @@ func Test_makeTerraformInputsNoDefaults(t *testing.T) { // The string property inside Computed is irrelevant. "unknownArrayValue": resource.Computed{Element: resource.NewStringProperty("")}, }), - //nolint:lll expect: autogold.Expect(map[string]interface{}{"unknown_array_value": "74D93920-ED26-11E3-AC10-0800200C9A66"}), }, { From 68de60630f4a502cd28978e61d6f6b6d1e2c32ae Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 19:49:15 +0300 Subject: [PATCH 28/52] update unused code --- pkg/tfbridge/diff_test.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index fd1ff623c..5b80875de 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -244,20 +244,8 @@ func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*Sche // Convert the diff to a detailed diff and check the result. diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) expectedDiff := map[string]*pulumirpc.PropertyDiff{} - expectedCollectionDiff := map[string]*pulumirpc.PropertyDiff{} for k, v := range expected { - propSchema, ok := sch.GetOk(k) - if ok && - (propSchema.Type() == shim.TypeList || - propSchema.Type() == shim.TypeMap || - propSchema.Type() == shim.TypeSet) { - expectedCollectionDiff[k] = &pulumirpc.PropertyDiff{Kind: v} - // TODO[pulumi/pulumi-terraform-bridge#2141]: We return diff kind ADD for collections with a diff. - // This is covered by integration tests so probably fine but we might still want to fix this. - expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} - } else { - expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} - } + expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } assert.Equal(t, expectedDiffChanges, changes) assert.Equal(t, expectedDiff, diff) From 480acc6fa0b29eda8dd498105b0cf56d99ee67eb Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 19:51:35 +0300 Subject: [PATCH 29/52] add todos --- pkg/tfbridge/diff_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 5b80875de..5c2ff3079 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1343,6 +1343,8 @@ func TestComputedListUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ + // TODO[pulumi/pulumi#2141]: This should be an U. + // makeDetailedDiff returns an empty diff for collections "prop": A, "prop[0]": D, }, @@ -1423,6 +1425,8 @@ func TestComputedSetUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ + // TODO[pulumi/pulumi#2141]: This should be an U. + // makeDetailedDiff returns an empty diff for collections "prop": A, "prop[0]": D, }, @@ -1562,6 +1566,8 @@ func TestComputedSetUpdateReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ + // TODO[pulumi/pulumi#2141]: This should be an UR. + // makeDetailedDiff returns an empty diff for collections "prop": AR, "prop[0]": DR, }, From bc614565cbc77bc9e7a65bbdf4ca6e7f08a918ea Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 19:58:57 +0300 Subject: [PATCH 30/52] another todo --- pkg/tfbridge/diff_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 5c2ff3079..8b4a3d26a 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1345,6 +1345,7 @@ func TestComputedListUpdate(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections + // TODO: Why is outp not present here? "prop": A, "prop[0]": D, }, From a44380fb75c90595e4832987674139d7466f149c Mon Sep 17 00:00:00 2001 From: Venelin Date: Thu, 27 Jun 2024 20:01:17 +0300 Subject: [PATCH 31/52] add note about odd test --- pkg/tfbridge/diff_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 8b4a3d26a..984916f31 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1328,6 +1328,7 @@ func TestComputedNestedIgnore(t *testing.T) { "prop") } +//nolint:lll func TestComputedListUpdate(t *testing.T) { diffTest(t, map[string]*schema.Schema{ @@ -1345,9 +1346,11 @@ func TestComputedListUpdate(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections - // TODO: Why is outp not present here? "prop": A, "prop[0]": D, + // Note outp is not here because of + // https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/data-consistency-errors#planned-value-for-a-non-computed-attribute + // Computed properties keep the state value after being removed from inputs. }, pulumirpc.DiffResponse_DIFF_SOME) } From ef39d9d0347aba476828d814b7a6bdfa22c0291f Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 1 Jul 2024 15:45:15 +0100 Subject: [PATCH 32/52] lint --- pkg/tfbridge/diff_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 984916f31..027cee1da 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1431,7 +1431,7 @@ func TestComputedSetUpdate(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections - "prop": A, + "prop": A, "prop[0]": D, }, pulumirpc.DiffResponse_DIFF_SOME) @@ -1572,7 +1572,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi#2141]: This should be an UR. // makeDetailedDiff returns an empty diff for collections - "prop": AR, + "prop": AR, "prop[0]": DR, }, pulumirpc.DiffResponse_DIFF_SOME) From 54f438b17481c3426678c96829bc06ff32c5c530 Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 1 Jul 2024 16:45:23 +0100 Subject: [PATCH 33/52] fix todo --- pkg/tfbridge/diff_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 027cee1da..125225f02 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1344,9 +1344,9 @@ func TestComputedListUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - // TODO[pulumi/pulumi#2141]: This should be an U. + // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections - "prop": A, + "prop": U, "prop[0]": D, // Note outp is not here because of // https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/data-consistency-errors#planned-value-for-a-non-computed-attribute @@ -1429,7 +1429,7 @@ func TestComputedSetUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - // TODO[pulumi/pulumi#2141]: This should be an U. + // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections "prop": A, "prop[0]": D, @@ -1570,7 +1570,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - // TODO[pulumi/pulumi#2141]: This should be an UR. + // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an UR. // makeDetailedDiff returns an empty diff for collections "prop": AR, "prop[0]": DR, From 06929b56395ffa782aa132c2b2ce3ade0ebb195e Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 1 Jul 2024 16:46:51 +0100 Subject: [PATCH 34/52] fix needs update check --- pkg/tests/internal/pulcheck/pulcheck.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/tests/internal/pulcheck/pulcheck.go b/pkg/tests/internal/pulcheck/pulcheck.go index e5e30bced..4c42ef79d 100644 --- a/pkg/tests/internal/pulcheck/pulcheck.go +++ b/pkg/tests/internal/pulcheck/pulcheck.go @@ -37,10 +37,8 @@ func resNeedsUpdate(res *schema.Resource) bool { if s.ForceNew { continue } - - return res.UpdateContext == nil } - return false + return res.UpdateContext == nil } // This is an experimental API. From 8a48049bb576231d625578973a8e06a7be10e80f Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 1 Jul 2024 18:11:28 +0100 Subject: [PATCH 35/52] fix test --- pkg/tfbridge/diff_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 42438fe44..395d94b65 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -5,13 +5,14 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" v2Schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim" shimv1 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v1" @@ -1345,7 +1346,7 @@ func TestComputedListUpdate(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an U. // makeDetailedDiff returns an empty diff for collections - "prop": U, + "prop": A, "prop[0]": D, // Note outp is not here because of // https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/data-consistency-errors#planned-value-for-a-non-computed-attribute From f91d22475c3e711ad08a96e2c3b78a330cf5a450 Mon Sep 17 00:00:00 2001 From: Venelin Date: Tue, 2 Jul 2024 16:21:04 +0100 Subject: [PATCH 36/52] more lint --- pkg/tfbridge/diff_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 395d94b65..4e2b78f31 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -5,14 +5,13 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" v2Schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim" shimv1 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v1" From 725ea594e9e814429719995033b6f28c5928c605 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 12:36:17 +0100 Subject: [PATCH 37/52] diff tests for sdkv2 --- go.mod | 5 +- go.sum | 4 +- pkg/tests/go.mod | 2 + pkg/tests/go.sum | 1 + pkg/tests/schemaconvert/schemaconvert.go | 130 ++++ pkg/tfbridge/diff_test.go | 775 +++++++++++------------ 6 files changed, 521 insertions(+), 396 deletions(-) create mode 100644 pkg/tests/schemaconvert/schemaconvert.go diff --git a/go.mod b/go.mod index f80338fb2..9ce42f612 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.21 replace github.com/pulumi/pulumi-terraform-bridge/x/muxer => ./x/muxer +replace github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests => ./pkg/tests + require ( github.com/apparentlymart/go-cidr v1.1.0 github.com/blang/semver v3.5.1+incompatible @@ -36,8 +38,9 @@ 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.0.11 + github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-java/pkg v0.11.0 + github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests v0.0.0-00010101000000-000000000000 github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.8 github.com/pulumi/pulumi-yaml v1.8.0 github.com/pulumi/schema-tools v0.1.2 diff --git a/go.sum b/go.sum index f07714892..d8910077d 100644 --- a/go.sum +++ b/go.sum @@ -1901,8 +1901,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.11 h1:mg8MQ7Cq7+9XlHIkBD+aCqQO4mwAJEISngZgVdnQUe8= -github.com/pulumi/providertest v0.0.11/go.mod h1:HsxjVsytcMIuNj19w1lT2W0QXY0oReXl1+h6eD2JXP8= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-yaml v1.8.0 h1:bhmidiCMMuzsJao5FE0UR69iF3WVKPCFrRkzjotFNn4= diff --git a/pkg/tests/go.mod b/pkg/tests/go.mod index 95d72e636..49959e926 100644 --- a/pkg/tests/go.mod +++ b/pkg/tests/go.mod @@ -8,6 +8,7 @@ replace ( ) require ( + github.com/hashicorp/terraform-plugin-sdk v1.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hexops/autogold/v2 v2.2.1 github.com/hexops/valast v1.4.4 @@ -91,6 +92,7 @@ require ( github.com/ulikunitz/xz v0.5.10 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty-yaml v1.0.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect diff --git a/pkg/tests/go.sum b/pkg/tests/go.sum index 35c379756..180bd055f 100644 --- a/pkg/tests/go.sum +++ b/pkg/tests/go.sum @@ -1651,6 +1651,7 @@ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8 h1:+RyjwU+Gnd/aTJBPZVDNm903eXVjjqhbaR4Ypx3xYyY= github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/terraform-json v0.4.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU= diff --git a/pkg/tests/schemaconvert/schemaconvert.go b/pkg/tests/schemaconvert/schemaconvert.go new file mode 100644 index 000000000..6aca18e52 --- /dev/null +++ b/pkg/tests/schemaconvert/schemaconvert.go @@ -0,0 +1,130 @@ +package schemaconvert + +import ( + v1Schema "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + v2Schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" +) + +func Sdkv2ToV1Type(t v2Schema.ValueType) v1Schema.ValueType { + return v1Schema.ValueType(t) +} + +func Sdkv2ToV1SchemaOrResource(elem interface{}) interface{} { + switch elem := elem.(type) { + case nil: + return nil + case *v2Schema.Schema: + return Sdkv2ToV1Schema(elem) + case *v2Schema.Resource: + return Sdkv2ToV1Resource(elem) + default: + contract.Failf("unexpected type %T", elem) + return nil + } +} + +func Sdkv2ToV1Resource(sch *v2Schema.Resource) *v1Schema.Resource { + if sch.MigrateState != nil { + contract.Failf("MigrateState is not supported in conversion") + } + if sch.StateUpgraders != nil { + contract.Failf("StateUpgraders is not supported in conversion") + } + if sch.Create != nil || sch.Read != nil || sch.Update != nil || sch.Delete != nil || sch.Exists != nil || + sch.CreateContext != nil || sch.ReadContext != nil || sch.UpdateContext != nil || sch.DeleteContext != nil || sch.Importer != nil { + contract.Failf("runtime methods not supported in conversion") + } + + if sch.CustomizeDiff != nil { + contract.Failf("CustomizeDiff is not supported in conversion") + } + + timeouts := v1Schema.ResourceTimeout{} + if sch.Timeouts != nil { + timeouts = v1Schema.ResourceTimeout{ + Create: sch.Timeouts.Create, + Read: sch.Timeouts.Read, + Update: sch.Timeouts.Update, + Delete: sch.Timeouts.Delete, + Default: sch.Timeouts.Default, + } + } + timoutsPtr := &timeouts + if sch.Timeouts == nil { + timoutsPtr = nil + } + + return &v1Schema.Resource{ + Schema: Sdkv2ToV1SchemaMap(sch.Schema), + SchemaVersion: sch.SchemaVersion, + DeprecationMessage: sch.DeprecationMessage, + Timeouts: timoutsPtr, + } +} + +func Sdkv2ToV1Schema(sch *v2Schema.Schema) *v1Schema.Schema { + if sch.DiffSuppressFunc != nil { + contract.Failf("DiffSuppressFunc is not supported in conversion") + } + + defaultFunc := v1Schema.SchemaDefaultFunc(nil) + if sch.DefaultFunc != nil { + defaultFunc = func() (interface{}, error) { + return sch.DefaultFunc() + } + } + + stateFunc := v1Schema.SchemaStateFunc(nil) + if sch.StateFunc != nil { + stateFunc = func(i interface{}) string { + return sch.StateFunc(i) + } + } + + set := v1Schema.SchemaSetFunc(nil) + if sch.Set != nil { + set = func(i interface{}) int { + return sch.Set(i) + } + } + + validateFunc := v1Schema.SchemaValidateFunc(nil) + if sch.ValidateFunc != nil { + validateFunc = func(i interface{}, s string) ([]string, []error) { + return sch.ValidateFunc(i, s) + } + } + + return &v1Schema.Schema{ + Type: Sdkv2ToV1Type(sch.Type), + Optional: sch.Optional, + Required: sch.Required, + Default: sch.Default, + DefaultFunc: defaultFunc, + Description: sch.Description, + InputDefault: sch.InputDefault, + Computed: sch.Computed, + ForceNew: sch.ForceNew, + StateFunc: stateFunc, + Elem: Sdkv2ToV1SchemaOrResource(sch.Elem), + MaxItems: sch.MaxItems, + MinItems: sch.MinItems, + Set: set, + ComputedWhen: sch.ComputedWhen, + ConflictsWith: sch.ConflictsWith, + ExactlyOneOf: sch.ExactlyOneOf, + AtLeastOneOf: sch.AtLeastOneOf, + Deprecated: sch.Deprecated, + ValidateFunc: validateFunc, + Sensitive: sch.Sensitive, + } +} + +func Sdkv2ToV1SchemaMap(sch map[string]*v2Schema.Schema) map[string]*v1Schema.Schema { + res := make(map[string]*v1Schema.Schema) + for k, v := range sch { + res[k] = Sdkv2ToV1Schema(v) + } + return res +} diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 03f70d874..fe4217f73 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/schemaconvert" shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim" shimv1 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v1" shimv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2" @@ -197,15 +198,9 @@ func TestCustomizeDiff(t *testing.T) { }) } -func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*SchemaInfo, - inputs, state map[string]interface{}, expected map[string]DiffKind, - expectedDiffChanges pulumirpc.DiffResponse_DiffChanges, - ignoreChanges ...string) { - ctx := context.Background() - - inputsMap := resource.NewPropertyMapFromMap(inputs) - stateMap := resource.NewPropertyMapFromMap(state) - +func v1Setup(tfs map[string]*schema.Schema) ( + shim.SchemaMap, Resource, shim.Provider, map[string]*SchemaInfo, +) { sch := shimv1.NewSchemaMap(tfs) // Fake up a TF resource and a TF provider. @@ -220,59 +215,126 @@ func diffTest(t *testing.T, tfs map[string]*schema.Schema, info map[string]*Sche "resource": res, }, }) + info := map[string]*SchemaInfo{} // Convert the inputs and state to TF config and resource attributes. r := Resource{ TF: shimv1.NewResource(res), Schema: &ResourceInfo{Fields: info}, } - tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) - assert.NoError(t, err) - config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) - assert.NoError(t, err) + return sch, r, provider, info +} - t.Run("standard", func(t *testing.T) { - tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ - IgnoreChanges: newIgnoreChanges(ctx, sch, info, stateMap, inputsMap, ignoreChanges), - }) - assert.NoError(t, err) +func v1SetupFromv2Schema(tfs map[string]*v2Schema.Schema) ( + shim.SchemaMap, Resource, shim.Provider, map[string]*SchemaInfo, +) { + v1Schema := schemaconvert.Sdkv2ToV1SchemaMap(tfs) + return v1Setup(v1Schema) +} - // Convert the diff to a detailed diff and check the result. - diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) - expectedDiff := map[string]*pulumirpc.PropertyDiff{} - for k, v := range expected { - expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} - } - assert.Equal(t, expectedDiffChanges, changes) - assert.Equal(t, expectedDiff, diff) +func v2Setup(tfs map[string]*v2Schema.Schema) ( + shim.SchemaMap, Resource, shim.Provider, map[string]*SchemaInfo, +) { + sch := shimv2.NewSchemaMap(tfs) + + // Fake up a TF resource and a TF provider. + res := &v2Schema.Resource{ + Schema: tfs, + CustomizeDiff: func(_ context.Context, d *v2Schema.ResourceDiff, _ interface{}) error { + return d.SetNewComputed("outp") + }, + } + provider := shimv2.NewProvider(&v2Schema.Provider{ + ResourcesMap: map[string]*v2Schema.Resource{ + "resource": res, + }, }) + info := map[string]*SchemaInfo{} - // Add an ignoreChanges entry for each path in the expected diff, then re-convert the diff - // and check the result. - t.Run("withIgnoreAllExpected", func(t *testing.T) { - for k := range expected { - ignoreChanges = append(ignoreChanges, k) - } - tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ - IgnoreChanges: newIgnoreChanges(ctx, sch, info, stateMap, inputsMap, ignoreChanges), - }) - assert.NoError(t, err) + // Convert the inputs and state to TF config and resource attributes. + r := Resource{ + TF: shimv2.NewResource(res), + Schema: &ResourceInfo{Fields: info}, + } - diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) - assert.Equal(t, pulumirpc.DiffResponse_DIFF_NONE, changes) - assert.Equal(t, map[string]*pulumirpc.PropertyDiff{}, diff) - }) + return sch, r, provider, info +} + +// type for v2Setup and v1SetupFromv2Schema +type setupFunc func(tfs map[string]*v2Schema.Schema) ( + shim.SchemaMap, Resource, shim.Provider, map[string]*SchemaInfo) + +func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, + state map[string]interface{}, expected map[string]DiffKind, + expectedDiffChanges pulumirpc.DiffResponse_DiffChanges, + ignoreChanges ...string, +) { + ctx := context.Background() + + inputsMap := resource.NewPropertyMapFromMap(inputs) + stateMap := resource.NewPropertyMapFromMap(state) + + setup := []struct { + name string + setup setupFunc + }{ + {"v1", v1SetupFromv2Schema}, + {"v2", v2Setup}, + } + + for _, s := range setup { + t.Run(s.name, func(t *testing.T) { + sch, r, provider, info := s.setup(tfs) + + tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, + makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + assert.NoError(t, err) + + config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) + assert.NoError(t, err) + + t.Run("standard", func(t *testing.T) { + tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ + IgnoreChanges: newIgnoreChanges(ctx, sch, info, stateMap, inputsMap, ignoreChanges), + }) + assert.NoError(t, err) + + // Convert the diff to a detailed diff and check the result. + diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) + expectedDiff := map[string]*pulumirpc.PropertyDiff{} + for k, v := range expected { + expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} + } + assert.Equal(t, expectedDiffChanges, changes) + assert.Equal(t, expectedDiff, diff) + }) + + // Add an ignoreChanges entry for each path in the expected diff, then re-convert the diff + // and check the result. + t.Run("withIgnoreAllExpected", func(t *testing.T) { + for k := range expected { + ignoreChanges = append(ignoreChanges, k) + } + tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ + IgnoreChanges: newIgnoreChanges(ctx, sch, info, stateMap, inputsMap, ignoreChanges), + }) + assert.NoError(t, err) + + diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) + assert.Equal(t, pulumirpc.DiffResponse_DIFF_NONE, changes) + assert.Equal(t, map[string]*pulumirpc.PropertyDiff{}, diff) + }) + }) + } } func TestCustomDiffProducesReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -286,11 +348,10 @@ func TestCustomDiffProducesReplace(t *testing.T) { func TestEmptyDiff(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -304,11 +365,10 @@ func TestEmptyDiff(t *testing.T) { func TestSimpleAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, Optional: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, Optional: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -323,11 +383,10 @@ func TestSimpleAdd(t *testing.T) { func TestSimpleAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, Optional: true, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, Optional: true, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -342,11 +401,10 @@ func TestSimpleAddReplace(t *testing.T) { func TestSimpleDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, Optional: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, Optional: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -360,11 +418,10 @@ func TestSimpleDelete(t *testing.T) { func TestSimpleDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, Optional: true, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, Optional: true, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -378,11 +435,10 @@ func TestSimpleDeleteReplace(t *testing.T) { func TestSimpleUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -398,11 +454,10 @@ func TestSimpleUpdate(t *testing.T) { func TestSimpleUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -418,11 +473,10 @@ func TestSimpleUpdateReplace(t *testing.T) { func TestNestedAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, }, @@ -437,11 +491,10 @@ func TestNestedAdd(t *testing.T) { func TestNestedAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, }, @@ -456,11 +509,10 @@ func TestNestedAddReplace(t *testing.T) { func TestNestedDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, @@ -474,11 +526,10 @@ func TestNestedDelete(t *testing.T) { func TestNestedDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, @@ -492,11 +543,10 @@ func TestNestedDeleteReplace(t *testing.T) { func TestNestedUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "baz"}, }, @@ -512,11 +562,10 @@ func TestNestedUpdate(t *testing.T) { func TestNestedUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "baz"}, }, @@ -532,11 +581,10 @@ func TestNestedUpdateReplace(t *testing.T) { func TestNestedIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": "baz"}, }, @@ -551,11 +599,10 @@ func TestNestedIgnore(t *testing.T) { func TestListAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"foo"}, }, @@ -570,11 +617,10 @@ func TestListAdd(t *testing.T) { func TestListAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"foo"}, }, @@ -589,11 +635,10 @@ func TestListAddReplace(t *testing.T) { func TestListDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": []interface{}{"foo"}, @@ -607,11 +652,10 @@ func TestListDelete(t *testing.T) { func TestListDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": []interface{}{"foo"}, @@ -625,11 +669,10 @@ func TestListDeleteReplace(t *testing.T) { func TestListUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -645,11 +688,10 @@ func TestListUpdate(t *testing.T) { func TestListUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -665,11 +707,10 @@ func TestListUpdateReplace(t *testing.T) { func TestListIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -684,11 +725,10 @@ func TestListIgnore(t *testing.T) { func TestMaxItemsOneListAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -704,11 +744,10 @@ func TestMaxItemsOneListAdd(t *testing.T) { func TestMaxItemsOneListAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -724,11 +763,10 @@ func TestMaxItemsOneListAddReplace(t *testing.T) { func TestMaxItemsOneListDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -742,11 +780,10 @@ func TestMaxItemsOneListDelete(t *testing.T) { func TestMaxItemsOneListDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -760,11 +797,10 @@ func TestMaxItemsOneListDeleteReplace(t *testing.T) { func TestMaxItemsOneListUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -780,11 +816,10 @@ func TestMaxItemsOneListUpdate(t *testing.T) { func TestMaxItemsOneListUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -800,11 +835,10 @@ func TestMaxItemsOneListUpdateReplace(t *testing.T) { func TestMaxItemsOneListIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -819,15 +853,14 @@ func TestMaxItemsOneListIgnore(t *testing.T) { func TestSetAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"foo"}, }, @@ -842,16 +875,15 @@ func TestSetAdd(t *testing.T) { func TestSetAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"foo"}, }, @@ -866,15 +898,14 @@ func TestSetAddReplace(t *testing.T) { func TestSetDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": []interface{}{"foo"}, @@ -888,16 +919,15 @@ func TestSetDelete(t *testing.T) { func TestSetDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": []interface{}{"foo"}, @@ -911,11 +941,10 @@ func TestSetDeleteReplace(t *testing.T) { func TestSetUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -931,11 +960,10 @@ func TestSetUpdate(t *testing.T) { func TestSetIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -950,11 +978,10 @@ func TestSetIgnore(t *testing.T) { func TestSetUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{"baz"}, }, @@ -970,16 +997,15 @@ func TestSetUpdateReplace(t *testing.T) { func TestMaxItemsOneSetAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -995,17 +1021,16 @@ func TestMaxItemsOneSetAdd(t *testing.T) { func TestMaxItemsOneSetAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "foo", }, @@ -1021,16 +1046,15 @@ func TestMaxItemsOneSetAddReplace(t *testing.T) { func TestMaxItemsOneSetDelete(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -1044,17 +1068,16 @@ func TestMaxItemsOneSetDelete(t *testing.T) { func TestMaxItemsOneSetDeleteReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, + Type: v2Schema.TypeSet, Set: func(_ interface{}) int { return 0 }, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{}, map[string]interface{}{ "prop": "foo", @@ -1068,11 +1091,10 @@ func TestMaxItemsOneSetDeleteReplace(t *testing.T) { func TestMaxItemsOneSetUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -1088,11 +1110,10 @@ func TestMaxItemsOneSetUpdate(t *testing.T) { func TestMaxItemsOneSetIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -1107,11 +1128,10 @@ func TestMaxItemsOneSetIgnore(t *testing.T) { func TestMaxItemsOneSetUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true, MaxItems: 1}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, MaxItems: 1}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": "baz", }, @@ -1127,18 +1147,17 @@ func TestMaxItemsOneSetUpdateReplace(t *testing.T) { func TestSetNestedUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "baz"}}, }, @@ -1154,18 +1173,17 @@ func TestSetNestedUpdate(t *testing.T) { func TestSetNestedUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true, ForceNew: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true, ForceNew: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "baz"}}, }, @@ -1182,18 +1200,17 @@ func TestSetNestedUpdateReplace(t *testing.T) { func TestSetNestedIgnore(t *testing.T) { for _, ignore := range []string{"prop[0]", "prop"} { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "baz"}}, }, @@ -1209,11 +1226,10 @@ func TestSetNestedIgnore(t *testing.T) { func TestComputedSimpleUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1229,11 +1245,10 @@ func TestComputedSimpleUpdate(t *testing.T) { func TestComputedSimpleUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeString, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeString, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1249,11 +1264,10 @@ func TestComputedSimpleUpdateReplace(t *testing.T) { func TestComputedMapUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1269,11 +1283,10 @@ func TestComputedMapUpdate(t *testing.T) { func TestComputedNestedUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": computedValue}, }, @@ -1289,11 +1302,10 @@ func TestComputedNestedUpdate(t *testing.T) { func TestComputedNestedUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": computedValue}, }, @@ -1309,11 +1321,10 @@ func TestComputedNestedUpdateReplace(t *testing.T) { func TestComputedNestedIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeMap}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeMap}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{"nest": computedValue}, }, @@ -1328,11 +1339,10 @@ func TestComputedNestedIgnore(t *testing.T) { func TestComputedListUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1348,11 +1358,10 @@ func TestComputedListUpdate(t *testing.T) { func TestComputedListElementUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1368,11 +1377,10 @@ func TestComputedListElementUpdate(t *testing.T) { func TestComputedListElementUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1388,11 +1396,10 @@ func TestComputedListElementUpdateReplace(t *testing.T) { func TestComputedListElementIgnore(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeList, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1407,11 +1414,10 @@ func TestComputedListElementIgnore(t *testing.T) { func TestComputedSetUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1427,11 +1433,10 @@ func TestComputedSetUpdate(t *testing.T) { func TestNestedComputedSetUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1447,11 +1452,10 @@ func TestNestedComputedSetUpdate(t *testing.T) { func TestNestedComputedSetAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1466,11 +1470,10 @@ func TestNestedComputedSetAdd(t *testing.T) { func TestNestedComputedSetUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1486,11 +1489,10 @@ func TestNestedComputedSetUpdateReplace(t *testing.T) { func TestNestedComputedSetIntUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeInt}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1506,11 +1508,10 @@ func TestNestedComputedSetIntUpdate(t *testing.T) { func TestNestedComputedSetIntUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeInt}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1526,11 +1527,10 @@ func TestNestedComputedSetIntUpdateReplace(t *testing.T) { func TestNestedComputedSetIntAdd(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeInt}}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{computedValue}, }, @@ -1545,11 +1545,10 @@ func TestNestedComputedSetIntAdd(t *testing.T) { func TestComputedSetUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ - "prop": {Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, ForceNew: true}, - "outp": {Type: schema.TypeString, Computed: true}, + map[string]*v2Schema.Schema{ + "prop": {Type: v2Schema.TypeSet, Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": computedValue, }, @@ -1565,18 +1564,17 @@ func TestComputedSetUpdateReplace(t *testing.T) { func TestComputedSetNestedUpdate(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": computedValue}}, }, @@ -1592,18 +1590,17 @@ func TestComputedSetNestedUpdate(t *testing.T) { func TestComputedSetNestedUpdateReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true, ForceNew: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true, ForceNew: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": computedValue}}, }, @@ -1620,18 +1617,17 @@ func TestComputedSetNestedUpdateReplace(t *testing.T) { func TestComputedSetNestedIgnore(t *testing.T) { for _, ignore := range []string{"prop[0]", "prop"} { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": computedValue}}, }, @@ -1647,24 +1643,23 @@ func TestComputedSetNestedIgnore(t *testing.T) { func TestRawElementNames(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeList, + Type: v2Schema.TypeList, Optional: true, MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ "variables": { - Type: schema.TypeMap, + Type: v2Schema.TypeMap, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, }, }, }, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": map[string]interface{}{ "variables": map[string]interface{}{ @@ -1844,19 +1839,19 @@ func TestCollectionsWithMultipleItems(t *testing.T) { }, } - runTestCase := func(t *testing.T, name string, typ schema.ValueType, inputs, state []interface{}, - expected map[string]DiffKind, expectedChanges pulumirpc.DiffResponse_DiffChanges) { + runTestCase := func(t *testing.T, name string, typ v2Schema.ValueType, inputs, state []interface{}, + expected map[string]DiffKind, expectedChanges pulumirpc.DiffResponse_DiffChanges, + ) { t.Run(name, func(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { Type: typ, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &v2Schema.Schema{Type: v2Schema.TypeString}, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": inputs, // inputs }, @@ -1872,32 +1867,31 @@ func TestCollectionsWithMultipleItems(t *testing.T) { t.Run("Set", func(t *testing.T) { for _, tc := range testCases { - runTestCase(t, tc.name, schema.TypeSet, tc.input, tc.state, tc.expectedDiffForSet, tc.expectedChangesForSet) + runTestCase(t, tc.name, v2Schema.TypeSet, tc.input, tc.state, tc.expectedDiffForSet, tc.expectedChangesForSet) } }) t.Run("List", func(t *testing.T) { for _, tc := range testCases { - runTestCase(t, tc.name, schema.TypeList, tc.input, tc.state, tc.expectedDiffForList, tc.expectedChangesForList) + runTestCase(t, tc.name, v2Schema.TypeList, tc.input, tc.state, tc.expectedDiffForList, tc.expectedChangesForList) } }) } func TestSetNestedAddReplace(t *testing.T) { diffTest(t, - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, - map[string]*SchemaInfo{}, map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "baz"}}, }, @@ -1914,20 +1908,19 @@ func TestSetNestedAddReplace(t *testing.T) { func TestListNestedAddReplace(t *testing.T) { diffTest(t, // tfSchema - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeList, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, // info - map[string]*SchemaInfo{}, // inputs map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "foo"}}, @@ -1947,20 +1940,19 @@ func TestListNestedAddReplace(t *testing.T) { func TestListNestedUpdate(t *testing.T) { diffTest(t, // tfSchema - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeList, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, // info - map[string]*SchemaInfo{}, // inputs map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "foo"}}, @@ -1980,20 +1972,19 @@ func TestListNestedUpdate(t *testing.T) { func TestListNestedDeleteReplace(t *testing.T) { diffTest(t, // tfSchema - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeList, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, // info - map[string]*SchemaInfo{}, // inputs map[string]interface{}{}, // state @@ -2011,20 +2002,19 @@ func TestListNestedDeleteReplace(t *testing.T) { func TestSetNestedDeleteReplace(t *testing.T) { diffTest(t, // tfSchema - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeSet, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeSet, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, // info - map[string]*SchemaInfo{}, // inputs map[string]interface{}{}, // state @@ -2042,21 +2032,20 @@ func TestSetNestedDeleteReplace(t *testing.T) { func TestListNestedAddMaxItemsOne(t *testing.T) { diffTest(t, // tfSchema - map[string]*schema.Schema{ + map[string]*v2Schema.Schema{ "prop": { - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nest": {Type: schema.TypeString, Required: true}, + Type: v2Schema.TypeList, + Elem: &v2Schema.Resource{ + Schema: map[string]*v2Schema.Schema{ + "nest": {Type: v2Schema.TypeString, Required: true}, }, }, MaxItems: 1, ForceNew: true, }, - "outp": {Type: schema.TypeString, Computed: true}, + "outp": {Type: v2Schema.TypeString, Computed: true}, }, // info - map[string]*SchemaInfo{}, // inputs map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, From d8395ffd0a69613dd987c3334a7a560766fff4b0 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 12:45:57 +0100 Subject: [PATCH 38/52] make new config and state for each test --- pkg/tfbridge/diff_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index fe4217f73..896d2dc02 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -309,7 +309,19 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, assert.Equal(t, expectedDiffChanges, changes) assert.Equal(t, expectedDiff, diff) }) + }) + } + + for _, s := range setup { + t.Run(s.name, func(t *testing.T) { + sch, r, provider, info := s.setup(tfs) + tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, + makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + assert.NoError(t, err) + + config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) + assert.NoError(t, err) // Add an ignoreChanges entry for each path in the expected diff, then re-convert the diff // and check the result. t.Run("withIgnoreAllExpected", func(t *testing.T) { From 9d054302a1e72c158fbdad3bb427d49c7d5d47a7 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 12:46:59 +0100 Subject: [PATCH 39/52] separate setup for each test --- pkg/tfbridge/diff_test.go | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 896d2dc02..d5251ab0d 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -285,16 +285,15 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, for _, s := range setup { t.Run(s.name, func(t *testing.T) { - sch, r, provider, info := s.setup(tfs) - - tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) - assert.NoError(t, err) + t.Run("standard", func(t *testing.T) { + sch, r, provider, info := s.setup(tfs) - config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) - assert.NoError(t, err) + tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, + makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + assert.NoError(t, err) - t.Run("standard", func(t *testing.T) { + config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) + assert.NoError(t, err) tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ IgnoreChanges: newIgnoreChanges(ctx, sch, info, stateMap, inputsMap, ignoreChanges), }) @@ -314,17 +313,17 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, for _, s := range setup { t.Run(s.name, func(t *testing.T) { - sch, r, provider, info := s.setup(tfs) - - tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) - assert.NoError(t, err) - - config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) - assert.NoError(t, err) // Add an ignoreChanges entry for each path in the expected diff, then re-convert the diff // and check the result. t.Run("withIgnoreAllExpected", func(t *testing.T) { + sch, r, provider, info := s.setup(tfs) + tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, + makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + assert.NoError(t, err) + + config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) + assert.NoError(t, err) + for k := range expected { ignoreChanges = append(ignoreChanges, k) } From 0573b9bf26cae9d7cf538398fcc53388d2f0235d Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 12:54:59 +0100 Subject: [PATCH 40/52] move schemaconvert --- go.mod | 3 --- pf/go.mod | 2 +- pf/go.sum | 4 ++-- pkg/tfbridge/diff_test.go | 7 +------ .../internal}/schemaconvert/schemaconvert.go | 0 5 files changed, 4 insertions(+), 12 deletions(-) rename pkg/{tests => tfbridge/internal}/schemaconvert/schemaconvert.go (100%) diff --git a/go.mod b/go.mod index 9ce42f612..62c00e88b 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,6 @@ go 1.21 replace github.com/pulumi/pulumi-terraform-bridge/x/muxer => ./x/muxer -replace github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests => ./pkg/tests - require ( github.com/apparentlymart/go-cidr v1.1.0 github.com/blang/semver v3.5.1+incompatible @@ -40,7 +38,6 @@ require ( github.com/pulumi/inflector v0.1.1 github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-java/pkg v0.11.0 - github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests v0.0.0-00010101000000-000000000000 github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.8 github.com/pulumi/pulumi-yaml v1.8.0 github.com/pulumi/schema-tools v0.1.2 diff --git a/pf/go.mod b/pf/go.mod index 01d2cc949..ab4ec9592 100644 --- a/pf/go.mod +++ b/pf/go.mod @@ -16,7 +16,7 @@ require ( github.com/hashicorp/terraform-plugin-go v0.22.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 - github.com/pulumi/providertest v0.0.11 + github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-terraform-bridge/v3 v3.86.0 github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.8 github.com/stretchr/testify v1.9.0 diff --git a/pf/go.sum b/pf/go.sum index 060ecc01a..8c1d18101 100644 --- a/pf/go.sum +++ b/pf/go.sum @@ -1900,8 +1900,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.11 h1:mg8MQ7Cq7+9XlHIkBD+aCqQO4mwAJEISngZgVdnQUe8= -github.com/pulumi/providertest v0.0.11/go.mod h1:HsxjVsytcMIuNj19w1lT2W0QXY0oReXl1+h6eD2JXP8= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-yaml v1.8.0 h1:bhmidiCMMuzsJao5FE0UR69iF3WVKPCFrRkzjotFNn4= diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index d5251ab0d..d797dd886 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests/schemaconvert" + "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/internal/schemaconvert" shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim" shimv1 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v1" shimv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2" @@ -1931,7 +1931,6 @@ func TestListNestedAddReplace(t *testing.T) { }, "outp": {Type: v2Schema.TypeString, Computed: true}, }, - // info // inputs map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "foo"}}, @@ -1963,7 +1962,6 @@ func TestListNestedUpdate(t *testing.T) { }, "outp": {Type: v2Schema.TypeString, Computed: true}, }, - // info // inputs map[string]interface{}{ "prop": []interface{}{map[string]interface{}{"nest": "foo"}}, @@ -1995,7 +1993,6 @@ func TestListNestedDeleteReplace(t *testing.T) { }, "outp": {Type: v2Schema.TypeString, Computed: true}, }, - // info // inputs map[string]interface{}{}, // state @@ -2025,7 +2022,6 @@ func TestSetNestedDeleteReplace(t *testing.T) { }, "outp": {Type: v2Schema.TypeString, Computed: true}, }, - // info // inputs map[string]interface{}{}, // state @@ -2056,7 +2052,6 @@ func TestListNestedAddMaxItemsOne(t *testing.T) { }, "outp": {Type: v2Schema.TypeString, Computed: true}, }, - // info // inputs map[string]interface{}{ "prop": map[string]interface{}{"nest": "foo"}, diff --git a/pkg/tests/schemaconvert/schemaconvert.go b/pkg/tfbridge/internal/schemaconvert/schemaconvert.go similarity index 100% rename from pkg/tests/schemaconvert/schemaconvert.go rename to pkg/tfbridge/internal/schemaconvert/schemaconvert.go From b5177ec134306d4b77bb24c931eb06aff4afc280 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 12:55:19 +0100 Subject: [PATCH 41/52] lint --- pkg/tfbridge/internal/schemaconvert/schemaconvert.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/tfbridge/internal/schemaconvert/schemaconvert.go b/pkg/tfbridge/internal/schemaconvert/schemaconvert.go index 6aca18e52..18f49fd23 100644 --- a/pkg/tfbridge/internal/schemaconvert/schemaconvert.go +++ b/pkg/tfbridge/internal/schemaconvert/schemaconvert.go @@ -32,7 +32,8 @@ func Sdkv2ToV1Resource(sch *v2Schema.Resource) *v1Schema.Resource { contract.Failf("StateUpgraders is not supported in conversion") } if sch.Create != nil || sch.Read != nil || sch.Update != nil || sch.Delete != nil || sch.Exists != nil || - sch.CreateContext != nil || sch.ReadContext != nil || sch.UpdateContext != nil || sch.DeleteContext != nil || sch.Importer != nil { + sch.CreateContext != nil || sch.ReadContext != nil || sch.UpdateContext != nil || + sch.DeleteContext != nil || sch.Importer != nil { contract.Failf("runtime methods not supported in conversion") } From 19736870b3a81f20c462fe34a8008470c0675442 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:01:28 +0100 Subject: [PATCH 42/52] lint --- .../internal/schemaconvert/schemaconvert.go | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/pkg/tfbridge/internal/schemaconvert/schemaconvert.go b/pkg/tfbridge/internal/schemaconvert/schemaconvert.go index 18f49fd23..95effb2e1 100644 --- a/pkg/tfbridge/internal/schemaconvert/schemaconvert.go +++ b/pkg/tfbridge/internal/schemaconvert/schemaconvert.go @@ -25,12 +25,14 @@ func Sdkv2ToV1SchemaOrResource(elem interface{}) interface{} { } func Sdkv2ToV1Resource(sch *v2Schema.Resource) *v1Schema.Resource { + //nolint:staticcheck if sch.MigrateState != nil { contract.Failf("MigrateState is not supported in conversion") } if sch.StateUpgraders != nil { contract.Failf("StateUpgraders is not supported in conversion") } + //nolint:staticcheck if sch.Create != nil || sch.Read != nil || sch.Update != nil || sch.Delete != nil || sch.Exists != nil || sch.CreateContext != nil || sch.ReadContext != nil || sch.UpdateContext != nil || sch.DeleteContext != nil || sch.Importer != nil { @@ -98,20 +100,21 @@ func Sdkv2ToV1Schema(sch *v2Schema.Schema) *v1Schema.Schema { } return &v1Schema.Schema{ - Type: Sdkv2ToV1Type(sch.Type), - Optional: sch.Optional, - Required: sch.Required, - Default: sch.Default, - DefaultFunc: defaultFunc, - Description: sch.Description, - InputDefault: sch.InputDefault, - Computed: sch.Computed, - ForceNew: sch.ForceNew, - StateFunc: stateFunc, - Elem: Sdkv2ToV1SchemaOrResource(sch.Elem), - MaxItems: sch.MaxItems, - MinItems: sch.MinItems, - Set: set, + Type: Sdkv2ToV1Type(sch.Type), + Optional: sch.Optional, + Required: sch.Required, + Default: sch.Default, + DefaultFunc: defaultFunc, + Description: sch.Description, + InputDefault: sch.InputDefault, + Computed: sch.Computed, + ForceNew: sch.ForceNew, + StateFunc: stateFunc, + Elem: Sdkv2ToV1SchemaOrResource(sch.Elem), + MaxItems: sch.MaxItems, + MinItems: sch.MinItems, + Set: set, + //nolint:staticcheck ComputedWhen: sch.ComputedWhen, ConflictsWith: sch.ConflictsWith, ExactlyOneOf: sch.ExactlyOneOf, From fc38c75b3c1f79383d61ff41d0dfb8b1908d75da Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:09:04 +0100 Subject: [PATCH 43/52] add a v2 override --- pkg/tfbridge/diff_test.go | 97 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index d797dd886..374fa9d69 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -105,7 +105,8 @@ func TestCustomizeDiff(t *testing.T) { for k, v := range expected { expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } - assert.Equal(t, pulumirpc.DiffResponse_DIFF_SOME, changes) + assert.Equal(t, + pulumirpc.DiffResponse_DIFF_SOME, changes) assert.Equal(t, expectedDiff, diff) }) @@ -267,6 +268,7 @@ type setupFunc func(tfs map[string]*v2Schema.Schema) ( func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, state map[string]interface{}, expected map[string]DiffKind, + expectedV2Override map[string]DiffKind, expectedDiffChanges pulumirpc.DiffResponse_DiffChanges, ignoreChanges ...string, ) { @@ -275,12 +277,18 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, inputsMap := resource.NewPropertyMapFromMap(inputs) stateMap := resource.NewPropertyMapFromMap(state) + v2Expected := expected + if expectedV2Override != nil { + v2Expected = expectedV2Override + } + setup := []struct { - name string - setup setupFunc + name string + setup setupFunc + expected map[string]DiffKind }{ - {"v1", v1SetupFromv2Schema}, - {"v2", v2Setup}, + {"v1", v1SetupFromv2Schema, expected}, + {"v2", v2Setup, v2Expected}, } for _, s := range setup { @@ -302,7 +310,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, // Convert the diff to a detailed diff and check the result. diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) expectedDiff := map[string]*pulumirpc.PropertyDiff{} - for k, v := range expected { + for k, v := range s.expected { expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } assert.Equal(t, expectedDiffChanges, changes) @@ -324,7 +332,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) assert.NoError(t, err) - for k := range expected { + for k := range s.expected { ignoreChanges = append(ignoreChanges, k) } tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ @@ -354,6 +362,7 @@ func TestCustomDiffProducesReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE) } @@ -371,6 +380,7 @@ func TestEmptyDiff(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE) } @@ -389,6 +399,7 @@ func TestSimpleAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -407,6 +418,7 @@ func TestSimpleAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -424,6 +436,7 @@ func TestSimpleDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -441,6 +454,7 @@ func TestSimpleDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -460,6 +474,7 @@ func TestSimpleUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -479,6 +494,7 @@ func TestSimpleUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -497,6 +513,7 @@ func TestNestedAdd(t *testing.T) { map[string]DiffKind{ "prop.nest": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -515,6 +532,7 @@ func TestNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -532,6 +550,7 @@ func TestNestedDelete(t *testing.T) { map[string]DiffKind{ "prop.nest": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -549,6 +568,7 @@ func TestNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -568,6 +588,7 @@ func TestNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop.nest": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -587,6 +608,7 @@ func TestNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -604,6 +626,7 @@ func TestNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -623,6 +646,7 @@ func TestListAdd(t *testing.T) { map[string]DiffKind{ "prop[0]": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -641,6 +665,7 @@ func TestListAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -658,6 +683,7 @@ func TestListDelete(t *testing.T) { map[string]DiffKind{ "prop[0]": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -675,6 +701,7 @@ func TestListDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -694,6 +721,7 @@ func TestListUpdate(t *testing.T) { map[string]DiffKind{ "prop[0]": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -713,6 +741,7 @@ func TestListUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -730,6 +759,7 @@ func TestListIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -750,6 +780,7 @@ func TestMaxItemsOneListAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -769,6 +800,7 @@ func TestMaxItemsOneListAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -786,6 +818,7 @@ func TestMaxItemsOneListDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -803,6 +836,7 @@ func TestMaxItemsOneListDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -822,6 +856,7 @@ func TestMaxItemsOneListUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -841,6 +876,7 @@ func TestMaxItemsOneListUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -858,6 +894,7 @@ func TestMaxItemsOneListIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -881,6 +918,7 @@ func TestSetAdd(t *testing.T) { map[string]DiffKind{ "prop[0]": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -904,6 +942,7 @@ func TestSetAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -925,6 +964,7 @@ func TestSetDelete(t *testing.T) { map[string]DiffKind{ "prop[0]": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -947,6 +987,7 @@ func TestSetDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -966,6 +1007,7 @@ func TestSetUpdate(t *testing.T) { map[string]DiffKind{ "prop[0]": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -983,6 +1025,7 @@ func TestSetIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1003,6 +1046,7 @@ func TestSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1027,6 +1071,7 @@ func TestMaxItemsOneSetAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1052,6 +1097,7 @@ func TestMaxItemsOneSetAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1074,6 +1120,7 @@ func TestMaxItemsOneSetDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1097,6 +1144,7 @@ func TestMaxItemsOneSetDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1116,6 +1164,7 @@ func TestMaxItemsOneSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1133,6 +1182,7 @@ func TestMaxItemsOneSetIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1153,6 +1203,7 @@ func TestMaxItemsOneSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1179,6 +1230,7 @@ func TestSetNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1205,6 +1257,7 @@ func TestSetNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1230,6 +1283,7 @@ func TestSetNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, ignore) } @@ -1251,6 +1305,7 @@ func TestComputedSimpleUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1270,6 +1325,7 @@ func TestComputedSimpleUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1289,6 +1345,7 @@ func TestComputedMapUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1308,6 +1365,7 @@ func TestComputedNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1327,6 +1385,7 @@ func TestComputedNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1344,6 +1403,7 @@ func TestComputedNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1364,6 +1424,7 @@ func TestComputedListUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1383,6 +1444,7 @@ func TestComputedListElementUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1402,6 +1464,7 @@ func TestComputedListElementUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1419,6 +1482,7 @@ func TestComputedListElementIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1439,6 +1503,7 @@ func TestComputedSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1458,6 +1523,7 @@ func TestNestedComputedSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1476,6 +1542,7 @@ func TestNestedComputedSetAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1495,6 +1562,7 @@ func TestNestedComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1514,6 +1582,7 @@ func TestNestedComputedSetIntUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1533,6 +1602,7 @@ func TestNestedComputedSetIntUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1551,6 +1621,7 @@ func TestNestedComputedSetIntAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1570,6 +1641,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1596,6 +1668,7 @@ func TestComputedSetNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1622,6 +1695,7 @@ func TestComputedSetNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": UR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1647,6 +1721,7 @@ func TestComputedSetNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, + nil, pulumirpc.DiffResponse_DIFF_NONE, ignore) } @@ -1688,6 +1763,7 @@ func TestRawElementNames(t *testing.T) { map[string]DiffKind{ "prop.variables.DYNAMODB_ROUTE_TABLE_NAME": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1871,6 +1947,7 @@ func TestCollectionsWithMultipleItems(t *testing.T) { "outp": "bar", }, expected, + nil, expectedChanges, ) }) @@ -1913,6 +1990,7 @@ func TestSetNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1944,6 +2022,7 @@ func TestListNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1975,6 +2054,7 @@ func TestListNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2004,6 +2084,7 @@ func TestListNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2033,6 +2114,7 @@ func TestSetNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": DR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2064,6 +2146,7 @@ func TestListNestedAddMaxItemsOne(t *testing.T) { map[string]DiffKind{ "prop.nest": AR, }, + nil, pulumirpc.DiffResponse_DIFF_SOME) } From beea3a343d6cd19ccf7416bc1e6b294f5e3098d2 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:10:47 +0100 Subject: [PATCH 44/52] go mod tidy --- pkg/tests/go.mod | 4 ---- pkg/tests/go.sum | 1 - 2 files changed, 5 deletions(-) diff --git a/pkg/tests/go.mod b/pkg/tests/go.mod index 48e6ff2b3..009070147 100644 --- a/pkg/tests/go.mod +++ b/pkg/tests/go.mod @@ -8,7 +8,6 @@ replace ( ) require ( - github.com/hashicorp/terraform-plugin-sdk v1.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hexops/autogold/v2 v2.2.1 github.com/hexops/valast v1.4.4 @@ -66,8 +65,6 @@ require ( github.com/iancoleman/strcase v0.2.0 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/klauspost/compress v1.15.11 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-localereader v0.0.1 // indirect @@ -94,7 +91,6 @@ require ( github.com/ulikunitz/xz v0.5.10 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/zclconf/go-cty-yaml v1.0.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect diff --git a/pkg/tests/go.sum b/pkg/tests/go.sum index af71a733f..6ada63733 100644 --- a/pkg/tests/go.sum +++ b/pkg/tests/go.sum @@ -1651,7 +1651,6 @@ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8 h1:+RyjwU+Gnd/aTJBPZVDNm903eXVjjqhbaR4Ypx3xYyY= github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/terraform-json v0.4.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU= From 8e17f48a4ffae83d56dd40ded866531b6d26c34c Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:33:17 +0100 Subject: [PATCH 45/52] rework schema.go to support both strategies for unknowns --- pkg/tfbridge/diff_test.go | 12 ++--- pkg/tfbridge/provider.go | 35 +++++++++---- pkg/tfbridge/schema.go | 102 +++++++++++++++++++++++++++++------- pkg/tfbridge/schema_test.go | 18 +++---- pkg/tfshim/shim.go | 4 ++ 5 files changed, 127 insertions(+), 44 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index f39027849..98bf2a96d 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -88,7 +88,7 @@ func TestCustomizeDiff(t *testing.T) { Schema: &ResourceInfo{Fields: info}, } tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: true}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -131,7 +131,7 @@ func TestCustomizeDiff(t *testing.T) { Schema: &ResourceInfo{Fields: info}, } tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: true}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -185,7 +185,7 @@ func TestCustomizeDiff(t *testing.T) { Schema: &ResourceInfo{Fields: info}, } tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: true}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -297,7 +297,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, sch, r, provider, info := s.setup(tfs) tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -326,7 +326,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, t.Run("withIgnoreAllExpected", func(t *testing.T) { sch, r, provider, info := s.setup(tfs) tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -1651,7 +1651,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an UR. // makeDetailedDiff returns an empty diff for collections - "prop": AR, + "prop": UR, "prop[0]": DR, }, nil, diff --git a/pkg/tfbridge/provider.go b/pkg/tfbridge/provider.go index f30a1119c..a56804479 100644 --- a/pkg/tfbridge/provider.go +++ b/pkg/tfbridge/provider.go @@ -665,7 +665,8 @@ func buildTerraformConfig(ctx context.Context, p *Provider, vars resource.Proper } } - inputs, _, err := MakeTerraformInputs(ctx, nil, tfVars, nil, tfVars, p.config, p.info.Config) + inputs, _, err := makeTerraformInputsWithOptions(ctx, nil, tfVars, nil, tfVars, p.config, p.info.Config, + makeTerraformInputsOptions{UnknownCollectionsSupported: p.tf.SupportsUnknownCollections()}) if err != nil { return nil, err } @@ -971,7 +972,7 @@ func (p *Provider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (*pul inputs, _, err := makeTerraformInputsWithOptions(ctx, &PulumiResource{URN: urn, Properties: news, Seed: req.RandomSeed}, p.configValues, olds, news, schemaMap, res.Schema.Fields, - makeTerraformInputsOptions{DisableTFDefaults: true}) + makeTerraformInputsOptions{DisableTFDefaults: true, UnknownCollectionsSupported: p.tf.SupportsUnknownCollections()}) if err != nil { return nil, err } @@ -987,9 +988,10 @@ func (p *Provider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (*pul failures = append(failures, p.adaptCheckFailures(ctx, urn, false /*isProvider*/, schemaMap, schemaInfos, errs)...) // Now re-generate the inputs WITH the TF defaults - inputs, assets, err := MakeTerraformInputs(ctx, + inputs, assets, err := makeTerraformInputsWithOptions(ctx, &PulumiResource{URN: urn, Properties: news, Seed: req.RandomSeed}, - p.configValues, olds, news, schemaMap, res.Schema.Fields) + p.configValues, olds, news, schemaMap, res.Schema.Fields, + makeTerraformInputsOptions{UnknownCollectionsSupported: p.tf.SupportsUnknownCollections()}) if err != nil { return nil, err } @@ -1073,7 +1075,10 @@ func (p *Provider) Diff(ctx context.Context, req *pulumirpc.DiffRequest) (*pulum } state, err := makeTerraformStateWithOpts(ctx, res, req.GetId(), olds, - makeTerraformStateOptions{defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion}, //nolint: gosimple + makeTerraformStateOptions{ + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), + }, ) if err != nil { return nil, errors.Wrapf(err, "unmarshaling %s's instance state", urn) @@ -1347,7 +1352,10 @@ func (p *Provider) Read(ctx context.Context, req *pulumirpc.ReadRequest) (*pulum return nil, err } state, err := unmarshalTerraformStateWithOpts(ctx, res, id, req.GetProperties(), fmt.Sprintf("%s.state", label), - unmarshalTerraformStateOptions{defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion}) //nolint: gosimple + unmarshalTerraformStateOptions{ + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), + }) if err != nil { return nil, errors.Wrapf(err, "unmarshaling %s's instance state", urn) } @@ -1462,7 +1470,10 @@ func (p *Provider) Update(ctx context.Context, req *pulumirpc.UpdateRequest) (*p } state, err := makeTerraformStateWithOpts(ctx, res, req.GetId(), olds, - makeTerraformStateOptions{defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion}) //nolint: gosimple + makeTerraformStateOptions{ + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), + }) if err != nil { return nil, errors.Wrapf(err, "unmarshaling %s's instance state", urn) } @@ -1592,7 +1603,10 @@ func (p *Provider) Delete(ctx context.Context, req *pulumirpc.DeleteRequest) (*p } // Fetch the resource attributes since many providers need more than just the ID to perform the delete. state, err := unmarshalTerraformStateWithOpts(ctx, res, req.GetId(), req.GetProperties(), label, - unmarshalTerraformStateOptions{defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion}) //nolint: gosimple + unmarshalTerraformStateOptions{ + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), + }) if err != nil { return nil, err } @@ -1646,13 +1660,14 @@ func (p *Provider) Invoke(ctx context.Context, req *pulumirpc.InvokeRequest) (*p // First, create the inputs. tfname := ds.TFName - inputs, _, err := MakeTerraformInputs( + inputs, _, err := makeTerraformInputsWithOptions( ctx, &PulumiResource{Properties: args}, p.configValues, nil, args, ds.TF.Schema(), - ds.Schema.Fields) + ds.Schema.Fields, + makeTerraformInputsOptions{UnknownCollectionsSupported: p.tf.SupportsUnknownCollections()}) if err != nil { return nil, errors.Wrapf(err, "couldn't prepare resource %v input state", tfname) } diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index 9e402030c..af0417b29 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -287,18 +287,20 @@ func elemSchemas(sch shim.Schema, ps *SchemaInfo) (shim.Schema, *SchemaInfo) { } type conversionContext struct { - Ctx context.Context - ComputeDefaultOptions ComputeDefaultOptions - ProviderConfig resource.PropertyMap - ApplyDefaults bool - ApplyTFDefaults bool - ApplyMaxItemsOneDefaults bool - Assets AssetTable + Ctx context.Context + ComputeDefaultOptions ComputeDefaultOptions + ProviderConfig resource.PropertyMap + ApplyDefaults bool + ApplyTFDefaults bool + ApplyMaxItemsOneDefaults bool + Assets AssetTable + UnknownCollectionsSupported bool } type makeTerraformInputsOptions struct { - DisableDefaults bool - DisableTFDefaults bool + DisableDefaults bool + DisableTFDefaults bool + UnknownCollectionsSupported bool } func makeTerraformInputsWithOptions( @@ -317,12 +319,13 @@ func makeTerraformInputsWithOptions( } cctx := &conversionContext{ - Ctx: ctx, - ComputeDefaultOptions: cdOptions, - ProviderConfig: config, - ApplyDefaults: !opts.DisableDefaults, - ApplyTFDefaults: !opts.DisableTFDefaults, - Assets: AssetTable{}, + Ctx: ctx, + ComputeDefaultOptions: cdOptions, + ProviderConfig: config, + ApplyDefaults: !opts.DisableDefaults, + ApplyTFDefaults: !opts.DisableTFDefaults, + Assets: AssetTable{}, + UnknownCollectionsSupported: opts.UnknownCollectionsSupported, } inputs, err := cctx.makeTerraformInputs(olds, news, tfs, ps) @@ -332,6 +335,7 @@ func makeTerraformInputsWithOptions( return inputs, cctx.Assets, err } +// Unused internally, use makeTerraformInputsWithOptions instead. func MakeTerraformInputs( ctx context.Context, instance *PulumiResource, config resource.PropertyMap, olds, news resource.PropertyMap, tfs shim.SchemaMap, ps map[string]*SchemaInfo, @@ -530,7 +534,7 @@ func (ctx *conversionContext) makeTerraformInput( // If any variables are unknown, we need to mark them in the inputs so the config map treats it right. This // requires the use of the special UnknownVariableValue sentinel in Terraform, which is how it internally stores // interpolated variables whose inputs are currently unknown. - return TerraformUnknownVariableValue, nil + return makeTerraformUnknown(tfs, ctx.UnknownCollectionsSupported), nil default: contract.Failf("Unexpected value marshaled: %v", v) return nil, nil @@ -958,6 +962,63 @@ func (ctx *conversionContext) applyDefaults( return nil } +// makeTerraformUnknownElement creates an unknown value to be used as an element of a list or set using the given +// element schema to guide the shape of the value. +func makeTerraformUnknownElement(elem interface{}) interface{} { + // If we have no element schema, just return a simple unknown. + if elem == nil { + return TerraformUnknownVariableValue + } + + switch e := elem.(type) { + case shim.Schema: + // If the element uses a normal schema, defer to makeTerraformUnknown. + return makeTerraformUnknown(e, false) + case shim.Resource: + // If the element uses a resource schema, fill in unknown values for any required properties. + res := make(map[string]interface{}) + e.Schema().Range(func(k string, v shim.Schema) bool { + if v.Required() { + res[k] = makeTerraformUnknown(v, false) + } + return true + }) + return res + default: + return TerraformUnknownVariableValue + } +} + +// makeTerraformUnknown creates an unknown value with the shape indicated by the given schema. +// +// It is important that we use the TF schema (if available) to decide what shape the unknown value should have: +// e.g. TF does not play nicely with unknown lists, instead expecting a list of unknowns. +func makeTerraformUnknown(tfs shim.Schema, unknownCollectionsSupported bool) interface{} { + if unknownCollectionsSupported { + return TerraformUnknownVariableValue + } + if tfs == nil { + return TerraformUnknownVariableValue + } + + switch tfs.Type() { + case shim.TypeList, shim.TypeSet: + // TF does not accept unknown lists or sets. Instead, it accepts lists or sets of unknowns. + count := 1 + if tfs.MinItems() > 0 { + count = tfs.MinItems() + } + arr := make([]interface{}, count) + for i := range arr { + arr[i] = makeTerraformUnknownElement(tfs.Elem()) + } + return arr + default: + return TerraformUnknownVariableValue + } +} + + // metaKey is the key in a TF bridge result that is used to store a resource's meta-attributes. const metaKey = "__meta" @@ -1180,7 +1241,8 @@ func MakeTerraformOutput( func MakeTerraformConfig(ctx context.Context, p *Provider, m resource.PropertyMap, tfs shim.SchemaMap, ps map[string]*SchemaInfo) (shim.ResourceConfig, AssetTable, error) { inputs, assets, err := makeTerraformInputsWithOptions(ctx, nil, p.configValues, nil, m, tfs, ps, - makeTerraformInputsOptions{DisableDefaults: true, DisableTFDefaults: true}) + makeTerraformInputsOptions{DisableDefaults: true, DisableTFDefaults: true, + UnknownCollectionsSupported: p.tf.SupportsUnknownCollections()}) if err != nil { return nil, nil, err } @@ -1236,7 +1298,8 @@ func MakeTerraformConfigFromInputs( } type makeTerraformStateOptions struct { - defaultZeroSchemaVersion bool + defaultZeroSchemaVersion bool + unknownCollectionsSupported bool } func makeTerraformStateWithOpts( @@ -1264,7 +1327,7 @@ func makeTerraformStateWithOpts( // ints, to represent numbers. inputs, _, err := makeTerraformInputsWithOptions(ctx, nil, nil, nil, m, res.TF.Schema(), res.Schema.Fields, makeTerraformInputsOptions{ - DisableDefaults: true, DisableTFDefaults: true, + DisableDefaults: true, DisableTFDefaults: true, UnknownCollectionsSupported: opts.unknownCollectionsSupported, }) if err != nil { return nil, err @@ -1285,6 +1348,7 @@ func MakeTerraformState( type unmarshalTerraformStateOptions struct { defaultZeroSchemaVersion bool + unknownCollectionsSupported bool } func unmarshalTerraformStateWithOpts( diff --git a/pkg/tfbridge/schema_test.go b/pkg/tfbridge/schema_test.go index 1f14931d8..62cfd528b 100644 --- a/pkg/tfbridge/schema_test.go +++ b/pkg/tfbridge/schema_test.go @@ -47,14 +47,14 @@ func makeTerraformInputsNoDefaults(olds, news resource.PropertyMap, tfs shim.SchemaMap, ps map[string]*SchemaInfo, ) (map[string]interface{}, AssetTable, error) { return makeTerraformInputsWithOptions(context.Background(), nil, nil, olds, news, tfs, ps, - makeTerraformInputsOptions{DisableDefaults: true, DisableTFDefaults: true}) + makeTerraformInputsOptions{DisableDefaults: true, DisableTFDefaults: true, UnknownCollectionsSupported: true}) } func makeTerraformInputsForConfig(olds, news resource.PropertyMap, tfs shim.SchemaMap, ps map[string]*SchemaInfo, ) (map[string]interface{}, AssetTable, error) { return makeTerraformInputsWithOptions(context.Background(), nil, nil, olds, news, tfs, ps, - makeTerraformInputsOptions{}) + makeTerraformInputsOptions{UnknownCollectionsSupported: true}) } func makeTerraformInput(v resource.PropertyValue, tfs shim.Schema, ps *SchemaInfo) (interface{}, error) { @@ -689,7 +689,7 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -705,7 +705,7 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -745,7 +745,7 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -774,7 +774,7 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -790,7 +790,7 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -833,7 +833,7 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -890,7 +890,7 @@ func TestResultAttributesRoundTrip(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true}) + makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) diff --git a/pkg/tfshim/shim.go b/pkg/tfshim/shim.go index 6fb38d34c..02759233d 100644 --- a/pkg/tfshim/shim.go +++ b/pkg/tfshim/shim.go @@ -247,6 +247,10 @@ type Provider interface { // Checks if a value is representing a Set, and unpacks its elements on success. IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) + + // SupportsUnknownCollections returns false if the provider needs special handling of unknown collections. + // True for the sdkv1 provider. + SupportsUnknownCollections() bool } type TimeoutOptions struct { From bae090ba7319eae90070f78c24eb62b8d9ed0942 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:40:07 +0100 Subject: [PATCH 46/52] implement all providers --- pf/internal/schemashim/provider.go | 4 ++++ pf/proto/unsupported.go | 4 ++++ pkg/tfshim/schema/provider.go | 4 ++++ pkg/tfshim/sdk-v1/provider.go | 4 ++++ pkg/tfshim/sdk-v2/provider.go | 4 ++++ pkg/tfshim/shim.go | 2 +- pkg/tfshim/tfplugin5/provider.go | 4 ++++ pkg/tfshim/util/filter.go | 4 ++++ pkg/tfshim/util/util.go | 4 ++++ 9 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pf/internal/schemashim/provider.go b/pf/internal/schemashim/provider.go index 6ace43016..e641b17dc 100644 --- a/pf/internal/schemashim/provider.go +++ b/pf/internal/schemashim/provider.go @@ -170,3 +170,7 @@ func (p *SchemaOnlyProvider) NewResourceConfig(context.Context, map[string]inter func (p *SchemaOnlyProvider) IsSet(context.Context, interface{}) ([]interface{}, bool) { panic("schemaOnlyProvider does not implement runtime operation IsSet") } + +func (p *SchemaOnlyProvider) SupportsUnknownCollections() bool { + return true +} \ No newline at end of file diff --git a/pf/proto/unsupported.go b/pf/proto/unsupported.go index b4168e830..1ba2ee327 100644 --- a/pf/proto/unsupported.go +++ b/pf/proto/unsupported.go @@ -82,3 +82,7 @@ func (Provider) NewResourceConfig(ctx context.Context, object map[string]interfa func (Provider) IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) { panic("Unimplemented") } + +func (Provider) SupportsUnknownCollections() bool { + panic("Unimplemented") +} \ No newline at end of file diff --git a/pkg/tfshim/schema/provider.go b/pkg/tfshim/schema/provider.go index 8a303c420..e17a4e1ec 100644 --- a/pkg/tfshim/schema/provider.go +++ b/pkg/tfshim/schema/provider.go @@ -123,3 +123,7 @@ func (ProviderShim) NewResourceConfig( func (ProviderShim) IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) { panic("this provider is schema-only and does not support runtime operations") } + +func (ProviderShim) SupportsUnknownCollections() bool { + panic("this provider is schema-only and does not support runtime operations") +} \ No newline at end of file diff --git a/pkg/tfshim/sdk-v1/provider.go b/pkg/tfshim/sdk-v1/provider.go index 7f5044f81..5b64e4ec7 100644 --- a/pkg/tfshim/sdk-v1/provider.go +++ b/pkg/tfshim/sdk-v1/provider.go @@ -177,3 +177,7 @@ func (p v1Provider) IsSet(_ context.Context, v interface{}) ([]interface{}, bool } return nil, false } + +func (p v1Provider) SupportsUnknownCollections() bool { + return false +} diff --git a/pkg/tfshim/sdk-v2/provider.go b/pkg/tfshim/sdk-v2/provider.go index d10f51eea..660258568 100644 --- a/pkg/tfshim/sdk-v2/provider.go +++ b/pkg/tfshim/sdk-v2/provider.go @@ -223,3 +223,7 @@ func (p v2Provider) IsSet(_ context.Context, v interface{}) ([]interface{}, bool } return nil, false } + +func (p v2Provider) SupportsUnknownCollections() bool { + return true +} \ No newline at end of file diff --git a/pkg/tfshim/shim.go b/pkg/tfshim/shim.go index 02759233d..5b092eec4 100644 --- a/pkg/tfshim/shim.go +++ b/pkg/tfshim/shim.go @@ -249,7 +249,7 @@ type Provider interface { IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) // SupportsUnknownCollections returns false if the provider needs special handling of unknown collections. - // True for the sdkv1 provider. + // False for the sdkv1 provider. SupportsUnknownCollections() bool } diff --git a/pkg/tfshim/tfplugin5/provider.go b/pkg/tfshim/tfplugin5/provider.go index a462f64a3..ae336b549 100644 --- a/pkg/tfshim/tfplugin5/provider.go +++ b/pkg/tfshim/tfplugin5/provider.go @@ -594,3 +594,7 @@ func (p *provider) IsSet(ctx context.Context, v interface{}) ([]interface{}, boo } return result, true } + +func (p *provider) SupportsUnknownCollections() bool { + return true +} \ No newline at end of file diff --git a/pkg/tfshim/util/filter.go b/pkg/tfshim/util/filter.go index ea583ab07..c34fc91e6 100644 --- a/pkg/tfshim/util/filter.go +++ b/pkg/tfshim/util/filter.go @@ -141,6 +141,10 @@ func (p *FilteringProvider) IsSet(ctx context.Context, v interface{}) ([]interfa return p.Provider.IsSet(ctx, v) } +func (p *FilteringProvider) SupportsUnknownCollections() bool { + return p.Provider.SupportsUnknownCollections() +} + type filteringMap struct { inner shim.ResourceMap tokenFilter func(string) bool diff --git a/pkg/tfshim/util/util.go b/pkg/tfshim/util/util.go index d55dea758..33a2b4992 100644 --- a/pkg/tfshim/util/util.go +++ b/pkg/tfshim/util/util.go @@ -103,3 +103,7 @@ func (UnimplementedProvider) NewResourceConfig( func (UnimplementedProvider) IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) { panic("unimplemented") } + +func (UnimplementedProvider) SupportsUnknownCollections() bool { + panic("unimplemented") +} \ No newline at end of file From 82616ba01a7b17ede0f9fae9c5c54179ab6db16e Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:42:38 +0100 Subject: [PATCH 47/52] update tests --- pkg/tfbridge/diff_test.go | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 98bf2a96d..331f2c421 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1408,7 +1408,6 @@ func TestComputedNestedIgnore(t *testing.T) { "prop") } -//nolint:lll func TestComputedListUpdate(t *testing.T) { diffTest(t, map[string]*v2Schema.Schema{ @@ -1422,14 +1421,8 @@ func TestComputedListUpdate(t *testing.T) { "prop": []interface{}{"foo"}, "outp": "bar", }, - map[string]DiffKind{ - // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an U. - // makeDetailedDiff returns an empty diff for collections - "prop": A, - "prop[0]": D, - // Note outp is not here because of - // https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/data-consistency-errors#planned-value-for-a-non-computed-attribute - // Computed properties keep the state value after being removed from inputs. + map[string]pulumirpc.PropertyDiff_Kind{ + "prop": U, }, nil, pulumirpc.DiffResponse_DIFF_SOME) @@ -1508,10 +1501,7 @@ func TestComputedSetUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an U. - // makeDetailedDiff returns an empty diff for collections - "prop": A, - "prop[0]": D, + "prop": U, }, nil, pulumirpc.DiffResponse_DIFF_SOME) @@ -1649,10 +1639,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - // TODO[pulumi/pulumi-terraform-bridge#2141]: This should be an UR. - // makeDetailedDiff returns an empty diff for collections "prop": UR, - "prop[0]": DR, }, nil, pulumirpc.DiffResponse_DIFF_SOME) From 71cdfd07a14b223e4ed92a0d89690228976f44b2 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:43:07 +0100 Subject: [PATCH 48/52] Revert "add a v2 override" This reverts commit fc38c75b3c1f79383d61ff41d0dfb8b1908d75da. --- pkg/tfbridge/diff_test.go | 97 +++------------------------------------ 1 file changed, 7 insertions(+), 90 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 374fa9d69..d797dd886 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -105,8 +105,7 @@ func TestCustomizeDiff(t *testing.T) { for k, v := range expected { expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } - assert.Equal(t, - pulumirpc.DiffResponse_DIFF_SOME, changes) + assert.Equal(t, pulumirpc.DiffResponse_DIFF_SOME, changes) assert.Equal(t, expectedDiff, diff) }) @@ -268,7 +267,6 @@ type setupFunc func(tfs map[string]*v2Schema.Schema) ( func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, state map[string]interface{}, expected map[string]DiffKind, - expectedV2Override map[string]DiffKind, expectedDiffChanges pulumirpc.DiffResponse_DiffChanges, ignoreChanges ...string, ) { @@ -277,18 +275,12 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, inputsMap := resource.NewPropertyMapFromMap(inputs) stateMap := resource.NewPropertyMapFromMap(state) - v2Expected := expected - if expectedV2Override != nil { - v2Expected = expectedV2Override - } - setup := []struct { - name string - setup setupFunc - expected map[string]DiffKind + name string + setup setupFunc }{ - {"v1", v1SetupFromv2Schema, expected}, - {"v2", v2Setup, v2Expected}, + {"v1", v1SetupFromv2Schema}, + {"v2", v2Setup}, } for _, s := range setup { @@ -310,7 +302,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, // Convert the diff to a detailed diff and check the result. diff, changes := makeDetailedDiff(ctx, sch, info, stateMap, inputsMap, tfDiff) expectedDiff := map[string]*pulumirpc.PropertyDiff{} - for k, v := range s.expected { + for k, v := range expected { expectedDiff[k] = &pulumirpc.PropertyDiff{Kind: v} } assert.Equal(t, expectedDiffChanges, changes) @@ -332,7 +324,7 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) assert.NoError(t, err) - for k := range s.expected { + for k := range expected { ignoreChanges = append(ignoreChanges, k) } tfDiff, err := provider.Diff(ctx, "resource", tfState, config, shim.DiffOptions{ @@ -362,7 +354,6 @@ func TestCustomDiffProducesReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE) } @@ -380,7 +371,6 @@ func TestEmptyDiff(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE) } @@ -399,7 +389,6 @@ func TestSimpleAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -418,7 +407,6 @@ func TestSimpleAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -436,7 +424,6 @@ func TestSimpleDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -454,7 +441,6 @@ func TestSimpleDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -474,7 +460,6 @@ func TestSimpleUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -494,7 +479,6 @@ func TestSimpleUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -513,7 +497,6 @@ func TestNestedAdd(t *testing.T) { map[string]DiffKind{ "prop.nest": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -532,7 +515,6 @@ func TestNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -550,7 +532,6 @@ func TestNestedDelete(t *testing.T) { map[string]DiffKind{ "prop.nest": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -568,7 +549,6 @@ func TestNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -588,7 +568,6 @@ func TestNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop.nest": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -608,7 +587,6 @@ func TestNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop.nest": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -626,7 +604,6 @@ func TestNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -646,7 +623,6 @@ func TestListAdd(t *testing.T) { map[string]DiffKind{ "prop[0]": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -665,7 +641,6 @@ func TestListAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -683,7 +658,6 @@ func TestListDelete(t *testing.T) { map[string]DiffKind{ "prop[0]": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -701,7 +675,6 @@ func TestListDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -721,7 +694,6 @@ func TestListUpdate(t *testing.T) { map[string]DiffKind{ "prop[0]": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -741,7 +713,6 @@ func TestListUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -759,7 +730,6 @@ func TestListIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -780,7 +750,6 @@ func TestMaxItemsOneListAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -800,7 +769,6 @@ func TestMaxItemsOneListAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -818,7 +786,6 @@ func TestMaxItemsOneListDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -836,7 +803,6 @@ func TestMaxItemsOneListDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -856,7 +822,6 @@ func TestMaxItemsOneListUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -876,7 +841,6 @@ func TestMaxItemsOneListUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -894,7 +858,6 @@ func TestMaxItemsOneListIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -918,7 +881,6 @@ func TestSetAdd(t *testing.T) { map[string]DiffKind{ "prop[0]": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -942,7 +904,6 @@ func TestSetAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -964,7 +925,6 @@ func TestSetDelete(t *testing.T) { map[string]DiffKind{ "prop[0]": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -987,7 +947,6 @@ func TestSetDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1007,7 +966,6 @@ func TestSetUpdate(t *testing.T) { map[string]DiffKind{ "prop[0]": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1025,7 +983,6 @@ func TestSetIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1046,7 +1003,6 @@ func TestSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0]": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1071,7 +1027,6 @@ func TestMaxItemsOneSetAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1097,7 +1052,6 @@ func TestMaxItemsOneSetAddReplace(t *testing.T) { map[string]DiffKind{ "prop": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1120,7 +1074,6 @@ func TestMaxItemsOneSetDelete(t *testing.T) { map[string]DiffKind{ "prop": D, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1144,7 +1097,6 @@ func TestMaxItemsOneSetDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1164,7 +1116,6 @@ func TestMaxItemsOneSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1182,7 +1133,6 @@ func TestMaxItemsOneSetIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1203,7 +1153,6 @@ func TestMaxItemsOneSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1230,7 +1179,6 @@ func TestSetNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1257,7 +1205,6 @@ func TestSetNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1283,7 +1230,6 @@ func TestSetNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, ignore) } @@ -1305,7 +1251,6 @@ func TestComputedSimpleUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1325,7 +1270,6 @@ func TestComputedSimpleUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1345,7 +1289,6 @@ func TestComputedMapUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1365,7 +1308,6 @@ func TestComputedNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1385,7 +1327,6 @@ func TestComputedNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1403,7 +1344,6 @@ func TestComputedNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1424,7 +1364,6 @@ func TestComputedListUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1444,7 +1383,6 @@ func TestComputedListElementUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1464,7 +1402,6 @@ func TestComputedListElementUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1482,7 +1419,6 @@ func TestComputedListElementIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, "prop") } @@ -1503,7 +1439,6 @@ func TestComputedSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1523,7 +1458,6 @@ func TestNestedComputedSetUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1542,7 +1476,6 @@ func TestNestedComputedSetAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1562,7 +1495,6 @@ func TestNestedComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1582,7 +1514,6 @@ func TestNestedComputedSetIntUpdate(t *testing.T) { map[string]DiffKind{ "prop": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1602,7 +1533,6 @@ func TestNestedComputedSetIntUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1621,7 +1551,6 @@ func TestNestedComputedSetIntAdd(t *testing.T) { map[string]DiffKind{ "prop": A, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1641,7 +1570,6 @@ func TestComputedSetUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1668,7 +1596,6 @@ func TestComputedSetNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1695,7 +1622,6 @@ func TestComputedSetNestedUpdateReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": UR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1721,7 +1647,6 @@ func TestComputedSetNestedIgnore(t *testing.T) { "outp": "bar", }, map[string]DiffKind{}, - nil, pulumirpc.DiffResponse_DIFF_NONE, ignore) } @@ -1763,7 +1688,6 @@ func TestRawElementNames(t *testing.T) { map[string]DiffKind{ "prop.variables.DYNAMODB_ROUTE_TABLE_NAME": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1947,7 +1871,6 @@ func TestCollectionsWithMultipleItems(t *testing.T) { "outp": "bar", }, expected, - nil, expectedChanges, ) }) @@ -1990,7 +1913,6 @@ func TestSetNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2022,7 +1944,6 @@ func TestListNestedAddReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2054,7 +1975,6 @@ func TestListNestedUpdate(t *testing.T) { map[string]DiffKind{ "prop[0].nest": U, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2084,7 +2004,6 @@ func TestListNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2114,7 +2033,6 @@ func TestSetNestedDeleteReplace(t *testing.T) { map[string]DiffKind{ "prop[0].nest": DR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } @@ -2146,7 +2064,6 @@ func TestListNestedAddMaxItemsOne(t *testing.T) { map[string]DiffKind{ "prop.nest": AR, }, - nil, pulumirpc.DiffResponse_DIFF_SOME) } From faeb1d417c58787187c6b92eda379d1fe7e658e3 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:44:00 +0100 Subject: [PATCH 49/52] go mod tidy --- dynamic/go.sum | 4 ++-- pf/tests/go.mod | 2 +- pf/tests/go.sum | 4 ++-- pkg/tests/go.mod | 4 +--- pkg/tests/go.sum | 5 ++--- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/dynamic/go.sum b/dynamic/go.sum index 4717c503a..d6c9c02ba 100644 --- a/dynamic/go.sum +++ b/dynamic/go.sum @@ -761,8 +761,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.11 h1:mg8MQ7Cq7+9XlHIkBD+aCqQO4mwAJEISngZgVdnQUe8= -github.com/pulumi/providertest v0.0.11/go.mod h1:HsxjVsytcMIuNj19w1lT2W0QXY0oReXl1+h6eD2JXP8= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.8 h1:mav2tSitA9BPJPLLahKgepHyYsMzwaTm4cvp0dcTMYw= diff --git a/pf/tests/go.mod b/pf/tests/go.mod index a88f7fcbe..98aa4b6e6 100644 --- a/pf/tests/go.mod +++ b/pf/tests/go.mod @@ -8,7 +8,7 @@ require ( github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hashicorp/terraform-provider-tls/shim v0.0.0-00010101000000-000000000000 github.com/hexops/autogold/v2 v2.2.1 - github.com/pulumi/providertest v0.0.11 + github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-terraform-bridge/pf v0.0.0 github.com/pulumi/pulumi-terraform-bridge/v3 v3.86.0 github.com/stretchr/testify v1.9.0 diff --git a/pf/tests/go.sum b/pf/tests/go.sum index 6458542e7..78a58c10b 100644 --- a/pf/tests/go.sum +++ b/pf/tests/go.sum @@ -1927,8 +1927,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.11 h1:mg8MQ7Cq7+9XlHIkBD+aCqQO4mwAJEISngZgVdnQUe8= -github.com/pulumi/providertest v0.0.11/go.mod h1:HsxjVsytcMIuNj19w1lT2W0QXY0oReXl1+h6eD2JXP8= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-yaml v1.8.0 h1:bhmidiCMMuzsJao5FE0UR69iF3WVKPCFrRkzjotFNn4= diff --git a/pkg/tests/go.mod b/pkg/tests/go.mod index 49959e926..009070147 100644 --- a/pkg/tests/go.mod +++ b/pkg/tests/go.mod @@ -8,11 +8,10 @@ replace ( ) require ( - github.com/hashicorp/terraform-plugin-sdk v1.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hexops/autogold/v2 v2.2.1 github.com/hexops/valast v1.4.4 - github.com/pulumi/providertest v0.0.12 + github.com/pulumi/providertest v0.0.13 github.com/pulumi/pulumi-terraform-bridge/v3 v3.80.0 github.com/stretchr/testify v1.9.0 gotest.tools v2.2.0+incompatible @@ -92,7 +91,6 @@ require ( github.com/ulikunitz/xz v0.5.10 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/zclconf/go-cty-yaml v1.0.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect diff --git a/pkg/tests/go.sum b/pkg/tests/go.sum index 180bd055f..6ada63733 100644 --- a/pkg/tests/go.sum +++ b/pkg/tests/go.sum @@ -1651,7 +1651,6 @@ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+ github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8 h1:+RyjwU+Gnd/aTJBPZVDNm903eXVjjqhbaR4Ypx3xYyY= github.com/hashicorp/terraform-config-inspect v0.0.0-20191115094559-17f92b0546e8/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/terraform-json v0.4.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU= @@ -1912,8 +1911,8 @@ github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs= github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c= 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.0.12 h1:UjcFQHHs4AGJyJqxhvC2q8yVQ7Li+UyCyP95HZcK03U= -github.com/pulumi/providertest v0.0.12/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= +github.com/pulumi/providertest v0.0.13 h1:9CAaoviOTuCVHDI15h3znXa5JsKYtXLYHIIdxOCzo3Y= +github.com/pulumi/providertest v0.0.13/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= github.com/pulumi/pulumi-java/pkg v0.11.0 h1:Jw9gBvyfmfOMq/EkYDm9+zGPxsDAA8jfeMpHmtZ+1oA= github.com/pulumi/pulumi-java/pkg v0.11.0/go.mod h1:sXAk25P47AQVQL6ilAbFmRNgZykC7og/+87ihnqzFTc= github.com/pulumi/pulumi-yaml v1.8.0 h1:bhmidiCMMuzsJao5FE0UR69iF3WVKPCFrRkzjotFNn4= From 3affc4a4d89afcb6d91b35d6ed133823aec98e2c Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 13:44:58 +0100 Subject: [PATCH 50/52] lint --- pkg/tfbridge/diff_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 6a8c9db65..581cdb2d9 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -1437,7 +1437,7 @@ func TestComputedSetUpdate(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": U, + "prop": U, }, pulumirpc.DiffResponse_DIFF_SOME) } @@ -1568,7 +1568,7 @@ func TestComputedSetUpdateReplace(t *testing.T) { "outp": "bar", }, map[string]DiffKind{ - "prop": UR, + "prop": UR, }, pulumirpc.DiffResponse_DIFF_SOME) } From d029d6e66a9c5c889e83d0d96b24fcfcc6318984 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 3 Jul 2024 14:20:12 +0100 Subject: [PATCH 51/52] lint --- pf/internal/schemashim/provider.go | 2 +- pf/proto/unsupported.go | 2 +- pkg/tfbridge/diff_test.go | 6 ++++-- pkg/tfbridge/provider.go | 8 ++++---- pkg/tfbridge/schema.go | 3 +-- pkg/tfbridge/schema_test.go | 21 ++++++++++++++------- pkg/tfshim/schema/provider.go | 2 +- pkg/tfshim/sdk-v2/provider.go | 2 +- pkg/tfshim/tfplugin5/provider.go | 2 +- pkg/tfshim/util/util.go | 2 +- 10 files changed, 29 insertions(+), 21 deletions(-) diff --git a/pf/internal/schemashim/provider.go b/pf/internal/schemashim/provider.go index e641b17dc..72366c1fe 100644 --- a/pf/internal/schemashim/provider.go +++ b/pf/internal/schemashim/provider.go @@ -173,4 +173,4 @@ func (p *SchemaOnlyProvider) IsSet(context.Context, interface{}) ([]interface{}, func (p *SchemaOnlyProvider) SupportsUnknownCollections() bool { return true -} \ No newline at end of file +} diff --git a/pf/proto/unsupported.go b/pf/proto/unsupported.go index 1ba2ee327..2e3692b7d 100644 --- a/pf/proto/unsupported.go +++ b/pf/proto/unsupported.go @@ -85,4 +85,4 @@ func (Provider) IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) func (Provider) SupportsUnknownCollections() bool { panic("Unimplemented") -} \ No newline at end of file +} diff --git a/pkg/tfbridge/diff_test.go b/pkg/tfbridge/diff_test.go index 581cdb2d9..18b487a0a 100644 --- a/pkg/tfbridge/diff_test.go +++ b/pkg/tfbridge/diff_test.go @@ -289,7 +289,8 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, sch, r, provider, info := s.setup(tfs) tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) @@ -318,7 +319,8 @@ func diffTest(t *testing.T, tfs map[string]*v2Schema.Schema, inputs, t.Run("withIgnoreAllExpected", func(t *testing.T) { sch, r, provider, info := s.setup(tfs) tfState, err := makeTerraformStateWithOpts(ctx, r, "id", stateMap, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: provider.SupportsUnknownCollections()}) assert.NoError(t, err) config, _, err := MakeTerraformConfig(ctx, &Provider{tf: provider}, inputsMap, sch, info) diff --git a/pkg/tfbridge/provider.go b/pkg/tfbridge/provider.go index a56804479..0279ff55d 100644 --- a/pkg/tfbridge/provider.go +++ b/pkg/tfbridge/provider.go @@ -1076,7 +1076,7 @@ func (p *Provider) Diff(ctx context.Context, req *pulumirpc.DiffRequest) (*pulum state, err := makeTerraformStateWithOpts(ctx, res, req.GetId(), olds, makeTerraformStateOptions{ - defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), }, ) @@ -1353,7 +1353,7 @@ func (p *Provider) Read(ctx context.Context, req *pulumirpc.ReadRequest) (*pulum } state, err := unmarshalTerraformStateWithOpts(ctx, res, id, req.GetProperties(), fmt.Sprintf("%s.state", label), unmarshalTerraformStateOptions{ - defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), }) if err != nil { @@ -1471,7 +1471,7 @@ func (p *Provider) Update(ctx context.Context, req *pulumirpc.UpdateRequest) (*p state, err := makeTerraformStateWithOpts(ctx, res, req.GetId(), olds, makeTerraformStateOptions{ - defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), }) if err != nil { @@ -1604,7 +1604,7 @@ func (p *Provider) Delete(ctx context.Context, req *pulumirpc.DeleteRequest) (*p // Fetch the resource attributes since many providers need more than just the ID to perform the delete. state, err := unmarshalTerraformStateWithOpts(ctx, res, req.GetId(), req.GetProperties(), label, unmarshalTerraformStateOptions{ - defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, + defaultZeroSchemaVersion: opts.defaultZeroSchemaVersion, unknownCollectionsSupported: p.tf.SupportsUnknownCollections(), }) if err != nil { diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index af0417b29..997df2666 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -1017,7 +1017,6 @@ func makeTerraformUnknown(tfs shim.Schema, unknownCollectionsSupported bool) int return TerraformUnknownVariableValue } } - // metaKey is the key in a TF bridge result that is used to store a resource's meta-attributes. const metaKey = "__meta" @@ -1347,7 +1346,7 @@ func MakeTerraformState( } type unmarshalTerraformStateOptions struct { - defaultZeroSchemaVersion bool + defaultZeroSchemaVersion bool unknownCollectionsSupported bool } diff --git a/pkg/tfbridge/schema_test.go b/pkg/tfbridge/schema_test.go index 62cfd528b..329d385f7 100644 --- a/pkg/tfbridge/schema_test.go +++ b/pkg/tfbridge/schema_test.go @@ -689,7 +689,8 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -705,7 +706,8 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -745,7 +747,8 @@ func TestMetaProperties(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -774,7 +777,8 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -790,7 +794,8 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -833,7 +838,8 @@ func TestInjectingCustomTimeouts(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) @@ -890,7 +896,8 @@ func TestResultAttributesRoundTrip(t *testing.T) { state, err = makeTerraformStateWithOpts( ctx, Resource{TF: res, Schema: &ResourceInfo{}}, state.ID(), props, - makeTerraformStateOptions{defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) + makeTerraformStateOptions{ + defaultZeroSchemaVersion: true, unknownCollectionsSupported: prov.SupportsUnknownCollections()}) assert.NoError(t, err) assert.NotNil(t, state) diff --git a/pkg/tfshim/schema/provider.go b/pkg/tfshim/schema/provider.go index e17a4e1ec..db53d0921 100644 --- a/pkg/tfshim/schema/provider.go +++ b/pkg/tfshim/schema/provider.go @@ -126,4 +126,4 @@ func (ProviderShim) IsSet(ctx context.Context, v interface{}) ([]interface{}, bo func (ProviderShim) SupportsUnknownCollections() bool { panic("this provider is schema-only and does not support runtime operations") -} \ No newline at end of file +} diff --git a/pkg/tfshim/sdk-v2/provider.go b/pkg/tfshim/sdk-v2/provider.go index 660258568..7ab87eb37 100644 --- a/pkg/tfshim/sdk-v2/provider.go +++ b/pkg/tfshim/sdk-v2/provider.go @@ -226,4 +226,4 @@ func (p v2Provider) IsSet(_ context.Context, v interface{}) ([]interface{}, bool func (p v2Provider) SupportsUnknownCollections() bool { return true -} \ No newline at end of file +} diff --git a/pkg/tfshim/tfplugin5/provider.go b/pkg/tfshim/tfplugin5/provider.go index ae336b549..0255dd6cb 100644 --- a/pkg/tfshim/tfplugin5/provider.go +++ b/pkg/tfshim/tfplugin5/provider.go @@ -597,4 +597,4 @@ func (p *provider) IsSet(ctx context.Context, v interface{}) ([]interface{}, boo func (p *provider) SupportsUnknownCollections() bool { return true -} \ No newline at end of file +} diff --git a/pkg/tfshim/util/util.go b/pkg/tfshim/util/util.go index 33a2b4992..c91fafb2b 100644 --- a/pkg/tfshim/util/util.go +++ b/pkg/tfshim/util/util.go @@ -106,4 +106,4 @@ func (UnimplementedProvider) IsSet(ctx context.Context, v interface{}) ([]interf func (UnimplementedProvider) SupportsUnknownCollections() bool { panic("unimplemented") -} \ No newline at end of file +} From c910839e36a97d0297b9b69f587af9777c72d70d Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 17 Jul 2024 13:42:44 +0300 Subject: [PATCH 52/52] address review comments --- pkg/tests/internal/pulcheck/pulcheck.go | 24 ++++++++++++++++-------- pkg/tfbridge/diff.go | 1 - pkg/tfbridge/schema.go | 8 ++++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/pkg/tests/internal/pulcheck/pulcheck.go b/pkg/tests/internal/pulcheck/pulcheck.go index 4c42ef79d..e0e2e61df 100644 --- a/pkg/tests/internal/pulcheck/pulcheck.go +++ b/pkg/tests/internal/pulcheck/pulcheck.go @@ -29,16 +29,24 @@ import ( "gotest.tools/assert" ) -func resNeedsUpdate(res *schema.Resource) bool { +func propNeedsUpdate(prop *schema.Schema) bool { + if prop.Computed && !prop.Optional { + return false + } + if prop.ForceNew { + return false + } + return true +} + +func resourceNeedsUpdate(res *schema.Resource) bool { + // If any of the properties need an update, then the resource needs an update. for _, s := range res.Schema { - if s.Computed && !s.Optional { - continue - } - if s.ForceNew { - continue + if propNeedsUpdate(s) { + return true } } - return res.UpdateContext == nil + return false } // This is an experimental API. @@ -66,7 +74,7 @@ func EnsureProviderValid(t T, tfp *schema.Provider) { } } - if resNeedsUpdate(r) { + if resourceNeedsUpdate(r) && r.UpdateContext == nil { r.UpdateContext = func( ctx context.Context, rd *schema.ResourceData, i interface{}, ) diag.Diagnostics { diff --git a/pkg/tfbridge/diff.go b/pkg/tfbridge/diff.go index b77ad91d7..5ee359e12 100644 --- a/pkg/tfbridge/diff.go +++ b/pkg/tfbridge/diff.go @@ -380,7 +380,6 @@ func makeDetailedDiffExtra( if len(diff) > 0 || *forceDiff { changes = pulumirpc.DiffResponse_DIFF_SOME } - return detailedDiffExtra{ changes: changes, diffs: diff, diff --git a/pkg/tfbridge/schema.go b/pkg/tfbridge/schema.go index 997df2666..e42b79e5c 100644 --- a/pkg/tfbridge/schema.go +++ b/pkg/tfbridge/schema.go @@ -335,7 +335,7 @@ func makeTerraformInputsWithOptions( return inputs, cctx.Assets, err } -// Unused internally, use makeTerraformInputsWithOptions instead. +// Deprecated: missing some important functionality, use makeTerraformInputsWithOptions instead. func MakeTerraformInputs( ctx context.Context, instance *PulumiResource, config resource.PropertyMap, olds, news resource.PropertyMap, tfs shim.SchemaMap, ps map[string]*SchemaInfo, @@ -1249,7 +1249,7 @@ func MakeTerraformConfig(ctx context.Context, p *Provider, m resource.PropertyMa } // UnmarshalTerraformConfig creates a Terraform config map from a Pulumi RPC property map. -// Unused internally. +// Deprecated: use MakeTerraformConfig instead. func UnmarshalTerraformConfig(ctx context.Context, p *Provider, m *pbstruct.Struct, tfs shim.SchemaMap, ps map[string]*SchemaInfo, label string) (shim.ResourceConfig, AssetTable, error) { @@ -1338,7 +1338,7 @@ func makeTerraformStateWithOpts( // MakeTerraformState converts a Pulumi property bag into its Terraform equivalent. This requires // flattening everything and serializing individual properties as strings. This is a little awkward, but it's how // Terraform represents resource properties (schemas are simply sugar on top). -// Prefer makeTerraformStateWithOpts for internal use. +// Deprecated: Use makeTerraformStateWithOpts instead. func MakeTerraformState( ctx context.Context, res Resource, id string, m resource.PropertyMap, ) (shim.InstanceState, error) { @@ -1373,7 +1373,7 @@ func unmarshalTerraformStateWithOpts( } // UnmarshalTerraformState unmarshals a Terraform instance state from an RPC property map. -// Prefer unmarshalTerraformStateWithOpts for internal use. +// Deprecated: Use unmarshalTerraformStateWithOpts instead. func UnmarshalTerraformState( ctx context.Context, r Resource, id string, m *pbstruct.Struct, l string, ) (shim.InstanceState, error) {