| package terraform |
| |
| import ( |
| "log" |
| |
| "github.com/hashicorp/terraform/internal/addrs" |
| "github.com/hashicorp/terraform/internal/dag" |
| "github.com/hashicorp/terraform/internal/lang" |
| "github.com/hashicorp/terraform/internal/tfdiags" |
| ) |
| |
| // nodeExpandApplyableResource handles the first layer of resource |
| // expansion during apply. Even though the resource instances themselves are |
| // already expanded from the plan, we still need to expand the |
| // NodeApplyableResource nodes into their respective modules. |
| type nodeExpandApplyableResource struct { |
| *NodeAbstractResource |
| } |
| |
| var ( |
| _ GraphNodeDynamicExpandable = (*nodeExpandApplyableResource)(nil) |
| _ GraphNodeReferenceable = (*nodeExpandApplyableResource)(nil) |
| _ GraphNodeReferencer = (*nodeExpandApplyableResource)(nil) |
| _ GraphNodeConfigResource = (*nodeExpandApplyableResource)(nil) |
| _ GraphNodeAttachResourceConfig = (*nodeExpandApplyableResource)(nil) |
| _ graphNodeExpandsInstances = (*nodeExpandApplyableResource)(nil) |
| _ GraphNodeTargetable = (*nodeExpandApplyableResource)(nil) |
| ) |
| |
| func (n *nodeExpandApplyableResource) expandsInstances() { |
| } |
| |
| func (n *nodeExpandApplyableResource) References() []*addrs.Reference { |
| return (&NodeApplyableResource{NodeAbstractResource: n.NodeAbstractResource}).References() |
| } |
| |
| func (n *nodeExpandApplyableResource) Name() string { |
| return n.NodeAbstractResource.Name() + " (expand)" |
| } |
| |
| func (n *nodeExpandApplyableResource) DynamicExpand(ctx EvalContext) (*Graph, error) { |
| var g Graph |
| |
| expander := ctx.InstanceExpander() |
| moduleInstances := expander.ExpandModule(n.Addr.Module) |
| for _, module := range moduleInstances { |
| g.Add(&NodeApplyableResource{ |
| NodeAbstractResource: n.NodeAbstractResource, |
| Addr: n.Addr.Resource.Absolute(module), |
| }) |
| } |
| addRootNodeToGraph(&g) |
| |
| return &g, nil |
| } |
| |
| // NodeApplyableResource represents a resource that is "applyable": |
| // it may need to have its record in the state adjusted to match configuration. |
| // |
| // Unlike in the plan walk, this resource node does not DynamicExpand. Instead, |
| // it should be inserted into the same graph as any instances of the nodes |
| // with dependency edges ensuring that the resource is evaluated before any |
| // of its instances, which will turn ensure that the whole-resource record |
| // in the state is suitably prepared to receive any updates to instances. |
| type NodeApplyableResource struct { |
| *NodeAbstractResource |
| |
| Addr addrs.AbsResource |
| } |
| |
| var ( |
| _ GraphNodeModuleInstance = (*NodeApplyableResource)(nil) |
| _ GraphNodeConfigResource = (*NodeApplyableResource)(nil) |
| _ GraphNodeExecutable = (*NodeApplyableResource)(nil) |
| _ GraphNodeProviderConsumer = (*NodeApplyableResource)(nil) |
| _ GraphNodeAttachResourceConfig = (*NodeApplyableResource)(nil) |
| _ GraphNodeReferencer = (*NodeApplyableResource)(nil) |
| ) |
| |
| func (n *NodeApplyableResource) Path() addrs.ModuleInstance { |
| return n.Addr.Module |
| } |
| |
| func (n *NodeApplyableResource) References() []*addrs.Reference { |
| if n.Config == nil { |
| log.Printf("[WARN] NodeApplyableResource %q: no configuration, so can't determine References", dag.VertexName(n)) |
| return nil |
| } |
| |
| var result []*addrs.Reference |
| |
| // Since this node type only updates resource-level metadata, we only |
| // need to worry about the parts of the configuration that affect |
| // our "each mode": the count and for_each meta-arguments. |
| refs, _ := lang.ReferencesInExpr(n.Config.Count) |
| result = append(result, refs...) |
| refs, _ = lang.ReferencesInExpr(n.Config.ForEach) |
| result = append(result, refs...) |
| |
| return result |
| } |
| |
| // GraphNodeExecutable |
| func (n *NodeApplyableResource) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { |
| if n.Config == nil { |
| // Nothing to do, then. |
| log.Printf("[TRACE] NodeApplyableResource: no configuration present for %s", n.Name()) |
| return nil |
| } |
| |
| return n.writeResourceState(ctx, n.Addr) |
| } |