terraform: validate almost done

This commit is contained in:
Mitchell Hashimoto 2015-02-04 18:44:23 -05:00
parent 012d68923c
commit d9a964f44c
5 changed files with 4951 additions and 15 deletions

114
terraform/context.go Normal file
View File

@ -0,0 +1,114 @@
package terraform
import (
"sync"
"github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/dag"
)
// ContextOpts are the user-configurable options to create a context with
// NewContext.
type ContextOpts struct {
Diff *Diff
Hooks []Hook
Module *module.Tree
Parallelism int
State *State
Providers map[string]ResourceProviderFactory
Provisioners map[string]ResourceProvisionerFactory
Variables map[string]string
UIInput UIInput
}
// Context represents all the context that Terraform needs in order to
// perform operations on infrastructure. This structure is built using
// NewContext. See the documentation for that.
type Context2 struct {
module *module.Tree
providers map[string]ResourceProviderFactory
state *State
}
// NewContext creates a new Context structure.
//
// Once a Context is creator, the pointer values within ContextOpts
// should not be mutated in any way, since the pointers are copied, not
// the values themselves.
func NewContext2(opts *ContextOpts) *Context2 {
return &Context2{
module: opts.Module,
providers: opts.Providers,
state: opts.State,
}
}
// GraphBuilder returns the GraphBuilder that will be used to create
// the graphs for this context.
func (c *Context2) GraphBuilder() GraphBuilder {
// TODO test
providers := make([]string, 0, len(c.providers))
for k, _ := range c.providers {
providers = append(providers, k)
}
return &BuiltinGraphBuilder{
Root: c.module,
Providers: providers,
State: c.state,
}
}
// Validate validates the configuration and returns any warnings or errors.
func (c *Context2) Validate() ([]string, []error) {
evalCtx := c.evalContext()
evalCtx.ComputeMissing = true
// Build the graph
graph, err := c.GraphBuilder().Build(RootModulePath)
if err != nil {
return nil, []error{err}
}
// Valiate the graph
if err := graph.Validate(); err != nil {
return nil, []error{err}
}
// Walk the graph
var warns []string
var errs []error
var lock sync.Mutex
graph.Walk(func(v dag.Vertex) {
ev, ok := v.(GraphNodeEvalable)
if !ok {
return
}
_, err := Eval(ev.EvalTree(), evalCtx)
if err == nil {
return
}
lock.Lock()
defer lock.Unlock()
verr, ok := err.(*EvalValidateError)
if !ok {
errs = append(errs, err)
return
}
warns = append(warns, verr.Warnings...)
errs = append(errs, verr.Errors...)
})
return warns, errs
}
func (c *Context2) evalContext() *BuiltinEvalContext {
return &BuiltinEvalContext{
Providers: c.providers,
}
}

View File

@ -44,21 +44,6 @@ type Context struct {
sh *stopHook sh *stopHook
} }
// ContextOpts are the user-creatable configuration structure to create
// a context with NewContext.
type ContextOpts struct {
Diff *Diff
Hooks []Hook
Module *module.Tree
Parallelism int
State *State
Providers map[string]ResourceProviderFactory
Provisioners map[string]ResourceProvisionerFactory
Variables map[string]string
UIInput UIInput
}
// InputMode defines what sort of input will be asked for when Input // InputMode defines what sort of input will be asked for when Input
// is called on Context. // is called on Context.
type InputMode byte type InputMode byte

4789
terraform/context_test.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
package terraform
import (
"fmt"
"github.com/hashicorp/terraform/config"
)
// EvalValidateError is the error structure returned if there were
// validation errors.
type EvalValidateError struct {
Warnings []string
Errors []error
}
func (e *EvalValidateError) Error() string {
return ""
}
// EvalValidateResource is an EvalNode implementation that validates
// the configuration of a resource.
type EvalValidateResource struct {
Provider EvalNode
Config *config.RawConfig
}
func (n *EvalValidateResource) Args() ([]EvalNode, []EvalType) {
return []EvalNode{n.Provider},
[]EvalType{EvalTypeResourceProvider}
}
func (n *EvalValidateResource) Eval(
ctx EvalContext, args []interface{}) (interface{}, error) {
//provider := args[0].(ResourceProvider)
return nil, fmt.Errorf("WHAT")
}
func (n *EvalValidateResource) Type() EvalType {
return EvalTypeNull
}

View File

@ -119,6 +119,14 @@ func (n *GraphNodeConfigResource) Name() string {
return n.Resource.Id() return n.Resource.Id()
} }
// GraphNodeEvalable impl.
func (n *GraphNodeConfigResource) EvalTree() EvalNode {
return &EvalValidateResource{
Provider: &EvalGetProvider{Name: n.ProvidedBy()},
Config: n.Resource.RawConfig,
}
}
// GraphNodeProviderConsumer // GraphNodeProviderConsumer
func (n *GraphNodeConfigResource) ProvidedBy() string { func (n *GraphNodeConfigResource) ProvidedBy() string {
return resourceProvider(n.Resource.Type) return resourceProvider(n.Resource.Type)