From d026d4207e4f406a8f189dcdd7173beab4b68dc3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 30 Jun 2014 19:29:07 -0700 Subject: [PATCH] terraform: apply diff before apply --- terraform/resource.go | 18 ++++++++++ terraform/terraform.go | 33 +++++++++---------- terraform/terraform_test.go | 6 ++-- terraform/test-fixtures/apply-compute/main.tf | 4 +-- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/terraform/resource.go b/terraform/resource.go index 3efa11c69..a9db7e6a4 100644 --- a/terraform/resource.go +++ b/terraform/resource.go @@ -1,5 +1,9 @@ package terraform +import ( + "fmt" +) + // Resource encapsulates a resource, its configuration, its provider, // its current state, and potentially a desired diff from the state it // wants to reach. @@ -10,3 +14,17 @@ type Resource struct { Provider ResourceProvider 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 +} diff --git a/terraform/terraform.go b/terraform/terraform.go index f16155c61..149bd9f6e 100644 --- a/terraform/terraform.go +++ b/terraform/terraform.go @@ -102,6 +102,13 @@ func (t *Terraform) Refresh(c *config.Config, s *State) (*State, error) { func (t *Terraform) apply( g *depgraph.Graph, 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) err := g.Walk(t.applyWalkFn(s, p)) return s, err @@ -170,11 +177,9 @@ func (t *Terraform) applyWalkFn( result.init() cb := func(r *Resource) (map[string]string, error) { - diff, ok := p.Diff.Resources[r.Id] - if !ok { - // Skip if there is no diff for a resource - log.Printf("[DEBUG] No diff for %s, skipping.", r.Id) - return nil, nil + diff := r.Diff + if diff.Empty() { + return r.Vars(), nil } if !diff.Destroy { @@ -229,23 +234,21 @@ func (t *Terraform) applyWalkFn( result.Resources[r.Id] = rs l.Unlock() + // Update the state for the resource itself + r.State = rs + for _, h := range t.hooks { // TODO: return value h.PostApply(r.Id, r.State) } // 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 if len(errs) > 0 { err = &MultiError{Errors: errs} } - return vars, err + return r.Vars(), err } 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 - vars := make(map[string]string) if !diff.Empty() { 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) diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index df62962d0..dea495dd2 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -493,7 +493,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory { } id := "foo" - if idAttr, ok := d.Attributes["id"]; ok { + if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed { id = idAttr.New } @@ -687,12 +687,12 @@ const testTerraformApplyComputeStr = ` aws_instance.bar: ID = foo type = aws_instance - foo = computed_id + foo = computed_dynamical aws_instance.foo: ID = foo type = aws_instance num = 2 - id = computed_id + dynamical = computed_dynamical ` const testTerraformApplyDestroyStr = ` diff --git a/terraform/test-fixtures/apply-compute/main.tf b/terraform/test-fixtures/apply-compute/main.tf index cff609825..3999b5912 100644 --- a/terraform/test-fixtures/apply-compute/main.tf +++ b/terraform/test-fixtures/apply-compute/main.tf @@ -1,9 +1,9 @@ resource "aws_instance" "foo" { num = "2" - compute = "id" + compute = "dynamical" compute_value = "${var.value}" } resource "aws_instance" "bar" { - foo = "${aws_instance.foo.id}" + foo = "${aws_instance.foo.dynamical}" }