From 128c07e504be50b178b7551e40197d67efa0abfe Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Feb 2015 10:43:18 +0100 Subject: [PATCH] terraform: start eval stuff, untested --- terraform/eval.go | 33 ++++++++++++++++ terraform/eval_interpolate.go | 23 +++++++++++ terraform/eval_provider.go | 67 +++++++++++++++++++++++++++++++++ terraform/eval_type.go | 19 ++++++++++ terraform/evaltype_string.go | 34 +++++++++++++++++ terraform/graph_config_node.go | 8 ++++ terraform/transform_provider.go | 5 +++ 7 files changed, 189 insertions(+) create mode 100644 terraform/eval.go create mode 100644 terraform/eval_interpolate.go create mode 100644 terraform/eval_provider.go create mode 100644 terraform/eval_type.go create mode 100644 terraform/evaltype_string.go diff --git a/terraform/eval.go b/terraform/eval.go new file mode 100644 index 000000000..7a274d14c --- /dev/null +++ b/terraform/eval.go @@ -0,0 +1,33 @@ +package terraform + +// EvalContext is the interface that is given to eval nodes to execute. +type EvalContext interface { + // InitProvider initializes the provider with the given name and + // returns the implementation of the resource provider or an error. + InitProvider(string) (ResourceProvider, error) + + // Provider gets the provider instance with the given name (already + // initialized) or returns nil if the provider isn't initialized. + Provider(string) ResourceProvider +} + +// EvalNode is the interface that must be implemented by graph nodes to +// evaluate/execute. +type EvalNode interface { + // Args returns the arguments for this node as well as the list of + // expected types. The expected types are only used for type checking + // and not used at runtime. + Args() ([]EvalNode, []EvalType) + + // Eval evaluates this node with the given context. + Eval(EvalContext) (interface{}, error) + + // Type returns the type that will be returned by this node. + Type() EvalType +} + +// GraphNodeEvalable is the interface that graph nodes must implement +// to enable valuation. +type GraphNodeEvalable interface { + EvalTree() EvalNode +} diff --git a/terraform/eval_interpolate.go b/terraform/eval_interpolate.go new file mode 100644 index 000000000..ea7846b96 --- /dev/null +++ b/terraform/eval_interpolate.go @@ -0,0 +1,23 @@ +package terraform + +import ( + "github.com/hashicorp/terraform/config" +) + +// EvalInterpolate is an EvalNode implementation that takes a raw +// configuration and interpolates it. +type EvalInterpolate struct { + Config *config.RawConfig +} + +func (n *EvalInterpolate) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +func (n *EvalInterpolate) Eval(ctx EvalContext) (interface{}, error) { + return nil, nil +} + +func (n *EvalInterpolate) Type() EvalType { + return EvalTypeConfig +} diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go new file mode 100644 index 000000000..f2c9115bf --- /dev/null +++ b/terraform/eval_provider.go @@ -0,0 +1,67 @@ +package terraform + +import ( + "fmt" +) + +// EvalConfigProvider is an EvalNode implementation that configures +// a provider that is already initialized and retrieved. +type EvalConfigProvider struct { + Provider EvalNode + Config EvalNode +} + +func (n *EvalConfigProvider) Args() ([]EvalNode, []EvalType) { + return []EvalNode{n.Provider, n.Config}, + []EvalType{EvalTypeResourceProvider, EvalTypeConfig} +} + +func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { + return nil, nil +} + +func (n *EvalConfigProvider) Type() EvalType { + return EvalTypeNull +} + +// EvalInitProvider is an EvalNode implementation that initializes a provider +// and returns nothing. The provider can be retrieved again with the +// EvalGetProvider node. +type EvalInitProvider struct { + Name string +} + +func (n *EvalInitProvider) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) { + return ctx.InitProvider(n.Name) +} + +func (n *EvalInitProvider) Type() EvalType { + return EvalTypeNull +} + +// EvalGetProvider is an EvalNode implementation that retrieves an already +// initialized provider instance for the given name. +type EvalGetProvider struct { + Name string +} + +func (n *EvalGetProvider) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { + result := ctx.Provider(n.Name) + if result == nil { + return nil, fmt.Errorf("provider %s not initialized", n.Name) + } + + return result, nil +} + +func (n *EvalGetProvider) Type() EvalType { + return EvalTypeResourceProvider +} diff --git a/terraform/eval_type.go b/terraform/eval_type.go new file mode 100644 index 000000000..cf25cfc12 --- /dev/null +++ b/terraform/eval_type.go @@ -0,0 +1,19 @@ +package terraform + +// This separate file for EvalType exists so that stringer below +// can work without error. See this thread for more details: +// +// http://comments.gmane.org/gmane.comp.lang.go.general/148740 + +//go:generate stringer -type=EvalType eval_type.go + +// EvalType is the type of any value returned by an EvalNode. This is +// used for type checking. +type EvalType uint32 + +const ( + EvalTypeInvalid EvalType = 0 + EvalTypeNull EvalType = 1 << iota + EvalTypeConfig + EvalTypeResourceProvider +) diff --git a/terraform/evaltype_string.go b/terraform/evaltype_string.go new file mode 100644 index 000000000..6e60fd28d --- /dev/null +++ b/terraform/evaltype_string.go @@ -0,0 +1,34 @@ +// generated by stringer -type=EvalType eval_type.go; DO NOT EDIT + +package terraform + +import "fmt" + +const ( + _EvalType_name_0 = "EvalTypeInvalid" + _EvalType_name_1 = "EvalTypeNull" + _EvalType_name_2 = "EvalTypeConfig" + _EvalType_name_3 = "EvalTypeResourceProvider" +) + +var ( + _EvalType_index_0 = [...]uint8{0, 15} + _EvalType_index_1 = [...]uint8{0, 12} + _EvalType_index_2 = [...]uint8{0, 14} + _EvalType_index_3 = [...]uint8{0, 24} +) + +func (i EvalType) String() string { + switch { + case i == 0: + return _EvalType_name_0 + case i == 2: + return _EvalType_name_1 + case i == 4: + return _EvalType_name_2 + case i == 8: + return _EvalType_name_3 + default: + return fmt.Sprintf("EvalType(%d)", i) + } +} diff --git a/terraform/graph_config_node.go b/terraform/graph_config_node.go index c586245c3..edea52287 100644 --- a/terraform/graph_config_node.go +++ b/terraform/graph_config_node.go @@ -73,6 +73,14 @@ func (n *GraphNodeConfigProvider) DependentOn() []string { return result } +// GraphNodeEvalable impl. +func (n *GraphNodeConfigProvider) EvalTree() EvalNode { + return &EvalConfigProvider{ + Provider: &EvalGetProvider{Name: n.Provider.Name}, + Config: &EvalInterpolate{Config: n.Provider.RawConfig}, + } +} + // GraphNodeProvider implementation func (n *GraphNodeConfigProvider) ProviderName() string { return n.Provider.Name diff --git a/terraform/transform_provider.go b/terraform/transform_provider.go index a7bcca478..e68e6f610 100644 --- a/terraform/transform_provider.go +++ b/terraform/transform_provider.go @@ -100,6 +100,11 @@ func (n *graphNodeMissingProvider) Name() string { return fmt.Sprintf("provider.%s", n.ProviderNameValue) } +// GraphNodeEvalable impl. +func (n *graphNodeMissingProvider) EvalTree() EvalNode { + return &EvalInitProvider{Name: n.ProviderNameValue} +} + func (n *graphNodeMissingProvider) ProviderName() string { return n.ProviderNameValue }