From a614f6105a993934dbf0b3cab97a7a7fd408a877 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 12 Feb 2015 19:34:21 -0800 Subject: [PATCH] terraform: apply starting --- terraform/context.go | 17 ++++--- terraform/context_test.go | 1 - terraform/eval_apply.go | 81 +++++++++++++++++++++++++++++++++ terraform/graph_walk_context.go | 9 +--- 4 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 terraform/eval_apply.go diff --git a/terraform/context.go b/terraform/context.go index df83b0689..7dfbdbc5d 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -27,6 +27,7 @@ type ContextOpts struct { // NewContext. See the documentation for that. type Context2 struct { diff *Diff + diffLock sync.RWMutex hooks []Hook module *module.Tree providers map[string]ResourceProviderFactory @@ -134,17 +135,19 @@ func (c *Context2) Plan(opts *PlanOpts) (*Plan, error) { operation = walkPlan } + // Setup our diff + c.diffLock.Lock() + c.diff = new(Diff) + c.diff.init() + c.diffLock.Unlock() + // Do the walk - walker, err := c.walk(operation) - if err != nil { + if _, err := c.walk(operation); err != nil { return nil, err } - p.Diff = walker.Diff + p.Diff = c.diff - // Update the diff so that our context is up-to-date - c.diff = p.Diff - - return p, err + return p, nil } // Refresh goes through all the resources in the state and refreshes them diff --git a/terraform/context_test.go b/terraform/context_test.go index 5948489a9..1ff312def 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -2673,7 +2673,6 @@ func TestContextInput_varOnly(t *testing.T) { } */ -/* func TestContext2Apply(t *testing.T) { m := testModule(t, "apply-good") p := testProvider("aws") diff --git a/terraform/eval_apply.go b/terraform/eval_apply.go new file mode 100644 index 000000000..032150f1e --- /dev/null +++ b/terraform/eval_apply.go @@ -0,0 +1,81 @@ +package terraform + +import ( + "fmt" + "log" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform/config" +) + +// EvalApply is an EvalNode implementation that writes the diff to +// the full diff. +type EvalApply struct { + Info *InstanceInfo + State **InstanceState + Diff **InstanceDiff + Provider *ResourceProvider + Output **InstanceState +} + +func (n *EvalApply) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +// TODO: test +func (n *EvalApply) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { + diff := *n.Diff + provider := *n.Provider + state := *n.State + + // If we have no diff, we have nothing to do! + if diff.Empty() { + log.Printf( + "[DEBUG] apply: %s: diff is empty, doing nothing.", n.Info.Id) + return nil, nil + } + + // Remove any output values from the diff + for k, ad := range diff.Attributes { + if ad.Type == DiffAttrOutput { + delete(diff.Attributes, k) + } + } + + // TODO: hooks + + // With the completed diff, apply! + log.Printf("[DEBUG] apply: %s: executing Apply", n.Info.Id) + state, err := provider.Apply(n.Info, state, diff) + if state == nil { + state = new(InstanceState) + } + state.init() + + // Force the "id" attribute to be our ID + if state.ID != "" { + state.Attributes["id"] = state.ID + } + + // If the value is the unknown variable value, then it is an error. + // In this case we record the error and remove it from the state + for ak, av := range state.Attributes { + if av == config.UnknownVariableValue { + err = multierror.Append(err, fmt.Errorf( + "Attribute with unknown value: %s", ak)) + delete(state.Attributes, ak) + } + } + + // Write the final state + if n.Output != nil { + *n.Output = state + } + + return nil, nil +} + +func (n *EvalApply) Type() EvalType { + return EvalTypeNull +} diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index f8cc81086..3517cc3fd 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -17,13 +17,11 @@ type ContextGraphWalker struct { // Outputs, do not set these. Do not read these while the graph // is being walked. - Diff *Diff ValidationWarnings []string ValidationErrors []error errorLock sync.Mutex once sync.Once - diffLock sync.RWMutex contexts map[string]*BuiltinEvalContext contextLock sync.Mutex providerCache map[string]ResourceProvider @@ -64,8 +62,8 @@ func (w *ContextGraphWalker) EnterGraph(g *Graph) EvalContext { Provisioners: w.Context.provisioners, ProvisionerCache: w.provisionerCache, ProvisionerLock: &w.provisionerLock, - DiffValue: w.Diff, - DiffLock: &w.diffLock, + DiffValue: w.Context.diff, + DiffLock: &w.Context.diffLock, StateValue: w.Context.state, StateLock: &w.Context.stateLock, Interpolater: &Interpolater{ @@ -111,9 +109,6 @@ func (w *ContextGraphWalker) ExitEvalTree( } func (w *ContextGraphWalker) init() { - w.Diff = new(Diff) - w.Diff.init() - w.contexts = make(map[string]*BuiltinEvalContext, 5) w.providerCache = make(map[string]ResourceProvider, 5) w.providerConfigCache = make(map[string]*ResourceConfig, 5)