diff --git a/builtin/providers/test/resource.go b/builtin/providers/test/resource.go index 9df02bc15a..549f7271c5 100644 --- a/builtin/providers/test/resource.go +++ b/builtin/providers/test/resource.go @@ -21,6 +21,10 @@ func testResource() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "optional_bool": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + }, "optional_force_new": &schema.Schema{ Type: schema.TypeString, Optional: true, diff --git a/builtin/providers/test/resource_test.go b/builtin/providers/test/resource_test.go index 6b12227f98..59b4c47857 100644 --- a/builtin/providers/test/resource_test.go +++ b/builtin/providers/test/resource_test.go @@ -124,6 +124,47 @@ resource "test_resource" "foo" { }) } +// Covers specific scenario in #6005, handled by normalizing boolean strings in +// helper/schema +func TestResource_ignoreChangesForceNewBoolean(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" + optional_force_new = "one" + optional_bool = true + lifecycle { + ignore_changes = ["optional_force_new"] + } +} + `), + Check: func(s *terraform.State) error { + return nil + }, + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource" "foo" { + required = "yep" + optional_force_new = "two" + optional_bool = true + lifecycle { + ignore_changes = ["optional_force_new"] + } +} + `), + Check: func(s *terraform.State) error { + return nil + }, + }, + }, + }) +} + func TestResource_ignoreChangesMap(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, diff --git a/helper/schema/schema.go b/helper/schema/schema.go index cfe3c6a33d..43b5cc21ac 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -243,6 +243,20 @@ func (s *Schema) finalizeDiff( return d } + if s.Type == TypeBool { + normalizeBoolString := func(s string) string { + switch s { + case "0": + return "false" + case "1": + return "true" + } + return s + } + d.Old = normalizeBoolString(d.Old) + d.New = normalizeBoolString(d.New) + } + if d.NewRemoved { return d } diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 94c9c57ffa..dba10ee34e 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -491,7 +491,7 @@ func TestSchemaMap_Diff(t *testing.T) { Attributes: map[string]*terraform.ResourceAttrDiff{ "port": &terraform.ResourceAttrDiff{ Old: "", - New: "0", + New: "false", RequiresNew: true, }, }, @@ -2344,6 +2344,56 @@ func TestSchemaMap_Diff(t *testing.T) { Err: false, }, + + "Bools can be set with 0/1 in config, still get true/false": { + Schema: map[string]*Schema{ + "one": &Schema{ + Type: TypeBool, + Optional: true, + }, + "two": &Schema{ + Type: TypeBool, + Optional: true, + }, + "three": &Schema{ + Type: TypeBool, + Optional: true, + }, + }, + + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "one": "false", + "two": "true", + "three": "true", + }, + }, + + Config: map[string]interface{}{ + "one": "1", + "two": "0", + }, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "one": &terraform.ResourceAttrDiff{ + Old: "false", + New: "true", + }, + "two": &terraform.ResourceAttrDiff{ + Old: "true", + New: "false", + }, + "three": &terraform.ResourceAttrDiff{ + Old: "true", + New: "false", + NewRemoved: true, + }, + }, + }, + + Err: false, + }, } for tn, tc := range cases {