From aea6b0a7e19414713a47ed12542a26318a7453aa Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 12 Feb 2015 19:48:57 -0800 Subject: [PATCH] terraform: compare bad diffs for apply --- terraform/context_test.go | 1 - terraform/eval_diff.go | 45 ++++++++++++++++++++++++++++++--- terraform/transform_resource.go | 26 ++++++++++++++++--- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/terraform/context_test.go b/terraform/context_test.go index 2203a64f6c..b0b350c526 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -2817,7 +2817,6 @@ func TestContext2Apply_minimal(t *testing.T) { } } -/* func TestContext2Apply_badDiff(t *testing.T) { m := testModule(t, "apply-good") p := testProvider("aws") diff --git a/terraform/eval_diff.go b/terraform/eval_diff.go index 7e95b3ba4d..3ec842567d 100644 --- a/terraform/eval_diff.go +++ b/terraform/eval_diff.go @@ -1,5 +1,38 @@ package terraform +import ( + "fmt" +) + +// EvalCompareDiff is an EvalNode implementation that compares two diffs +// and errors if the diffs are not equal. +type EvalCompareDiff struct { + Info *InstanceInfo + One, Two **InstanceDiff +} + +func (n *EvalCompareDiff) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +// TODO: test +func (n *EvalCompareDiff) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { + one, two := *n.One, *n.Two + + if !one.Same(two) { + return nil, fmt.Errorf( + "%s: diffs didn't match during apply. This is a bug with "+ + "Terraform and should be reported.", n.Info.Id) + } + + return nil, nil +} + +func (n *EvalCompareDiff) Type() EvalType { + return EvalTypeNull +} + // EvalDiff is an EvalNode implementation that does a refresh for // a resource. type EvalDiff struct { @@ -84,11 +117,15 @@ func (n *EvalDiff) Eval( // Update our output *n.Output = diff - *n.OutputState = state - // Merge our state so that the state is updated with our plan - if !diff.Empty() && n.OutputState != nil { - *n.OutputState = state.MergeDiff(diff) + // Update the state if we care + if n.OutputState != nil { + *n.OutputState = state + + // Merge our state so that the state is updated with our plan + if !diff.Empty() && n.OutputState != nil { + *n.OutputState = state.MergeDiff(diff) + } } return state, nil diff --git a/terraform/transform_resource.go b/terraform/transform_resource.go index e490c51e56..ba06d6a471 100644 --- a/terraform/transform_resource.go +++ b/terraform/transform_resource.go @@ -98,7 +98,7 @@ func (n *graphNodeExpandedResource) ProvidedBy() []string { // GraphNodeEvalable impl. func (n *graphNodeExpandedResource) EvalTree() EvalNode { - var diff *InstanceDiff + var diff, diff2 *InstanceDiff var state *InstanceState // Build the resource. If we aren't part of a multi-resource, then @@ -225,14 +225,32 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode { Ops: []walkOperation{walkApply}, Node: &EvalSequence{ Nodes: []EvalNode{ - &EvalGetProvider{ - Name: n.ProvidedBy()[0], - Output: &provider, + // Redo the diff so we can compare outputs + &EvalDiff{ + Info: info, + Config: interpolateNode, + Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]}, + State: &EvalReadState{Name: n.stateId()}, + Output: &diff2, }, + + // Get the saved diff &EvalReadDiff{ Name: n.stateId(), Diff: &diff, }, + + // Compare the diffs + &EvalCompareDiff{ + Info: info, + One: &diff, + Two: &diff2, + }, + + &EvalGetProvider{ + Name: n.ProvidedBy()[0], + Output: &provider, + }, &EvalReadState{ Name: n.stateId(), Output: &state,