configs/configupgrade: Upgrade the bodies of "provisioner" blocks
Aside from the two special meta-arguments "connection" and "provisioner" this is just our standard mapping from schema to conversion rules, using the provisioner's configuration schema.
This commit is contained in:
parent
cdca8fbfe8
commit
e2ef51800a
|
@ -3,7 +3,7 @@ resource "test_instance" "example" {
|
|||
connection {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
provisioner "test" {
|
||||
connection {
|
||||
host = "127.0.0.2"
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ resource "test_instance" "example" {
|
|||
connection {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
provisioner "test" {
|
||||
connection {
|
||||
host = "127.0.0.2"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
resource "test_instance" "foo" {
|
||||
provisioner "test" {
|
||||
commands = "${list("a", "b", "c")}"
|
||||
|
||||
when = "create"
|
||||
on_failure = "fail"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
resource "test_instance" "foo" {
|
||||
provisioner "test" {
|
||||
commands = ["a", "b", "c"]
|
||||
|
||||
when = create
|
||||
on_failure = fail
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
terraform {
|
||||
required_version = ">= 0.12"
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
hcl1ast "github.com/hashicorp/hcl/hcl/ast"
|
||||
hcl1printer "github.com/hashicorp/hcl/hcl/printer"
|
||||
hcl1token "github.com/hashicorp/hcl/hcl/token"
|
||||
hcl2 "github.com/hashicorp/hcl2/hcl"
|
||||
hcl2syntax "github.com/hashicorp/hcl2/hcl/hclsyntax"
|
||||
|
@ -554,3 +555,69 @@ func lifecycleBlockBodyRules(filename string, an *analysis) bodyContentRules {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func provisionerBlockRule(filename string, an *analysis, adhocComments *commentQueue) bodyItemRule {
|
||||
// Unlike some other examples above, this is a rule for the entire
|
||||
// provisioner block, rather than just for its contents. Therefore it must
|
||||
// also produce the block header and body delimiters.
|
||||
return func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
body := item.Val.(*hcl1ast.ObjectType)
|
||||
declRange := hcl1PosRange(filename, item.Keys[0].Pos())
|
||||
|
||||
if len(item.Keys) < 2 {
|
||||
diags = diags.Append(&hcl2.Diagnostic{
|
||||
Severity: hcl2.DiagError,
|
||||
Summary: "Invalid provisioner block",
|
||||
Detail: "A provisioner block must have one label: the provisioner type.",
|
||||
Subject: &declRange,
|
||||
})
|
||||
return diags
|
||||
}
|
||||
|
||||
typeName := item.Keys[1].Token.Value().(string)
|
||||
schema := an.ProvisionerSchemas[typeName]
|
||||
if schema == nil {
|
||||
// This message is assuming that if the user _is_ using a third-party
|
||||
// provisioner plugin they already know how to install it for normal
|
||||
// use and so we don't need to spell out those instructions in detail
|
||||
// here.
|
||||
diags = diags.Append(&hcl2.Diagnostic{
|
||||
Severity: hcl2.DiagError,
|
||||
Summary: "Unknown provisioner type",
|
||||
Detail: fmt.Sprintf("The provisioner type %q is not supported. If this is a third-party plugin, make sure its plugin executable is available in one of the usual plugin search paths.", typeName),
|
||||
Subject: &declRange,
|
||||
})
|
||||
return diags
|
||||
}
|
||||
|
||||
rules := schemaDefaultBodyRules(filename, schema, an, adhocComments)
|
||||
rules["when"] = maybeBareTraversalAttributeRule(filename, an)
|
||||
rules["on_failure"] = maybeBareTraversalAttributeRule(filename, an)
|
||||
rules["connection"] = connectionBlockRule(filename, an, adhocComments)
|
||||
|
||||
printComments(buf, item.LeadComment)
|
||||
printBlockOpen(buf, "provisioner", []string{typeName}, item.LineComment)
|
||||
bodyDiags := upgradeBlockBody(filename, fmt.Sprintf("%s.provisioner[%q]", blockAddr, typeName), buf, body.List.Items, body.Rbrace, rules, adhocComments)
|
||||
diags = diags.Append(bodyDiags)
|
||||
buf.WriteString("}\n")
|
||||
|
||||
return diags
|
||||
}
|
||||
}
|
||||
|
||||
func connectionBlockRule(filename string, an *analysis, adhocComments *commentQueue) bodyItemRule {
|
||||
// Unlike some other examples above, this is a rule for the entire
|
||||
// connection block, rather than just for its contents. Therefore it must
|
||||
// also produce the block header and body delimiters.
|
||||
return func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
|
||||
// TODO: For the few resource types that were setting ConnInfo in
|
||||
// state after create/update in prior versions, generate the additional
|
||||
// explicit connection settings that are now required if and only if
|
||||
// there's at least one provisioner block.
|
||||
// For now, we just pass this through as-is.
|
||||
hcl1printer.Fprint(buf, item)
|
||||
buf.WriteByte('\n')
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,24 +329,8 @@ func (u *Upgrader) upgradeNativeSyntaxResource(filename string, buf *bytes.Buffe
|
|||
rules["depends_on"] = dependsOnAttributeRule(filename, an)
|
||||
rules["provider"] = maybeBareTraversalAttributeRule(filename, an)
|
||||
rules["lifecycle"] = nestedBlockRule(filename, lifecycleBlockBodyRules(filename, an), an, adhocComments)
|
||||
rules["connection"] = func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
|
||||
// TODO: For the few resource types that were setting ConnInfo in
|
||||
// state after create/update in prior versions, generate the additional
|
||||
// explicit connection settings that are now required if and only if
|
||||
// there's at least one provisioner block.
|
||||
// For now, we just pass this through as-is.
|
||||
hcl1printer.Fprint(buf, item)
|
||||
buf.WriteByte('\n')
|
||||
return nil
|
||||
}
|
||||
rules["provisioner"] = func(buf *bytes.Buffer, blockAddr string, item *hcl1ast.ObjectItem) tfdiags.Diagnostics {
|
||||
// TODO: Look up the provisioner schema and map this properly to ensure
|
||||
// any references get properly updated.
|
||||
// For now, we just pass this through as-is.
|
||||
hcl1printer.Fprint(buf, item)
|
||||
buf.WriteByte('\n')
|
||||
return nil
|
||||
}
|
||||
rules["connection"] = connectionBlockRule(filename, an, adhocComments)
|
||||
rules["provisioner"] = provisionerBlockRule(filename, an, adhocComments)
|
||||
|
||||
printComments(buf, item.LeadComment)
|
||||
printBlockOpen(buf, blockType, labels, item.LineComment)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/hashicorp/terraform/configs/configschema"
|
||||
"github.com/hashicorp/terraform/helper/logging"
|
||||
"github.com/hashicorp/terraform/providers"
|
||||
"github.com/hashicorp/terraform/provisioners"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
|
@ -40,6 +41,7 @@ func TestUpgradeValid(t *testing.T) {
|
|||
wantDir := filepath.Join(fixtureDir, entry.Name(), "want")
|
||||
u := &Upgrader{
|
||||
Providers: providers.ResolverFixed(testProviders),
|
||||
Provisioners: testProvisioners,
|
||||
}
|
||||
|
||||
inputSrc, err := LoadModule(inputDir)
|
||||
|
@ -250,6 +252,21 @@ var testProviders = map[string]providers.Factory{
|
|||
}),
|
||||
}
|
||||
|
||||
var testProvisioners = map[string]provisioners.Factory{
|
||||
"test": provisioners.Factory(func() (provisioners.Interface, error) {
|
||||
p := &terraform.MockProvisioner{}
|
||||
p.GetSchemaResponse = provisioners.GetSchemaResponse{
|
||||
Provisioner: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"commands": {Type: cty.List(cty.String), Optional: true},
|
||||
"interpreter": {Type: cty.String, Optional: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
return p, nil
|
||||
}),
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Initialize the backends
|
||||
backendinit.Init(nil)
|
||||
|
|
Loading…
Reference in New Issue