Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configs: Accept and minimally validate a "language" argument #27941

Merged
merged 1 commit into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
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
}