github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/internal/initwd/version_required.go (about)

     1  package initwd
     2  
     3  import (
     4  	"fmt"
     5  
     6  	version "github.com/hashicorp/go-version"
     7  	"github.com/hashicorp/terraform/internal/earlyconfig"
     8  	"github.com/hashicorp/terraform/tfdiags"
     9  	tfversion "github.com/hashicorp/terraform/version"
    10  )
    11  
    12  // CheckCoreVersionRequirements visits each of the modules in the given
    13  // early configuration tree and verifies that any given Core version constraints
    14  // match with the version of Terraform Core that is being used.
    15  //
    16  // The returned diagnostics will contain errors if any constraints do not match.
    17  // The returned diagnostics might also return warnings, which should be
    18  // displayed to the user.
    19  func CheckCoreVersionRequirements(earlyConfig *earlyconfig.Config) tfdiags.Diagnostics {
    20  	if earlyConfig == nil {
    21  		return nil
    22  	}
    23  
    24  	var diags tfdiags.Diagnostics
    25  	module := earlyConfig.Module
    26  
    27  	var constraints version.Constraints
    28  	for _, constraintStr := range module.RequiredCore {
    29  		constraint, err := version.NewConstraint(constraintStr)
    30  		if err != nil {
    31  			// Unfortunately the early config parser doesn't preserve a source
    32  			// location for this, so we're unable to indicate a specific
    33  			// location where this constraint came from, but we can at least
    34  			// say which module set it.
    35  			switch {
    36  			case len(earlyConfig.Path) == 0:
    37  				diags = diags.Append(tfdiags.Sourceless(
    38  					tfdiags.Error,
    39  					"Invalid provider version constraint",
    40  					fmt.Sprintf("Invalid version core constraint %q in the root module.", constraintStr),
    41  				))
    42  			default:
    43  				diags = diags.Append(tfdiags.Sourceless(
    44  					tfdiags.Error,
    45  					"Invalid provider version constraint",
    46  					fmt.Sprintf("Invalid version core constraint %q in %s.", constraintStr, earlyConfig.Path),
    47  				))
    48  			}
    49  			continue
    50  		}
    51  		constraints = append(constraints, constraint...)
    52  	}
    53  
    54  	if !constraints.Check(tfversion.SemVer) {
    55  		switch {
    56  		case len(earlyConfig.Path) == 0:
    57  			diags = diags.Append(tfdiags.Sourceless(
    58  				tfdiags.Error,
    59  				"Unsupported Terraform Core version",
    60  				fmt.Sprintf(
    61  					"This configuration does not support Terraform version %s. To proceed, either choose another supported Terraform version or update the root module's version constraint. Version constraints are normally set for good reason, so updating the constraint may lead to other errors or unexpected behavior.",
    62  					tfversion.String(),
    63  				),
    64  			))
    65  		default:
    66  			diags = diags.Append(tfdiags.Sourceless(
    67  				tfdiags.Error,
    68  				"Unsupported Terraform Core version",
    69  				fmt.Sprintf(
    70  					"Module %s (from %q) does not support Terraform version %s. To proceed, either choose another supported Terraform version or update the module's version constraint. Version constraints are normally set for good reason, so updating the constraint may lead to other errors or unexpected behavior.",
    71  					earlyConfig.Path, earlyConfig.SourceAddr, tfversion.String(),
    72  				),
    73  			))
    74  		}
    75  	}
    76  
    77  	for _, c := range earlyConfig.Children {
    78  		childDiags := CheckCoreVersionRequirements(c)
    79  		diags = diags.Append(childDiags)
    80  	}
    81  
    82  	return diags
    83  }