github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/node_local.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/hcl/v2"
     8  	"github.com/muratcelep/terraform/not-internal/addrs"
     9  	"github.com/muratcelep/terraform/not-internal/configs"
    10  	"github.com/muratcelep/terraform/not-internal/dag"
    11  	"github.com/muratcelep/terraform/not-internal/lang"
    12  	"github.com/muratcelep/terraform/not-internal/tfdiags"
    13  	"github.com/zclconf/go-cty/cty"
    14  )
    15  
    16  // nodeExpandLocal represents a named local value in a configuration module,
    17  // which has not yet been expanded.
    18  type nodeExpandLocal struct {
    19  	Addr   addrs.LocalValue
    20  	Module addrs.Module
    21  	Config *configs.Local
    22  }
    23  
    24  var (
    25  	_ GraphNodeReferenceable     = (*nodeExpandLocal)(nil)
    26  	_ GraphNodeReferencer        = (*nodeExpandLocal)(nil)
    27  	_ GraphNodeDynamicExpandable = (*nodeExpandLocal)(nil)
    28  	_ graphNodeTemporaryValue    = (*nodeExpandLocal)(nil)
    29  	_ graphNodeExpandsInstances  = (*nodeExpandLocal)(nil)
    30  )
    31  
    32  func (n *nodeExpandLocal) expandsInstances() {}
    33  
    34  // graphNodeTemporaryValue
    35  func (n *nodeExpandLocal) temporaryValue() bool {
    36  	return true
    37  }
    38  
    39  func (n *nodeExpandLocal) Name() string {
    40  	path := n.Module.String()
    41  	addr := n.Addr.String() + " (expand)"
    42  
    43  	if path != "" {
    44  		return path + "." + addr
    45  	}
    46  	return addr
    47  }
    48  
    49  // GraphNodeModulePath
    50  func (n *nodeExpandLocal) ModulePath() addrs.Module {
    51  	return n.Module
    52  }
    53  
    54  // GraphNodeReferenceable
    55  func (n *nodeExpandLocal) ReferenceableAddrs() []addrs.Referenceable {
    56  	return []addrs.Referenceable{n.Addr}
    57  }
    58  
    59  // GraphNodeReferencer
    60  func (n *nodeExpandLocal) References() []*addrs.Reference {
    61  	refs, _ := lang.ReferencesInExpr(n.Config.Expr)
    62  	return refs
    63  }
    64  
    65  func (n *nodeExpandLocal) DynamicExpand(ctx EvalContext) (*Graph, error) {
    66  	var g Graph
    67  	expander := ctx.InstanceExpander()
    68  	for _, module := range expander.ExpandModule(n.Module) {
    69  		o := &NodeLocal{
    70  			Addr:   n.Addr.Absolute(module),
    71  			Config: n.Config,
    72  		}
    73  		log.Printf("[TRACE] Expanding local: adding %s as %T", o.Addr.String(), o)
    74  		g.Add(o)
    75  	}
    76  	return &g, nil
    77  }
    78  
    79  // NodeLocal represents a named local value in a particular module.
    80  //
    81  // Local value nodes only have one operation, common to all walk types:
    82  // evaluate the result and place it in state.
    83  type NodeLocal struct {
    84  	Addr   addrs.AbsLocalValue
    85  	Config *configs.Local
    86  }
    87  
    88  var (
    89  	_ GraphNodeModuleInstance = (*NodeLocal)(nil)
    90  	_ GraphNodeReferenceable  = (*NodeLocal)(nil)
    91  	_ GraphNodeReferencer     = (*NodeLocal)(nil)
    92  	_ GraphNodeExecutable     = (*NodeLocal)(nil)
    93  	_ graphNodeTemporaryValue = (*NodeLocal)(nil)
    94  	_ dag.GraphNodeDotter     = (*NodeLocal)(nil)
    95  )
    96  
    97  // graphNodeTemporaryValue
    98  func (n *NodeLocal) temporaryValue() bool {
    99  	return true
   100  }
   101  
   102  func (n *NodeLocal) Name() string {
   103  	return n.Addr.String()
   104  }
   105  
   106  // GraphNodeModuleInstance
   107  func (n *NodeLocal) Path() addrs.ModuleInstance {
   108  	return n.Addr.Module
   109  }
   110  
   111  // GraphNodeModulePath
   112  func (n *NodeLocal) ModulePath() addrs.Module {
   113  	return n.Addr.Module.Module()
   114  }
   115  
   116  // GraphNodeReferenceable
   117  func (n *NodeLocal) ReferenceableAddrs() []addrs.Referenceable {
   118  	return []addrs.Referenceable{n.Addr.LocalValue}
   119  }
   120  
   121  // GraphNodeReferencer
   122  func (n *NodeLocal) References() []*addrs.Reference {
   123  	refs, _ := lang.ReferencesInExpr(n.Config.Expr)
   124  	return refs
   125  }
   126  
   127  // GraphNodeExecutable
   128  // NodeLocal.Execute is an Execute implementation that evaluates the
   129  // expression for a local value and writes it into a transient part of
   130  // the state.
   131  func (n *NodeLocal) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
   132  	expr := n.Config.Expr
   133  	addr := n.Addr.LocalValue
   134  
   135  	// We ignore diags here because any problems we might find will be found
   136  	// again in EvaluateExpr below.
   137  	refs, _ := lang.ReferencesInExpr(expr)
   138  	for _, ref := range refs {
   139  		if ref.Subject == addr {
   140  			diags = diags.Append(&hcl.Diagnostic{
   141  				Severity: hcl.DiagError,
   142  				Summary:  "Self-referencing local value",
   143  				Detail:   fmt.Sprintf("Local value %s cannot use its own result as part of its expression.", addr),
   144  				Subject:  ref.SourceRange.ToHCL().Ptr(),
   145  				Context:  expr.Range().Ptr(),
   146  			})
   147  		}
   148  	}
   149  	if diags.HasErrors() {
   150  		return diags
   151  	}
   152  
   153  	val, moreDiags := ctx.EvaluateExpr(expr, cty.DynamicPseudoType, nil)
   154  	diags = diags.Append(moreDiags)
   155  	if moreDiags.HasErrors() {
   156  		return diags
   157  	}
   158  
   159  	state := ctx.State()
   160  	if state == nil {
   161  		diags = diags.Append(fmt.Errorf("cannot write local value to nil state"))
   162  		return diags
   163  	}
   164  
   165  	state.SetLocalValue(addr.Absolute(ctx.Path()), val)
   166  
   167  	return diags
   168  }
   169  
   170  // dag.GraphNodeDotter impl.
   171  func (n *NodeLocal) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
   172  	return &dag.DotNode{
   173  		Name: name,
   174  		Attrs: map[string]string{
   175  			"label": n.Name(),
   176  			"shape": "note",
   177  		},
   178  	}
   179  }