From ebb129f05162813dd946f4e9ef0aaf2ed350a78d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 3 Feb 2017 20:58:03 +0100 Subject: [PATCH] terraform: data source on refresh should just delete from state This was caught by an acceptance test. We've now added a unit test. When refreshing, an orphan (no config) data source should just be deleted. --- terraform/context_refresh_test.go | 32 ++++++++++++++++++++++++++++++ terraform/node_data_destroy.go | 22 ++++++++++++++++++++ terraform/node_resource_refresh.go | 14 +++++++++++-- 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 terraform/node_data_destroy.go diff --git a/terraform/context_refresh_test.go b/terraform/context_refresh_test.go index b3f0039a2..7c00cf4f4 100644 --- a/terraform/context_refresh_test.go +++ b/terraform/context_refresh_test.go @@ -571,6 +571,38 @@ func TestContext2Refresh_stateBasic(t *testing.T) { } } +func TestContext2Refresh_dataOrphan(t *testing.T) { + p := testProvider("null") + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "data.null_data_source.bar": &ResourceState{ + Type: "foo", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + } + ctx := testContext2(t, &ContextOpts{ + Providers: map[string]ResourceProviderFactory{ + "null": testProviderFuncFixed(p), + }, + State: state, + }) + + s, err := ctx.Refresh() + if err != nil { + t.Fatalf("err: %s", err) + } + + checkStateString(t, s, ``) +} + func TestContext2Refresh_dataState(t *testing.T) { p := testProvider("null") m := testModule(t, "refresh-data-resource-basic") diff --git a/terraform/node_data_destroy.go b/terraform/node_data_destroy.go new file mode 100644 index 000000000..e32cea882 --- /dev/null +++ b/terraform/node_data_destroy.go @@ -0,0 +1,22 @@ +package terraform + +// NodeDestroyableDataResource represents a resource that is "plannable": +// it is ready to be planned in order to create a diff. +type NodeDestroyableDataResource struct { + *NodeAbstractResource +} + +// GraphNodeEvalable +func (n *NodeDestroyableDataResource) EvalTree() EvalNode { + addr := n.NodeAbstractResource.Addr + + // stateId is the ID to put into the state + stateId := addr.stateId() + + // Just destroy it. + var state *InstanceState + return &EvalWriteState{ + Name: stateId, + State: &state, // state is nil here + } +} diff --git a/terraform/node_resource_refresh.go b/terraform/node_resource_refresh.go index 3adfffdf9..3a44926ce 100644 --- a/terraform/node_resource_refresh.go +++ b/terraform/node_resource_refresh.go @@ -23,9 +23,19 @@ func (n *NodeRefreshableResource) EvalTree() EvalNode { switch mode := n.Addr.Mode; mode { case config.ManagedResourceMode: return n.evalTreeManagedResource() + case config.DataResourceMode: - dn := &NodeRefreshableDataResourceInstance{ - NodeAbstractResource: n.NodeAbstractResource, + // Get the data source node. If we don't have a configuration + // then it is an orphan so we destroy it (remove it from the state). + var dn GraphNodeEvalable + if n.Config != nil { + dn = &NodeRefreshableDataResourceInstance{ + NodeAbstractResource: n.NodeAbstractResource, + } + } else { + dn = &NodeDestroyableDataResource{ + NodeAbstractResource: n.NodeAbstractResource, + } } return dn.EvalTree()