mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
39e609d5fd
Previously we were using the experimental HCL 2 repository, but now we'll shift over to the v2 import path within the main HCL repository as part of actually releasing HCL 2.0 as stable. This is a mechanical search/replace to the new import paths. It also switches to the v2.0.0 release of HCL, which includes some new code that Terraform didn't previously have but should not change any behavior that matters for Terraform's purposes. For the moment the experimental HCL2 repository is still an indirect dependency via terraform-config-inspect, so it remains in our go.sum and vendor directories for the moment. Because terraform-config-inspect uses a much smaller subset of the HCL2 functionality, this does still manage to prune the vendor directory a little. A subsequent release of terraform-config-inspect should allow us to completely remove that old repository in a future commit.
117 lines
4.8 KiB
Go
117 lines
4.8 KiB
Go
package configs
|
|
|
|
import (
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Functions in this file are compatibility shims intended to ease conversion
|
|
// from the old configuration loader. Any use of these functions that makes
|
|
// a change should generate a deprecation warning explaining to the user how
|
|
// to update their code for new patterns.
|
|
//
|
|
// Shims are particularly important for any patterns that have been widely
|
|
// documented in books, tutorials, etc. Users will still be starting from
|
|
// these examples and we want to help them adopt the latest patterns rather
|
|
// than leave them stranded.
|
|
// -------------------------------------------------------------------------
|
|
|
|
// shimTraversalInString takes any arbitrary expression and checks if it is
|
|
// a quoted string in the native syntax. If it _is_, then it is parsed as a
|
|
// traversal and re-wrapped into a synthetic traversal expression and a
|
|
// warning is generated. Otherwise, the given expression is just returned
|
|
// verbatim.
|
|
//
|
|
// This function has no effect on expressions from the JSON syntax, since
|
|
// traversals in strings are the required pattern in that syntax.
|
|
//
|
|
// If wantKeyword is set, the generated warning diagnostic will talk about
|
|
// keywords rather than references. The behavior is otherwise unchanged, and
|
|
// the caller remains responsible for checking that the result is indeed
|
|
// a keyword, e.g. using hcl.ExprAsKeyword.
|
|
func shimTraversalInString(expr hcl.Expression, wantKeyword bool) (hcl.Expression, hcl.Diagnostics) {
|
|
// ObjectConsKeyExpr is a special wrapper type used for keys on object
|
|
// constructors to deal with the fact that naked identifiers are normally
|
|
// handled as "bareword" strings rather than as variable references. Since
|
|
// we know we're interpreting as a traversal anyway (and thus it won't
|
|
// matter whether it's a string or an identifier) we can safely just unwrap
|
|
// here and then process whatever we find inside as normal.
|
|
if ocke, ok := expr.(*hclsyntax.ObjectConsKeyExpr); ok {
|
|
expr = ocke.Wrapped
|
|
}
|
|
|
|
if !exprIsNativeQuotedString(expr) {
|
|
return expr, nil
|
|
}
|
|
|
|
strVal, diags := expr.Value(nil)
|
|
if diags.HasErrors() || strVal.IsNull() || !strVal.IsKnown() {
|
|
// Since we're not even able to attempt a shim here, we'll discard
|
|
// the diagnostics we saw so far and let the caller's own error
|
|
// handling take care of reporting the invalid expression.
|
|
return expr, nil
|
|
}
|
|
|
|
// The position handling here isn't _quite_ right because it won't
|
|
// take into account any escape sequences in the literal string, but
|
|
// it should be close enough for any error reporting to make sense.
|
|
srcRange := expr.Range()
|
|
startPos := srcRange.Start // copy
|
|
startPos.Column++ // skip initial quote
|
|
startPos.Byte++ // skip initial quote
|
|
|
|
traversal, tDiags := hclsyntax.ParseTraversalAbs(
|
|
[]byte(strVal.AsString()),
|
|
srcRange.Filename,
|
|
startPos,
|
|
)
|
|
diags = append(diags, tDiags...)
|
|
|
|
// For initial release our deprecation warnings are disabled to allow
|
|
// a period where modules can be compatible with both old and new
|
|
// conventions.
|
|
// FIXME: Re-enable these deprecation warnings in a release prior to
|
|
// Terraform 0.13 and then remove the shims altogether for 0.13.
|
|
/*
|
|
if wantKeyword {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagWarning,
|
|
Summary: "Quoted keywords are deprecated",
|
|
Detail: "In this context, keywords are expected literally rather than in quotes. Previous versions of Terraform required quotes, but that usage is now deprecated. Remove the quotes surrounding this keyword to silence this warning.",
|
|
Subject: &srcRange,
|
|
})
|
|
} else {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagWarning,
|
|
Summary: "Quoted references are deprecated",
|
|
Detail: "In this context, references are expected literally rather than in quotes. Previous versions of Terraform required quotes, but that usage is now deprecated. Remove the quotes surrounding this reference to silence this warning.",
|
|
Subject: &srcRange,
|
|
})
|
|
}
|
|
*/
|
|
|
|
return &hclsyntax.ScopeTraversalExpr{
|
|
Traversal: traversal,
|
|
SrcRange: srcRange,
|
|
}, diags
|
|
}
|
|
|
|
// shimIsIgnoreChangesStar returns true if the given expression seems to be
|
|
// a string literal whose value is "*". This is used to support a legacy
|
|
// form of ignore_changes = all .
|
|
//
|
|
// This function does not itself emit any diagnostics, so it's the caller's
|
|
// responsibility to emit a warning diagnostic when this function returns true.
|
|
func shimIsIgnoreChangesStar(expr hcl.Expression) bool {
|
|
val, valDiags := expr.Value(nil)
|
|
if valDiags.HasErrors() {
|
|
return false
|
|
}
|
|
if val.Type() != cty.String || val.IsNull() || !val.IsKnown() {
|
|
return false
|
|
}
|
|
return val.AsString() == "*"
|
|
}
|