terraform: re-diff on apply

This commit is contained in:
Mitchell Hashimoto 2014-06-23 12:19:41 -07:00
parent 84cf644a30
commit 92ffbf2880
4 changed files with 82 additions and 11 deletions

View File

@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"sort"
"sync" "sync"
"github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/config"
@ -29,7 +30,15 @@ func (s *State) init() {
func (s *State) String() string { func (s *State) String() string {
var buf bytes.Buffer var buf bytes.Buffer
for k, rs := range s.Resources { names := make([]string, 0, len(s.Resources))
for name, _ := range s.Resources {
names = append(names, name)
}
sort.Strings(names)
for _, k := range names {
rs := s.Resources[k]
buf.WriteString(fmt.Sprintf("%s:\n", k)) buf.WriteString(fmt.Sprintf("%s:\n", k))
buf.WriteString(fmt.Sprintf(" ID = %s\n", rs.ID)) buf.WriteString(fmt.Sprintf(" ID = %s\n", rs.ID))

View File

@ -136,7 +136,13 @@ func (t *Terraform) applyWalkFn(
result.init() result.init()
cb := func(r *Resource) (map[string]string, error) { cb := func(r *Resource) (map[string]string, error) {
rs, err := r.Provider.Apply(r.State, r.Diff) // Get the latest diff since there are no computed values anymore
diff, err := r.Provider.Diff(r.State, r.Config)
if err != nil {
return nil, err
}
rs, err := r.Provider.Apply(r.State, diff)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,7 @@
package terraform package terraform
import ( import (
"fmt"
"path/filepath" "path/filepath"
"strings" "strings"
"testing" "testing"
@ -228,6 +229,33 @@ func TestTerraformApply(t *testing.T) {
} }
} }
func TestTerraformApply_compute(t *testing.T) {
// This tests that computed variables are properly re-diffed
// to get the value prior to application (Apply).
tf := testTerraform(t, "apply-compute")
s := &State{}
p, err := tf.Plan(s)
if err != nil {
t.Fatalf("err: %s", err)
}
// Set meta to change behavior so that computed variables are filled
testProviderMock(testProvider(tf, "aws_instance.foo")).Meta =
"compute"
state, err := tf.Apply(p)
if err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(state.String())
expected := strings.TrimSpace(testTerraformApplyComputeStr)
if actual != expected {
t.Fatalf("bad: \n%s", actual)
}
}
func TestTerraformPlan(t *testing.T) { func TestTerraformPlan(t *testing.T) {
tf := testTerraform(t, "plan-good") tf := testTerraform(t, "plan-good")
@ -324,6 +352,8 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
} }
return func() (ResourceProvider, error) { return func() (ResourceProvider, error) {
p := &MockResourceProvider{Meta: n}
applyFn := func( applyFn := func(
s *ResourceState, s *ResourceState,
d *ResourceDiff) (*ResourceState, error) { d *ResourceDiff) (*ResourceState, error) {
@ -361,11 +391,20 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
} }
if k == "compute" { if k == "compute" {
diff.Attributes[v.(string)] = &ResourceAttrDiff{ attrDiff := &ResourceAttrDiff{
Old: "", Old: "",
New: "", New: "",
NewComputed: true, NewComputed: true,
} }
// If the value of Meta turns into "compute", then we
// fill the computed values.
if mv, ok := p.Meta.(string); ok && mv == "compute" {
attrDiff.NewComputed = false
attrDiff.New = fmt.Sprintf("computed_%s", v.(string))
}
diff.Attributes[v.(string)] = attrDiff
continue continue
} }
@ -408,15 +447,12 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
return s, nil return s, nil
} }
result := &MockResourceProvider{ p.ApplyFn = applyFn
Meta: n, p.DiffFn = diffFn
ApplyFn: applyFn, p.RefreshFn = refreshFn
DiffFn: diffFn, p.ResourcesReturn = resources
RefreshFn: refreshFn,
ResourcesReturn: resources,
}
return result, nil return p, nil
} }
} }
@ -502,6 +538,18 @@ aws_instance.foo:
num = 2 num = 2
` `
const testTerraformApplyComputeStr = `
aws_instance.bar:
ID = foo
type = aws_instance
foo = computed_id
aws_instance.foo:
ID = foo
type = aws_instance
num = 2
id = computed_id
`
const testTerraformPlanStr = ` const testTerraformPlanStr = `
UPDATE: aws_instance.bar UPDATE: aws_instance.bar
foo: "" => "2" foo: "" => "2"

View File

@ -0,0 +1,8 @@
resource "aws_instance" "foo" {
num = "2"
compute = "id"
}
resource "aws_instance" "bar" {
foo = "${aws_instance.foo.id}"
}