From d0b7a4a072d4829bfcc3eae4d0a1dd2b03761c2d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 21 Jan 2017 10:24:03 -0800 Subject: [PATCH] terraform: StateFilter handles cases where ResourceState has no type This was possible with test fixtures but it is also conceiably possible with older states or corrupted states. We can also extract the type from the key so we do that now so that StateFilter is more robust. --- terraform/state_filter.go | 23 ++++++++++++------- terraform/state_filter_test.go | 9 ++++++++ .../single-minimal-resource.tfstate | 18 +++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 terraform/test-fixtures/state-filter/single-minimal-resource.tfstate diff --git a/terraform/state_filter.go b/terraform/state_filter.go index 1b41a3b7e..9d3a5fb32 100644 --- a/terraform/state_filter.go +++ b/terraform/state_filter.go @@ -85,15 +85,22 @@ func (f *StateFilter) filterSingle(a *ResourceAddress) []*StateFilterResult { // the modules to find relevant resources. for _, m := range modules { for n, r := range m.Resources { - if f.relevant(a, r) { - // The name in the state contains valuable information. Parse. - key, err := ParseResourceStateKey(n) - if err != nil { - // If we get an error parsing, then just ignore it - // out of the state. - continue - } + // The name in the state contains valuable information. Parse. + key, err := ParseResourceStateKey(n) + if err != nil { + // If we get an error parsing, then just ignore it + // out of the state. + continue + } + // Older states and test fixtures often don't contain the + // type directly on the ResourceState. We add this so StateFilter + // is a bit more robust. + if r.Type == "" { + r.Type = key.Type + } + + if f.relevant(a, r) { if a.Name != "" && a.Name != key.Name { // Name doesn't match continue diff --git a/terraform/state_filter_test.go b/terraform/state_filter_test.go index a0dcba0fe..6fbcfa716 100644 --- a/terraform/state_filter_test.go +++ b/terraform/state_filter_test.go @@ -38,6 +38,15 @@ func TestStateFilterFilter(t *testing.T) { }, }, + "single resource from minimal state": { + "single-minimal-resource.tfstate", + []string{"aws_instance.web"}, + []string{ + "*terraform.ResourceState: aws_instance.web", + "*terraform.InstanceState: aws_instance.web", + }, + }, + "single resource with similar names": { "small_test_instance.tfstate", []string{"test_instance.foo"}, diff --git a/terraform/test-fixtures/state-filter/single-minimal-resource.tfstate b/terraform/test-fixtures/state-filter/single-minimal-resource.tfstate new file mode 100644 index 000000000..b6963ee31 --- /dev/null +++ b/terraform/test-fixtures/state-filter/single-minimal-resource.tfstate @@ -0,0 +1,18 @@ +{ + "version": 1, + "serial": 12, + "modules": [ + { + "path": [ + "root" + ], + "resources": { + "aws_instance.web": { + "primary": { + "id": "onprem" + } + } + } + } + ] +}