From 8b9fa6d05fd45273c2f145988097d59c13417ccb Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 28 Mar 2019 16:21:58 -0400 Subject: [PATCH] add test provider coverage around unknown vals --- builtin/providers/test/resource.go | 14 ++ builtin/providers/test/resource_list.go | 20 +++ builtin/providers/test/resource_list_test.go | 129 +++++++++++++++++++ builtin/providers/test/resource_test.go | 126 ++++++++++++++++++ 4 files changed, 289 insertions(+) diff --git a/builtin/providers/test/resource.go b/builtin/providers/test/resource.go index c8556a2b7..32f1049c7 100644 --- a/builtin/providers/test/resource.go +++ b/builtin/providers/test/resource.go @@ -18,6 +18,13 @@ func testResource() *schema.Resource { State: schema.ImportStatePassthrough, }, + CustomizeDiff: func(d *schema.ResourceDiff, _ interface{}) error { + if d.HasChange("required") { + d.SetNewComputed("planned_computed") + } + return nil + }, + Schema: map[string]*schema.Schema{ "required": { Type: schema.TypeString, @@ -129,6 +136,11 @@ func testResource() *schema.Resource { Optional: true, Description: "return and error during apply", }, + "planned_computed": { + Type: schema.TypeString, + Computed: true, + Description: "copied the required field during apply, and plans computed when changed", + }, }, } } @@ -164,6 +176,8 @@ func testResourceRead(d *schema.ResourceData, meta interface{}) error { d.Set("computed_list", []string{"listval1", "listval2"}) d.Set("computed_set", []string{"setval1", "setval2"}) + d.Set("planned_computed", d.Get("required")) + // if there is no "set" value, erroneously set it to an empty set. This // might change a null value to an empty set, but we should be able to // ignore that. diff --git a/builtin/providers/test/resource_list.go b/builtin/providers/test/resource_list.go index a3d01b79e..36db61993 100644 --- a/builtin/providers/test/resource_list.go +++ b/builtin/providers/test/resource_list.go @@ -11,6 +11,13 @@ func testResourceList() *schema.Resource { Update: testResourceListUpdate, Delete: testResourceListDelete, + CustomizeDiff: func(d *schema.ResourceDiff, _ interface{}) error { + if d.HasChange("dependent_list") { + d.SetNewComputed("computed_list") + } + return nil + }, + Schema: map[string]*schema.Schema{ "list_block": { Type: schema.TypeList, @@ -55,6 +62,19 @@ func testResourceList() *schema.Resource { }, }, }, + "sublist_block_optional": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "list": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, }, }, }, diff --git a/builtin/providers/test/resource_list_test.go b/builtin/providers/test/resource_list_test.go index 87d1dde12..aeb56e989 100644 --- a/builtin/providers/test/resource_list_test.go +++ b/builtin/providers/test/resource_list_test.go @@ -318,3 +318,132 @@ resource "test_resource_list" "foo" { }, }) } + +func TestResourceList_planUnknownInterpolation(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + list_block { + string = "x" + } +} +resource "test_resource_list" "bar" { + list_block { + sublist = [ + test_resource_list.foo.list_block[0].string, + ] + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.bar", "list_block.0.sublist.0", "x", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + list_block { + string = "x" + } + dependent_list { + val = "y" + } +} +resource "test_resource_list" "bar" { + list_block { + sublist = [ + test_resource_list.foo.computed_list[0], + ] + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.bar", "list_block.0.sublist.0", "y", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + list_block { + string = "x" + } + dependent_list { + val = "z" + } +} +resource "test_resource_list" "bar" { + list_block { + sublist = [ + test_resource_list.foo.computed_list[0], + ] + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.bar", "list_block.0.sublist.0", "z", + ), + ), + }, + }, + }) +} + +func TestResourceList_planUnknownInterpolationList(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + dependent_list { + val = "y" + } +} +resource "test_resource_list" "bar" { + list_block { + sublist_block_optional { + list = test_resource_list.foo.computed_list + } + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.bar", "list_block.0.sublist_block_optional.0.list.0", "y", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + dependent_list { + val = "z" + } +} +resource "test_resource_list" "bar" { + list_block { + sublist_block_optional { + list = test_resource_list.foo.computed_list + } + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.bar", "list_block.0.sublist_block_optional.0.list.0", "z", + ), + ), + }, + }, + }) +} diff --git a/builtin/providers/test/resource_test.go b/builtin/providers/test/resource_test.go index 350a76841..3c64dc594 100644 --- a/builtin/providers/test/resource_test.go +++ b/builtin/providers/test/resource_test.go @@ -790,3 +790,129 @@ resource "test_resource" "foo" { }, }) } + +func TestResource_optionalComputedMap(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource" "foo" { + required = "yep" + required_map = { + key = "value" + } + optional_computed_map = { + foo = "bar" + baz = "" + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource.foo", "optional_computed_map.foo", "bar", + ), + resource.TestCheckResourceAttr( + "test_resource.foo", "optional_computed_map.baz", "", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource" "foo" { + required = "yep" + required_map = { + key = "value" + } + optional_computed_map = {} +} + `), + // removing the map from the config should still leave an empty computed map + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource.foo", "optional_computed_map.%", "0", + ), + ), + }, + }, + }) +} + +func TestResource_plannedComputed(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource" "foo" { + required = "ok" + required_map = { + key = "value" + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource.foo", "planned_computed", "ok", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource" "foo" { + required = "changed" + required_map = { + key = "value" + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource.foo", "planned_computed", "changed", + ), + ), + }, + }, + }) +} + +func TestDiffApply_map(t *testing.T) { + resSchema := map[string]*schema.Schema{ + "map": { + Type: schema.TypeMap, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + } + + priorAttrs := map[string]string{ + "id": "ok", + "map.%": "2", + "map.foo": "bar", + "map.bar": "", + } + + diff := &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "map.foo": &terraform.ResourceAttrDiff{Old: "bar", New: "", NewRemoved: true}, + "map.bar": &terraform.ResourceAttrDiff{Old: "", New: "", NewRemoved: true}, + }, + } + + newAttrs, err := diff.Apply(priorAttrs, (&schema.Resource{Schema: resSchema}).CoreConfigSchema()) + if err != nil { + t.Fatal(err) + } + + expect := map[string]string{ + "id": "ok", + "map.%": "0", + } + + if !reflect.DeepEqual(newAttrs, expect) { + t.Fatalf("expected:%#v got:%#v", expect, newAttrs) + } +}