terraform: apply diff before apply

This commit is contained in:
Mitchell Hashimoto 2014-06-30 19:29:07 -07:00
parent 2d72164c6a
commit d026d4207e
4 changed files with 38 additions and 23 deletions

View File

@ -1,5 +1,9 @@
package terraform package terraform
import (
"fmt"
)
// Resource encapsulates a resource, its configuration, its provider, // Resource encapsulates a resource, its configuration, its provider,
// its current state, and potentially a desired diff from the state it // its current state, and potentially a desired diff from the state it
// wants to reach. // wants to reach.
@ -10,3 +14,17 @@ type Resource struct {
Provider ResourceProvider Provider ResourceProvider
State *ResourceState State *ResourceState
} }
// TODO: test
func (r *Resource) Vars() map[string]string {
if r.State == nil {
return nil
}
vars := make(map[string]string)
for ak, av := range r.State.Attributes {
vars[fmt.Sprintf("%s.%s", r.Id, ak)] = av
}
return vars
}

View File

@ -102,6 +102,13 @@ func (t *Terraform) Refresh(c *config.Config, s *State) (*State, error) {
func (t *Terraform) apply( func (t *Terraform) apply(
g *depgraph.Graph, g *depgraph.Graph,
p *Plan) (*State, error) { p *Plan) (*State, error) {
if err := GraphAddDiff(g, p.Diff); err != nil {
return nil, err
}
if err := g.Validate(); err != nil {
return nil, err
}
s := new(State) s := new(State)
err := g.Walk(t.applyWalkFn(s, p)) err := g.Walk(t.applyWalkFn(s, p))
return s, err return s, err
@ -170,11 +177,9 @@ func (t *Terraform) applyWalkFn(
result.init() result.init()
cb := func(r *Resource) (map[string]string, error) { cb := func(r *Resource) (map[string]string, error) {
diff, ok := p.Diff.Resources[r.Id] diff := r.Diff
if !ok { if diff.Empty() {
// Skip if there is no diff for a resource return r.Vars(), nil
log.Printf("[DEBUG] No diff for %s, skipping.", r.Id)
return nil, nil
} }
if !diff.Destroy { if !diff.Destroy {
@ -229,23 +234,21 @@ func (t *Terraform) applyWalkFn(
result.Resources[r.Id] = rs result.Resources[r.Id] = rs
l.Unlock() l.Unlock()
// Update the state for the resource itself
r.State = rs
for _, h := range t.hooks { for _, h := range t.hooks {
// TODO: return value // TODO: return value
h.PostApply(r.Id, r.State) h.PostApply(r.Id, r.State)
} }
// Determine the new state and update variables // Determine the new state and update variables
vars := make(map[string]string)
for ak, av := range rs.Attributes {
vars[fmt.Sprintf("%s.%s", r.Id, ak)] = av
}
err = nil err = nil
if len(errs) > 0 { if len(errs) > 0 {
err = &MultiError{Errors: errs} err = &MultiError{Errors: errs}
} }
return vars, err return r.Vars(), err
} }
return t.genericWalkFn(p.Vars, cb) return t.genericWalkFn(p.Vars, cb)
@ -298,17 +301,11 @@ func (t *Terraform) planWalkFn(result *Plan, opts *PlanOpts) depgraph.WalkFunc {
} }
// Determine the new state and update variables // Determine the new state and update variables
vars := make(map[string]string)
if !diff.Empty() { if !diff.Empty() {
r.State = r.State.MergeDiff(diff) r.State = r.State.MergeDiff(diff)
} }
if r.State != nil {
for ak, av := range r.State.Attributes {
vars[fmt.Sprintf("%s.%s", r.Id, ak)] = av
}
}
return vars, nil return r.Vars(), nil
} }
return t.genericWalkFn(opts.Vars, cb) return t.genericWalkFn(opts.Vars, cb)

View File

@ -493,7 +493,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
} }
id := "foo" id := "foo"
if idAttr, ok := d.Attributes["id"]; ok { if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed {
id = idAttr.New id = idAttr.New
} }
@ -687,12 +687,12 @@ const testTerraformApplyComputeStr = `
aws_instance.bar: aws_instance.bar:
ID = foo ID = foo
type = aws_instance type = aws_instance
foo = computed_id foo = computed_dynamical
aws_instance.foo: aws_instance.foo:
ID = foo ID = foo
type = aws_instance type = aws_instance
num = 2 num = 2
id = computed_id dynamical = computed_dynamical
` `
const testTerraformApplyDestroyStr = ` const testTerraformApplyDestroyStr = `

View File

@ -1,9 +1,9 @@
resource "aws_instance" "foo" { resource "aws_instance" "foo" {
num = "2" num = "2"
compute = "id" compute = "dynamical"
compute_value = "${var.value}" compute_value = "${var.value}"
} }
resource "aws_instance" "bar" { resource "aws_instance" "bar" {
foo = "${aws_instance.foo.id}" foo = "${aws_instance.foo.dynamical}"
} }