github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/node_root_variable.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/terraform/internal/addrs"
     7  	"github.com/hashicorp/terraform/internal/configs"
     8  	"github.com/hashicorp/terraform/internal/dag"
     9  	"github.com/hashicorp/terraform/internal/tfdiags"
    10  	"github.com/zclconf/go-cty/cty"
    11  )
    12  
    13  // NodeRootVariable represents a root variable input.
    14  type NodeRootVariable struct {
    15  	Addr   addrs.InputVariable
    16  	Config *configs.Variable
    17  
    18  	// RawValue is the value for the variable set from outside Terraform
    19  	// Core, such as on the command line, or from an environment variable,
    20  	// or similar. This is the raw value that was provided, not yet
    21  	// converted or validated, and can be nil for a variable that isn't
    22  	// set at all.
    23  	RawValue *InputValue
    24  }
    25  
    26  var (
    27  	_ GraphNodeModuleInstance = (*NodeRootVariable)(nil)
    28  	_ GraphNodeReferenceable  = (*NodeRootVariable)(nil)
    29  )
    30  
    31  func (n *NodeRootVariable) Name() string {
    32  	return n.Addr.String()
    33  }
    34  
    35  // GraphNodeModuleInstance
    36  func (n *NodeRootVariable) Path() addrs.ModuleInstance {
    37  	return addrs.RootModuleInstance
    38  }
    39  
    40  func (n *NodeRootVariable) ModulePath() addrs.Module {
    41  	return addrs.RootModule
    42  }
    43  
    44  // GraphNodeReferenceable
    45  func (n *NodeRootVariable) ReferenceableAddrs() []addrs.Referenceable {
    46  	return []addrs.Referenceable{n.Addr}
    47  }
    48  
    49  // GraphNodeExecutable
    50  func (n *NodeRootVariable) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
    51  	// Root module variables are special in that they are provided directly
    52  	// by the caller (usually, the CLI layer) and so we don't really need to
    53  	// evaluate them in the usual sense, but we do need to process the raw
    54  	// values given by the caller to match what the module is expecting, and
    55  	// make sure the values are valid.
    56  	var diags tfdiags.Diagnostics
    57  
    58  	addr := addrs.RootModuleInstance.InputVariable(n.Addr.Name)
    59  	log.Printf("[TRACE] NodeRootVariable: evaluating %s", addr)
    60  
    61  	if n.Config == nil {
    62  		// Because we build NodeRootVariable from configuration in the normal
    63  		// case it's strange to get here, but we tolerate it to allow for
    64  		// tests that might not populate the inputs fully.
    65  		return nil
    66  	}
    67  
    68  	givenVal := n.RawValue
    69  	if givenVal == nil {
    70  		// We'll use cty.NilVal to represent the variable not being set at
    71  		// all, which for historical reasons is unfortunately different than
    72  		// explicitly setting it to null in some cases. In normal code we
    73  		// should never get here because all variables should have raw
    74  		// values, but we can get here in some historical tests that call
    75  		// in directly and don't necessarily obey the rules.
    76  		givenVal = &InputValue{
    77  			Value:      cty.NilVal,
    78  			SourceType: ValueFromUnknown,
    79  		}
    80  	}
    81  
    82  	finalVal, moreDiags := prepareFinalInputVariableValue(
    83  		addr,
    84  		givenVal,
    85  		n.Config,
    86  	)
    87  	diags = diags.Append(moreDiags)
    88  	if moreDiags.HasErrors() {
    89  		// No point in proceeding to validations then, because they'll
    90  		// probably fail trying to work with a value of the wrong type.
    91  		return diags
    92  	}
    93  
    94  	ctx.SetRootModuleArgument(addr.Variable, finalVal)
    95  
    96  	moreDiags = evalVariableValidations(
    97  		addrs.RootModuleInstance.InputVariable(n.Addr.Name),
    98  		n.Config,
    99  		nil, // not set for root module variables
   100  		ctx,
   101  	)
   102  	diags = diags.Append(moreDiags)
   103  	return diags
   104  }
   105  
   106  // dag.GraphNodeDotter impl.
   107  func (n *NodeRootVariable) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
   108  	return &dag.DotNode{
   109  		Name: name,
   110  		Attrs: map[string]string{
   111  			"label": n.Name(),
   112  			"shape": "note",
   113  		},
   114  	}
   115  }