github.com/pulumi/terraform@v1.4.0/pkg/terraform/context_validate.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/pulumi/terraform/pkg/addrs"
     7  	"github.com/pulumi/terraform/pkg/configs"
     8  	"github.com/pulumi/terraform/pkg/states"
     9  	"github.com/pulumi/terraform/pkg/tfdiags"
    10  	"github.com/zclconf/go-cty/cty"
    11  )
    12  
    13  // Validate performs semantic validation of a configuration, and returns
    14  // any warnings or errors.
    15  //
    16  // Syntax and structural checks are performed by the configuration loader,
    17  // and so are not repeated here.
    18  //
    19  // Validate considers only the configuration and so it won't catch any
    20  // errors caused by current values in the state, or other external information
    21  // such as root module input variables. However, the Plan function includes
    22  // all of the same checks as Validate, in addition to the other work it does
    23  // to consider the previous run state and the planning options.
    24  func (c *Context) Validate(config *configs.Config) tfdiags.Diagnostics {
    25  	defer c.acquireRun("validate")()
    26  
    27  	var diags tfdiags.Diagnostics
    28  
    29  	moreDiags := c.checkConfigDependencies(config)
    30  	diags = diags.Append(moreDiags)
    31  	// If required dependencies are not available then we'll bail early since
    32  	// otherwise we're likely to just see a bunch of other errors related to
    33  	// incompatibilities, which could be overwhelming for the user.
    34  	if diags.HasErrors() {
    35  		return diags
    36  	}
    37  
    38  	log.Printf("[DEBUG] Building and walking validate graph")
    39  
    40  	// Validate is to check if the given module is valid regardless of
    41  	// input values, current state, etc. Therefore we populate all of the
    42  	// input values with unknown values of the expected type, allowing us
    43  	// to perform a type check without assuming any particular values.
    44  	varValues := make(InputValues)
    45  	for name, variable := range config.Module.Variables {
    46  		ty := variable.Type
    47  		if ty == cty.NilType {
    48  			// Can't predict the type at all, so we'll just mark it as
    49  			// cty.DynamicVal (unknown value of cty.DynamicPseudoType).
    50  			ty = cty.DynamicPseudoType
    51  		}
    52  		varValues[name] = &InputValue{
    53  			Value:      cty.UnknownVal(ty),
    54  			SourceType: ValueFromUnknown,
    55  		}
    56  	}
    57  
    58  	graph, moreDiags := (&PlanGraphBuilder{
    59  		Config:             config,
    60  		Plugins:            c.plugins,
    61  		State:              states.NewState(),
    62  		RootVariableValues: varValues,
    63  		Operation:          walkValidate,
    64  	}).Build(addrs.RootModuleInstance)
    65  	diags = diags.Append(moreDiags)
    66  	if moreDiags.HasErrors() {
    67  		return diags
    68  	}
    69  
    70  	walker, walkDiags := c.walk(graph, walkValidate, &graphWalkOpts{
    71  		Config: config,
    72  	})
    73  	diags = diags.Append(walker.NonFatalDiagnostics)
    74  	diags = diags.Append(walkDiags)
    75  	if walkDiags.HasErrors() {
    76  		return diags
    77  	}
    78  
    79  	return diags
    80  }