// Copyright (c) The OpenTofu Authors // SPDX-License-Identifier: MPL-2.0 // Copyright (c) 2023 HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package tofu import ( "github.com/opentofu/opentofu/internal/addrs" "github.com/opentofu/opentofu/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 ( _ 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 { refs := n.NodeAbstractResource.References() // The expand node needs to connect to the individual resource instances it // references, but cannot refer to it's own instances without causing // cycles. It would be preferable to entirely disallow self references // without the `self` identifier, but those were allowed in provisioners // for compatibility with legacy configuration. We also can't always just // filter them out for all resource node types, because the only method we // have for catching certain invalid configurations are the cycles that // result from these inter-instance references. return filterSelfRefs(n.Addr.Resource, refs) } func (n *nodeExpandApplyableResource) Name() string { return n.NodeAbstractResource.Name() + " (expand)" } func (n *nodeExpandApplyableResource) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { var diags tfdiags.Diagnostics expander := ctx.InstanceExpander() moduleInstances := expander.ExpandModule(n.Addr.Module) for _, module := range moduleInstances { ctx = ctx.WithPath(module) diags = diags.Append(n.writeResourceState(ctx, n.Addr.Resource.Absolute(module))) } return diags }