diff --git a/config/config.go b/config/config.go index 45fb3028c..b7a1fef6b 100644 --- a/config/config.go +++ b/config/config.go @@ -54,12 +54,13 @@ type ProviderConfig struct { // A Terraform resource is something that represents some component that // can be created and managed, and has some properties associated with it. type Resource struct { - Name string - Type string - Count int - RawConfig *RawConfig - Provisioners []*Provisioner - DependsOn []string + Name string + Type string + Count int + RawConfig *RawConfig + Provisioners []*Provisioner + DependsOn []string + CreateBeforeDestroy bool } // Provisioner is a configured provisioner step on a resource. diff --git a/config/loader_hcl.go b/config/loader_hcl.go index babc34ca6..4bf34c376 100644 --- a/config/loader_hcl.go +++ b/config/loader_hcl.go @@ -394,6 +394,7 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) { delete(config, "count") delete(config, "depends_on") delete(config, "provisioner") + delete(config, "create_before_destroy") rawConfig, err := NewRawConfig(config) if err != nil { @@ -457,13 +458,28 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) { } } + // Check if the resource should be re-created before + // destroying the existing instance + var createBeforeDestroy bool + if o := obj.Get("create_before_destroy", false); o != nil { + err = hcl.DecodeObject(&createBeforeDestroy, o) + if err != nil { + return nil, fmt.Errorf( + "Error parsing create_before_destroy for %s[%s]: %s", + t.Key, + k, + err) + } + } + result = append(result, &Resource{ - Name: k, - Type: t.Key, - Count: count, - RawConfig: rawConfig, - Provisioners: provisioners, - DependsOn: dependsOn, + Name: k, + Type: t.Key, + Count: count, + RawConfig: rawConfig, + Provisioners: provisioners, + DependsOn: dependsOn, + CreateBeforeDestroy: createBeforeDestroy, }) } } diff --git a/config/loader_test.go b/config/loader_test.go index 70dba0a16..d8ab2b6c2 100644 --- a/config/loader_test.go +++ b/config/loader_test.go @@ -346,6 +346,43 @@ func TestLoad_connections(t *testing.T) { } } +func TestLoad_createBeforeDestroy(t *testing.T) { + c, err := Load(filepath.Join(fixtureDir, "create-before-destroy.tf")) + if err != nil { + t.Fatalf("err: %s", err) + } + + if c == nil { + t.Fatal("config should not be nil") + } + + actual := resourcesStr(c.Resources) + if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) { + t.Fatalf("bad:\n%s", actual) + } + + // Check for the flag value + r := c.Resources[0] + if r.Name != "web" && r.Type != "aws_instance" { + t.Fatalf("Bad: %#v", r) + } + + // Should enable create before destroy + if !r.CreateBeforeDestroy { + t.Fatalf("Bad: %#v", r) + } + + r = c.Resources[1] + if r.Name != "bar" && r.Type != "aws_instance" { + t.Fatalf("Bad: %#v", r) + } + + // Should not enable create before destroy + if r.CreateBeforeDestroy { + t.Fatalf("Bad: %#v", r) + } +} + const basicOutputsStr = ` web_ip vars @@ -523,3 +560,10 @@ foo (required) <> <> ` + +const createBeforeDestroyResourcesStr = ` +aws_instance[bar] (x1) + ami +aws_instance[web] (x1) + ami +` diff --git a/config/test-fixtures/create-before-destroy.tf b/config/test-fixtures/create-before-destroy.tf new file mode 100644 index 000000000..7f348aeac --- /dev/null +++ b/config/test-fixtures/create-before-destroy.tf @@ -0,0 +1,10 @@ + +resource "aws_instance" "web" { + ami = "foo" + create_before_destroy = true +} + +resource "aws_instance" "bar" { + ami = "foo" + create_before_destroy = false +}