configs/configupgrade: Upgrade depends_on in resources and outputs
This commit is contained in:
parent
ef017345f1
commit
028b5ba34e
|
@ -0,0 +1,17 @@
|
||||||
|
resource "test_instance" "foo" {
|
||||||
|
depends_on = [
|
||||||
|
"test_instance.bar",
|
||||||
|
"test_instance.bar.0",
|
||||||
|
"test_instance.bar.*",
|
||||||
|
"test_instance.bar.invalid",
|
||||||
|
"data.test_instance.baz",
|
||||||
|
"data.test_instance.baz.invalid",
|
||||||
|
"module.foo.bar",
|
||||||
|
"module.foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
output "foo" {
|
||||||
|
value = "a"
|
||||||
|
depends_on = ["test_instance.foo"]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
resource "test_instance" "foo" {
|
||||||
|
depends_on = [
|
||||||
|
test_instance.bar,
|
||||||
|
test_instance.bar[0],
|
||||||
|
test_instance.bar,
|
||||||
|
test_instance.bar,
|
||||||
|
data.test_instance.baz,
|
||||||
|
data.test_instance.baz,
|
||||||
|
module.foo.bar,
|
||||||
|
module.foo,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
output "foo" {
|
||||||
|
value = "a"
|
||||||
|
depends_on = [test_instance.foo]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.12"
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package configupgrade
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
hcl1ast "github.com/hashicorp/hcl/hcl/ast"
|
hcl1ast "github.com/hashicorp/hcl/hcl/ast"
|
||||||
hcl1token "github.com/hashicorp/hcl/hcl/token"
|
hcl1token "github.com/hashicorp/hcl/hcl/token"
|
||||||
|
@ -71,13 +73,84 @@ func maybeBareTraversalAttributeRule(filename string, an *analysis) bodyItemRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func dependsOnAttributeRule(filename string, an *analysis) bodyItemRule {
|
func dependsOnAttributeRule(filename string, an *analysis) bodyItemRule {
|
||||||
// FIXME: Should dig into the individual list items here and try to unwrap
|
return func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
|
||||||
// them as naked references, as well as upgrading any legacy-style index
|
var diags tfdiags.Diagnostics
|
||||||
// references like aws_instance.foo.0 to be aws_instance.foo[0] instead.
|
val, ok := item.Val.(*hcl1ast.ListType)
|
||||||
exprRule := func(val interface{}) ([]byte, tfdiags.Diagnostics) {
|
if !ok {
|
||||||
return upgradeExpr(val, filename, false, an)
|
diags = diags.Append(&hcl2.Diagnostic{
|
||||||
|
Severity: hcl2.DiagError,
|
||||||
|
Summary: "Invalid depends_on argument",
|
||||||
|
Detail: `The "depends_on" argument must be a list of strings containing references to resources and modules.`,
|
||||||
|
Subject: hcl1PosRange(filename, item.Keys[0].Pos()).Ptr(),
|
||||||
|
})
|
||||||
|
return diags
|
||||||
|
}
|
||||||
|
|
||||||
|
var exprBuf bytes.Buffer
|
||||||
|
multiline := len(val.List) > 1
|
||||||
|
exprBuf.WriteByte('[')
|
||||||
|
if multiline {
|
||||||
|
exprBuf.WriteByte('\n')
|
||||||
|
}
|
||||||
|
for _, node := range val.List {
|
||||||
|
lit, ok := node.(*hcl1ast.LiteralType)
|
||||||
|
if (!ok) || lit.Token.Type != hcl1token.STRING {
|
||||||
|
diags = diags.Append(&hcl2.Diagnostic{
|
||||||
|
Severity: hcl2.DiagError,
|
||||||
|
Summary: "Invalid depends_on argument",
|
||||||
|
Detail: `The "depends_on" argument must be a list of strings containing references to resources and modules.`,
|
||||||
|
Subject: hcl1PosRange(filename, item.Keys[0].Pos()).Ptr(),
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
refStr := lit.Token.Value().(string)
|
||||||
|
if refStr == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
refParts := strings.Split(refStr, ".")
|
||||||
|
var maxNames int
|
||||||
|
switch refParts[0] {
|
||||||
|
case "data", "module":
|
||||||
|
maxNames = 3
|
||||||
|
default: // resource references
|
||||||
|
maxNames = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
exprBuf.WriteString(refParts[0])
|
||||||
|
for i, part := range refParts[1:] {
|
||||||
|
if part == "*" {
|
||||||
|
// We used to allow test_instance.foo.* as a reference
|
||||||
|
// but now that's expressed instead as test_instance.foo,
|
||||||
|
// referring to the tuple of instances. This also
|
||||||
|
// always marks the end of the reference part of the
|
||||||
|
// traversal, so anything after this would be resource
|
||||||
|
// attributes that don't belong on depends_on.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if i, err := strconv.Atoi(part); err == nil {
|
||||||
|
fmt.Fprintf(&exprBuf, "[%d]", i)
|
||||||
|
// An index always marks the end of the reference part.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (i + 1) >= maxNames {
|
||||||
|
// We've reached the end of the reference part, so anything
|
||||||
|
// after this would be invalid in 0.12.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
exprBuf.WriteByte('.')
|
||||||
|
exprBuf.WriteString(part)
|
||||||
|
}
|
||||||
|
|
||||||
|
if multiline {
|
||||||
|
exprBuf.WriteString(",\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exprBuf.WriteByte(']')
|
||||||
|
|
||||||
|
printAttribute(buf, item.Keys[0].Token.Value().(string), exprBuf.Bytes(), item.LineComment)
|
||||||
|
|
||||||
|
return diags
|
||||||
}
|
}
|
||||||
return attributeRule(filename, cty.List(cty.String), an, exprRule)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func attributeRule(filename string, wantTy cty.Type, an *analysis, upgradeExpr func(val interface{}) ([]byte, tfdiags.Diagnostics)) bodyItemRule {
|
func attributeRule(filename string, wantTy cty.Type, an *analysis, upgradeExpr func(val interface{}) ([]byte, tfdiags.Diagnostics)) bodyItemRule {
|
||||||
|
|
|
@ -326,6 +326,7 @@ func (u *Upgrader) upgradeNativeSyntaxResource(filename string, buf *bytes.Buffe
|
||||||
|
|
||||||
rules := schemaDefaultBodyRules(filename, schema, an, adhocComments)
|
rules := schemaDefaultBodyRules(filename, schema, an, adhocComments)
|
||||||
rules["count"] = normalAttributeRule(filename, cty.Number, an)
|
rules["count"] = normalAttributeRule(filename, cty.Number, an)
|
||||||
|
rules["depends_on"] = dependsOnAttributeRule(filename, an)
|
||||||
rules["provider"] = maybeBareTraversalAttributeRule(filename, an)
|
rules["provider"] = maybeBareTraversalAttributeRule(filename, an)
|
||||||
rules["lifecycle"] = nestedBlockRule(filename, lifecycleBlockBodyRules(filename, an), an, adhocComments)
|
rules["lifecycle"] = nestedBlockRule(filename, lifecycleBlockBodyRules(filename, an), an, adhocComments)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue