implement NodePlannableLocal

Using this in the same manner as NodePlannableOutput, which expands the
local values within modules. All thee output and local types are used in
both plan and apply, we may rename these to better reflect their usage
in expanding. That wait until we are certain that apply won't need any
extra machinery for handling values that aren't stored in the plan.
This commit is contained in:
James Bardin 2020-03-06 18:27:11 -05:00
parent 67e06f4fbe
commit ab9a2935ce
2 changed files with 65 additions and 10 deletions

View File

@ -1,12 +1,73 @@
package terraform package terraform
import ( import (
"log"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/lang"
) )
// NodePlannableLocal represents a named local value in a configuration module,
// which has not yet been expanded.
type NodePlannableLocal struct {
Addr addrs.LocalValue
Module addrs.Module
Config *configs.Local
}
var (
_ RemovableIfNotTargeted = (*NodePlannableLocal)(nil)
_ GraphNodeReferenceable = (*NodePlannableLocal)(nil)
_ GraphNodeReferencer = (*NodePlannableLocal)(nil)
_ GraphNodeDynamicExpandable = (*NodePlannableLocal)(nil)
)
func (n *NodePlannableLocal) Name() string {
path := n.Module.String()
addr := n.Addr.String()
if path != "" {
return path + "." + addr
}
return addr
}
// GraphNodeModulePath
func (n *NodePlannableLocal) ModulePath() addrs.Module {
return n.Module
}
// RemovableIfNotTargeted
func (n *NodePlannableLocal) RemoveIfNotTargeted() bool {
return true
}
// GraphNodeReferenceable
func (n *NodePlannableLocal) ReferenceableAddrs() []addrs.Referenceable {
return []addrs.Referenceable{n.Addr}
}
// GraphNodeReferencer
func (n *NodePlannableLocal) References() []*addrs.Reference {
refs, _ := lang.ReferencesInExpr(n.Config.Expr)
return appendResourceDestroyReferences(refs)
}
func (n *NodePlannableLocal) DynamicExpand(ctx EvalContext) (*Graph, error) {
var g Graph
expander := ctx.InstanceExpander()
for _, module := range expander.ExpandModule(n.Module) {
o := &NodeLocal{
Addr: n.Addr.Absolute(module),
Config: n.Config,
}
log.Printf("[TRACE] Expanding local: adding %s as %T", o.Addr.String(), o)
g.Add(o)
}
return &g, nil
}
// NodeLocal represents a named local value in a particular module. // NodeLocal represents a named local value in a particular module.
// //
// Local value nodes only have one operation, common to all walk types: // Local value nodes only have one operation, common to all walk types:

View File

@ -1,6 +1,7 @@
package terraform package terraform
import ( import (
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
) )
@ -20,18 +21,11 @@ func (t *LocalTransformer) transformModule(g *Graph, c *configs.Config) error {
return nil return nil
} }
// Our addressing system distinguishes between modules and module instances,
// but we're not yet ready to make that distinction here (since we don't
// support "count"/"for_each" on modules) and so we just do a naive
// transform of the module path into a module instance path, assuming that
// no keys are in use. This should be removed when "count" and "for_each"
// are implemented for modules.
path := c.Path.UnkeyedInstanceShim()
for _, local := range c.Module.Locals { for _, local := range c.Module.Locals {
addr := path.LocalValue(local.Name) addr := addrs.LocalValue{Name: local.Name}
node := &NodeLocal{ node := &NodePlannableLocal{
Addr: addr, Addr: addr,
Module: c.Path,
Config: local, Config: local,
} }
g.Add(node) g.Add(node)