configs/configupgrade: Upgrade the resource "lifecycle" nested block

The main tricky thing here is ignore_changes, which contains strings that
are better given as naked traversals in 0.12. We also handle here mapping
the old special case ["*"] value to the new "all" keyword.
This commit is contained in:
Martin Atkins 2018-12-04 16:57:27 -08:00
parent 4b52148262
commit ef017345f1
6 changed files with 124 additions and 14 deletions

View File

@ -0,0 +1,29 @@
resource "test_instance" "foo" {
lifecycle {
create_before_destroy = true
prevent_destroy = true
}
}
resource "test_instance" "bar" {
lifecycle {
ignore_changes = ["*"]
}
}
resource "test_instance" "baz" {
lifecycle {
ignore_changes = [
"image",
"tags.name",
]
}
}
resource "test_instance" "boop" {
lifecycle {
ignore_changes = [
"image",
]
}
}

View File

@ -0,0 +1,27 @@
resource "test_instance" "foo" {
lifecycle {
create_before_destroy = true
prevent_destroy = true
}
}
resource "test_instance" "bar" {
lifecycle {
ignore_changes = all
}
}
resource "test_instance" "baz" {
lifecycle {
ignore_changes = [
image,
tags.name,
]
}
}
resource "test_instance" "boop" {
lifecycle {
ignore_changes = [image]
}
}

View File

@ -0,0 +1,3 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -65,20 +65,7 @@ func maybeBareKeywordAttributeRule(filename string, an *analysis, specials map[s
func maybeBareTraversalAttributeRule(filename string, an *analysis) bodyItemRule { func maybeBareTraversalAttributeRule(filename string, an *analysis) bodyItemRule {
exprRule := func(val interface{}) ([]byte, tfdiags.Diagnostics) { exprRule := func(val interface{}) ([]byte, tfdiags.Diagnostics) {
// If the expression is a literal that would be valid as a naked return upgradeTraversalExpr(val, filename, an)
// absolute traversal then we'll turn it into one.
if lit, isLit := val.(*hcl1ast.LiteralType); isLit {
if lit.Token.Type == hcl1token.STRING {
trStr := lit.Token.Value().(string)
trSrc := []byte(trStr)
_, trDiags := hcl2syntax.ParseTraversalAbs(trSrc, "", hcl2.Pos{})
if !trDiags.HasErrors() {
return trSrc, nil
}
}
}
return upgradeExpr(val, filename, false, an)
} }
return attributeRule(filename, cty.String, an, exprRule) return attributeRule(filename, cty.String, an, exprRule)
} }
@ -373,3 +360,54 @@ func justAttributesBodyRules(filename string, body *hcl1ast.ObjectType, an *anal
} }
return rules return rules
} }
func lifecycleBlockBodyRules(filename string, an *analysis) bodyContentRules {
return bodyContentRules{
"create_before_destroy": noInterpAttributeRule(filename, cty.Bool, an),
"prevent_destroy": noInterpAttributeRule(filename, cty.Bool, an),
"ignore_changes": func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
val, ok := item.Val.(*hcl1ast.ListType)
if !ok {
diags = diags.Append(&hcl2.Diagnostic{
Severity: hcl2.DiagError,
Summary: "Invalid providers argument",
Detail: `The "providers" argument must be a map from provider addresses in the child module to corresponding provider addresses in this module.`,
Subject: hcl1PosRange(filename, item.Keys[0].Pos()).Ptr(),
})
return diags
}
// As a special case, we'll map the single-element list ["*"] to
// the new keyword "all".
if len(val.List) == 1 {
if lit, ok := val.List[0].(*hcl1ast.LiteralType); ok {
if lit.Token.Value() == "*" {
printAttribute(buf, item.Keys[0].Token.Value().(string), []byte("all"), item.LineComment)
return diags
}
}
}
var exprBuf bytes.Buffer
multiline := len(val.List) > 1
exprBuf.WriteByte('[')
if multiline {
exprBuf.WriteByte('\n')
}
for _, node := range val.List {
itemSrc, moreDiags := upgradeTraversalExpr(node, filename, an)
diags = diags.Append(moreDiags)
exprBuf.Write(itemSrc)
if multiline {
exprBuf.WriteString(",\n")
}
}
exprBuf.WriteByte(']')
printAttribute(buf, item.Keys[0].Token.Value().(string), exprBuf.Bytes(), item.LineComment)
return diags
},
}
}

View File

@ -392,6 +392,18 @@ Value:
return buf.Bytes(), diags return buf.Bytes(), diags
} }
func upgradeTraversalExpr(val interface{}, filename string, an *analysis) ([]byte, tfdiags.Diagnostics) {
if lit, ok := val.(*hcl1ast.LiteralType); ok && lit.Token.Type == hcl1token.STRING {
trStr := lit.Token.Value().(string)
trSrc := []byte(trStr)
_, trDiags := hcl2syntax.ParseTraversalAbs(trSrc, "", hcl2.Pos{})
if !trDiags.HasErrors() {
return trSrc, nil
}
}
return upgradeExpr(val, filename, false, an)
}
var hilArithmeticOpSyms = map[hilast.ArithmeticOp]string{ var hilArithmeticOpSyms = map[hilast.ArithmeticOp]string{
hilast.ArithmeticOpAdd: " + ", hilast.ArithmeticOpAdd: " + ",
hilast.ArithmeticOpSub: " - ", hilast.ArithmeticOpSub: " - ",

View File

@ -327,6 +327,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["provider"] = maybeBareTraversalAttributeRule(filename, an) rules["provider"] = maybeBareTraversalAttributeRule(filename, an)
rules["lifecycle"] = nestedBlockRule(filename, lifecycleBlockBodyRules(filename, an), an, adhocComments)
printComments(buf, item.LeadComment) printComments(buf, item.LeadComment)
printBlockOpen(buf, blockType, labels, item.LineComment) printBlockOpen(buf, blockType, labels, item.LineComment)