core: graph nodes and edges for local values

A local value is similar to an output in that it exists only within state
and just always evaluates its value as best it can with the current state.
Therefore it has a single graph node type for all walks, which will
deal with that evaluation operation.
This commit is contained in:
Martin Atkins 2017-07-01 09:48:37 -07:00
parent d41d58967f
commit 5b66953d1d
7 changed files with 142 additions and 0 deletions

View File

@ -74,6 +74,9 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
Module: b.Module,
},
// Add the local values
&LocalTransformer{Module: b.Module},
// Add the outputs
&OutputTransformer{Module: b.Module},

View File

@ -61,16 +61,22 @@ aws_load_balancer.weblb
provider.aws
aws_security_group.firewall
provider.aws
local.instance_id
aws_instance.web
meta.count-boundary (count boundary fixup)
aws_instance.web
aws_load_balancer.weblb
aws_security_group.firewall
local.instance_id
openstack_floating_ip.random
output.instance_id
provider.aws
provider.openstack
var.foo
openstack_floating_ip.random
provider.openstack
output.instance_id
local.instance_id
provider.aws
openstack_floating_ip.random
provider.aws (close)

View File

@ -133,6 +133,9 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
&ParentProviderTransformer{},
&AttachProviderConfigTransformer{Module: b.Module},
// Add the local values
&LocalTransformer{Module: b.Module},
// Add the outputs
&OutputTransformer{Module: b.Module},

80
terraform/node_local.go Normal file
View File

@ -0,0 +1,80 @@
package terraform
import (
"fmt"
"strings"
"github.com/hashicorp/terraform/config"
)
// NodeLocal represents a named local value in a particular module.
//
// Local value nodes only have one operation, common to all walk types:
// evaluate the result and place it in state.
type NodeLocal struct {
PathValue []string
Config *config.Local
}
func (n *NodeLocal) Name() string {
result := fmt.Sprintf("local.%s", n.Config.Name)
if len(n.PathValue) > 1 {
result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
}
return result
}
// GraphNodeSubPath
func (n *NodeLocal) Path() []string {
return n.PathValue
}
// RemovableIfNotTargeted
func (n *NodeLocal) RemoveIfNotTargeted() bool {
return true
}
// GraphNodeReferenceable
func (n *NodeLocal) ReferenceableName() []string {
name := fmt.Sprintf("local.%s", n.Config.Name)
return []string{name}
}
// GraphNodeReferencer
func (n *NodeLocal) References() []string {
var result []string
result = append(result, ReferencesFromConfig(n.Config.RawConfig)...)
for _, v := range result {
split := strings.Split(v, "/")
for i, s := range split {
split[i] = s + ".destroy"
}
result = append(result, strings.Join(split, "/"))
}
return result
}
// GraphNodeEvalable
func (n *NodeLocal) EvalTree() EvalNode {
return &EvalOpFilter{
Ops: []walkOperation{
walkInput,
walkValidate,
walkRefresh,
walkPlan,
walkApply,
walkDestroy,
},
Node: &EvalSequence{
Nodes: []EvalNode{
/*&EvalWriteLocal{
Name: n.Config.Name,
Value: n.Config.RawConfig,
},*/
},
},
}
}

View File

@ -22,3 +22,11 @@ resource "aws_instance" "web" {
resource "aws_load_balancer" "weblb" {
members = "${aws_instance.web.id_list}"
}
locals {
instance_id = "${aws_instance.web.id}"
}
output "instance_id" {
value = "${local.instance_id}"
}

View File

@ -0,0 +1,40 @@
package terraform
import (
"github.com/hashicorp/terraform/config/module"
)
// LocalTransformer is a GraphTransformer that adds all the local values
// from the configuration to the graph.
type LocalTransformer struct {
Module *module.Tree
}
func (t *LocalTransformer) Transform(g *Graph) error {
return t.transformModule(g, t.Module)
}
func (t *LocalTransformer) transformModule(g *Graph, m *module.Tree) error {
if m == nil {
// Can't have any locals if there's no config
return nil
}
for _, local := range m.Config().Locals {
node := &NodeLocal{
PathValue: normalizeModulePath(m.Path()),
Config: local,
}
g.Add(node)
}
// Also populate locals for child modules
for _, c := range m.Children() {
if err := t.transformModule(g, c); err != nil {
return err
}
}
return nil
}

View File

@ -296,6 +296,8 @@ func ReferenceFromInterpolatedVar(v config.InterpolatedVariable) []string {
return []string{fmt.Sprintf("%s.%d/%s.N", id, idx, id)}
case *config.UserVariable:
return []string{fmt.Sprintf("var.%s", v.Name)}
case *config.LocalVariable:
return []string{fmt.Sprintf("local.%s", v.Name)}
default:
return nil
}