From ab9a2935ced85ece918e2c960b677abaac15026a Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 6 Mar 2020 18:27:11 -0500 Subject: [PATCH] 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. --- terraform/node_local.go | 61 ++++++++++++++++++++++++++++++++++++ terraform/transform_local.go | 14 +++------ 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/terraform/node_local.go b/terraform/node_local.go index 9861f0a15..50cff018a 100644 --- a/terraform/node_local.go +++ b/terraform/node_local.go @@ -1,12 +1,73 @@ package terraform import ( + "log" + "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/dag" "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. // // Local value nodes only have one operation, common to all walk types: diff --git a/terraform/transform_local.go b/terraform/transform_local.go index 84eb26b26..7739ff48d 100644 --- a/terraform/transform_local.go +++ b/terraform/transform_local.go @@ -1,6 +1,7 @@ package terraform import ( + "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" ) @@ -20,18 +21,11 @@ func (t *LocalTransformer) transformModule(g *Graph, c *configs.Config) error { 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 { - addr := path.LocalValue(local.Name) - node := &NodeLocal{ + addr := addrs.LocalValue{Name: local.Name} + node := &NodePlannableLocal{ Addr: addr, + Module: c.Path, Config: local, } g.Add(node)