Skip to content

Commit

Permalink
backport of commit 012cdb5
Browse files Browse the repository at this point in the history
  • Loading branch information
apparentlymart committed Feb 26, 2021
1 parent cb9fc9e commit 06c426f
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 5 deletions.
44 changes: 44 additions & 0 deletions configs/experiments.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/experiments"
"github.com/hashicorp/terraform/version"
"github.com/zclconf/go-cty/cty"
)

Expand All @@ -25,6 +26,49 @@ func sniffActiveExperiments(body hcl.Body) (experiments.Set, hcl.Diagnostics) {
content, _, blockDiags := block.Body.PartialContent(configFileExperimentsSniffBlockSchema)
diags = append(diags, blockDiags...)

if attr, exists := content.Attributes["language"]; exists {
// We don't yet have a sense of selecting an edition of the
// language, but we're reserving this syntax for now so that
// if and when we do this later older versions of Terraform
// will emit a more helpful error message than just saying
// this attribute doesn't exist. Handling this as part of
// experiments is a bit odd for now but justified by the
// fact that a future fuller implementation of switchable
// languages would be likely use a similar implementation
// strategy as experiments, and thus would lead to this
// function being refactored to deal with both concerns at
// once. We'll see, though!
kw := hcl.ExprAsKeyword(attr.Expr)
currentVersion := version.SemVer.String()
const firstEdition = "TF2021"
switch {
case kw == "": // (the expression wasn't a keyword at all)
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid language edition",
Detail: fmt.Sprintf(
"The language argument expects a bare language edition keyword. Terraform %s supports only language edition %s, which is the default.",
currentVersion, firstEdition,
),
Subject: attr.Expr.Range().Ptr(),
})
case kw != firstEdition:
rel := "different"
if kw > firstEdition { // would be weird for this not to be true, but it's user input so anything goes
rel = "newer"
}
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Unsupported language edition",
Detail: fmt.Sprintf(
"Terraform v%s only supports language edition %s. This module requires a %s version of Terraform CLI.",
currentVersion, firstEdition, rel,
),
Subject: attr.Expr.Range().Ptr(),
})
}
}

attr, exists := content.Attributes["experiments"]
if !exists {
continue
Expand Down
10 changes: 5 additions & 5 deletions configs/parser_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ func (p *Parser) loadConfigFile(path string, override bool) (*File, hcl.Diagnost
content, contentDiags := block.Body.Content(terraformBlockSchema)
diags = append(diags, contentDiags...)

// We ignore the "terraform_version" and "experiments" attributes
// here because sniffCoreVersionRequirements and
// We ignore the "terraform_version", "language" and "experiments"
// attributes here because sniffCoreVersionRequirements and
// sniffActiveExperiments already dealt with those above.

for _, innerBlock := range content.Blocks {
Expand Down Expand Up @@ -244,6 +244,7 @@ var terraformBlockSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{Name: "required_version"},
{Name: "experiments"},
{Name: "language"},
},
Blocks: []hcl.BlockHeaderSchema{
{
Expand Down Expand Up @@ -283,8 +284,7 @@ var configFileVersionSniffBlockSchema = &hcl.BodySchema{
// to decode a single attribute from inside a "terraform" block.
var configFileExperimentsSniffBlockSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "experiments",
},
{Name: "experiments"},
{Name: "language"},
},
}
4 changes: 4 additions & 0 deletions configs/testdata/error-files/invalid_language_edition.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
terraform {
# The language argument expects a bare keyword, not a string.
language = "TF2021" # ERROR: Invalid language edition
}
6 changes: 6 additions & 0 deletions configs/testdata/error-files/unsupported_language_edition.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
terraform {
# If a future change in this repository happens to make TF2038 a valid
# edition then this will start failing; in that case, change this file to
# select a different edition that isn't supported.
language = TF2038 # ERROR: Unsupported language edition
}
8 changes: 8 additions & 0 deletions configs/testdata/valid-files/valid-language-edition.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
# If we drop support for TF2021 in a future Terraform release then this
# test will fail. In that case, update this to a newer edition that is
# still supported, because the purpose of this test is to verify that
# we can successfully decode the language argument, not specifically
# that we support TF2021.
language = TF2021
}

0 comments on commit 06c426f

Please sign in to comment.