diff --git a/config/config.go b/config/config.go index 59db96de1..67e0a2e7e 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ package config import ( "fmt" + "strconv" "strings" "github.com/hashicorp/terraform/flatmap" @@ -56,7 +57,7 @@ type ProviderConfig struct { type Resource struct { Name string Type string - Count *RawConfig + RawCount *RawConfig RawConfig *RawConfig Provisioners []*Provisioner DependsOn []string @@ -120,6 +121,16 @@ func (r *Module) Id() string { return fmt.Sprintf("%s", r.Name) } +// Count returns the count of this resource. +func (r *Resource) Count() (int, error) { + v, err := strconv.ParseInt(r.RawCount.Value().(string), 0, 0) + if err != nil { + return 0, err + } + + return int(v), nil +} + // A unique identifier for this resource. func (r *Resource) Id() string { return fmt.Sprintf("%s.%s", r.Type, r.Name) @@ -308,7 +319,7 @@ func (c *Config) InterpolatedVariables() map[string][]InterpolatedVariable { for _, rc := range c.Resources { source := fmt.Sprintf("resource '%s'", rc.Id()) - for _, v := range rc.Count.Variables { + for _, v := range rc.RawCount.Variables { result[source] = append(result[source], v) } for _, v := range rc.RawConfig.Variables { @@ -384,8 +395,8 @@ func (r *Resource) mergerMerge(m merger) merger { result.Type = r2.Type result.RawConfig = result.RawConfig.merge(r2.RawConfig) - if r2.Count.Value() != "1" { - result.Count = r2.Count + if r2.RawCount.Value() != "1" { + result.RawCount = r2.RawCount } if len(r2.Provisioners) > 0 { diff --git a/config/config_string.go b/config/config_string.go index 983bdf8d4..2db0cbe49 100644 --- a/config/config_string.go +++ b/config/config_string.go @@ -193,7 +193,7 @@ func resourcesStr(rs []*Resource) string { "%s[%s] (x%s)\n", r.Type, r.Name, - r.Count.Value()) + r.RawCount.Value()) ks := make([]string, 0, len(r.RawConfig.Raw)) for k, _ := range r.RawConfig.Raw { diff --git a/config/config_test.go b/config/config_test.go index 8b9a65f8d..a31df6b5a 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -9,6 +9,36 @@ import ( // This is the directory where our test fixtures are. const fixtureDir = "./test-fixtures" +func TestConfigCount(t *testing.T) { + c := testConfig(t, "count-int") + actual, err := c.Resources[0].Count() + if err != nil { + t.Fatalf("err: %s", err) + } + if actual != 5 { + t.Fatalf("bad: %#v", actual) + } +} + +func TestConfigCount_string(t *testing.T) { + c := testConfig(t, "count-string") + actual, err := c.Resources[0].Count() + if err != nil { + t.Fatalf("err: %s", err) + } + if actual != 5 { + t.Fatalf("bad: %#v", actual) + } +} + +func TestConfigCount_var(t *testing.T) { + c := testConfig(t, "count-var") + _, err := c.Resources[0].Count() + if err == nil { + t.Fatalf("should error") + } +} + func TestConfigValidate(t *testing.T) { c := testConfig(t, "validate-good") if err := c.Validate(); err != nil { diff --git a/config/loader_hcl.go b/config/loader_hcl.go index 78c7064d5..10e178c1e 100644 --- a/config/loader_hcl.go +++ b/config/loader_hcl.go @@ -482,7 +482,7 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) { result = append(result, &Resource{ Name: k, Type: t.Key, - Count: countConfig, + RawCount: countConfig, RawConfig: rawConfig, Provisioners: provisioners, DependsOn: dependsOn, diff --git a/config/test-fixtures/count-int/main.tf b/config/test-fixtures/count-int/main.tf new file mode 100644 index 000000000..213bb4dfa --- /dev/null +++ b/config/test-fixtures/count-int/main.tf @@ -0,0 +1,3 @@ +resource "foo" "bar" { + count = 5 +} diff --git a/config/test-fixtures/count-string/main.tf b/config/test-fixtures/count-string/main.tf new file mode 100644 index 000000000..6ad7191f7 --- /dev/null +++ b/config/test-fixtures/count-string/main.tf @@ -0,0 +1,3 @@ +resource "foo" "bar" { + count = "5" +} diff --git a/config/test-fixtures/count-var/main.tf b/config/test-fixtures/count-var/main.tf new file mode 100644 index 000000000..789262030 --- /dev/null +++ b/config/test-fixtures/count-var/main.tf @@ -0,0 +1,3 @@ +resource "foo" "bar" { + count = "${var.foo}" +} diff --git a/terraform/state.go b/terraform/state.go index ef537ab54..1a6980fc4 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -198,9 +198,10 @@ func (m *ModuleState) Orphans(c *config.Config) []string { for _, r := range c.Resources { delete(keys, r.Id()) - // Mark all the counts as not orphans. - for i := 0; i < r.Count; i++ { - delete(keys, fmt.Sprintf("%s.%d", r.Id(), i)) + for k, _ := range keys { + if strings.HasPrefix(k, r.Id()+".") { + delete(keys, k) + } } } diff --git a/terraform/state_v1.go b/terraform/state_v1.go index 14436f205..85ba939a7 100644 --- a/terraform/state_v1.go +++ b/terraform/state_v1.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "sort" + "strings" "sync" "github.com/hashicorp/terraform/config" @@ -80,9 +81,10 @@ func (s *StateV1) Orphans(c *config.Config) []string { for _, r := range c.Resources { delete(keys, r.Id()) - // Mark all the counts as not orphans. - for i := 0; i < r.Count; i++ { - delete(keys, fmt.Sprintf("%s.%d", r.Id(), i)) + for k, _ := range keys { + if strings.HasPrefix(k, r.Id()+".") { + delete(keys, k) + } } }