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"
"fmt"
"io"
"sort"
"sync"
"github.com/hashicorp/terraform/config"
@ -29,7 +30,15 @@ func (s *State) init() {
func (s *State) String() string {
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(" ID = %s\n", rs.ID))

View File

@ -136,7 +136,13 @@ func (t *Terraform) applyWalkFn(
result.init()
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 {
return nil, err
}

View File

@ -1,6 +1,7 @@
package terraform
import (
"fmt"
"path/filepath"
"strings"
"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) {
tf := testTerraform(t, "plan-good")
@ -324,6 +352,8 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
}
return func() (ResourceProvider, error) {
p := &MockResourceProvider{Meta: n}
applyFn := func(
s *ResourceState,
d *ResourceDiff) (*ResourceState, error) {
@ -361,11 +391,20 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
}
if k == "compute" {
diff.Attributes[v.(string)] = &ResourceAttrDiff{
attrDiff := &ResourceAttrDiff{
Old: "",
New: "",
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
}
@ -408,15 +447,12 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
return s, nil
}
result := &MockResourceProvider{
Meta: n,
ApplyFn: applyFn,
DiffFn: diffFn,
RefreshFn: refreshFn,
ResourcesReturn: resources,
}
p.ApplyFn = applyFn
p.DiffFn = diffFn
p.RefreshFn = refreshFn
p.ResourcesReturn = resources
return result, nil
return p, nil
}
}
@ -502,6 +538,18 @@ aws_instance.foo:
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 = `
UPDATE: aws_instance.bar
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}"
}