terraform: apply starting

This commit is contained in:
Mitchell Hashimoto 2015-02-12 19:34:21 -08:00
parent 93f3050dbd
commit a614f6105a
4 changed files with 93 additions and 15 deletions

View File

@ -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

View File

@ -2673,7 +2673,6 @@ func TestContextInput_varOnly(t *testing.T) {
}
*/
/*
func TestContext2Apply(t *testing.T) {
m := testModule(t, "apply-good")
p := testProvider("aws")

81
terraform/eval_apply.go Normal file
View File

@ -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
}

View File

@ -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)