command: Change 0.13upgrade default to versions.tf
Instead of using providers.tf as the default output file for the upgrader, we now default to versions.tf. This means that if the configuration has no `required_providers` blocks at all, or has multiple, the provider version requirements will be stored in the versions.tf file. We now also update the versions.tf file to set a `required_version` attribute in the first `terraform` block, with value ">= 0.13". This is similar to the behaviour of the 0.12upgrade command, and signals that the configuration should not be used with older versions of Terraform.
This commit is contained in:
parent
01a3376ead
commit
a740b739e0
|
@ -247,8 +247,9 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default output filename is "providers.tf"
|
// Default output filename is "versions.tf", which is also where the
|
||||||
filename := path.Join(dir, "providers.tf")
|
// 0.12upgrade command added the required_version constraint.
|
||||||
|
filename := path.Join(dir, "versions.tf")
|
||||||
|
|
||||||
// Special case: if we only have one file with a required providers
|
// Special case: if we only have one file with a required providers
|
||||||
// block, output to that file instead.
|
// block, output to that file instead.
|
||||||
|
@ -322,14 +323,22 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
|
||||||
var first *hclwrite.Block
|
var first *hclwrite.Block
|
||||||
var rest []*hclwrite.Block
|
var rest []*hclwrite.Block
|
||||||
|
|
||||||
|
// First terraform block in the first file. Declared at this scope so
|
||||||
|
// that it can be used to write the version constraint later, if this
|
||||||
|
// is the "versions.tf" file.
|
||||||
|
var tfBlock *hclwrite.Block
|
||||||
|
|
||||||
if len(requiredProviderBlocks) > 0 {
|
if len(requiredProviderBlocks) > 0 {
|
||||||
// If we already have one or more required provider blocks, we'll rewrite
|
// If we already have one or more required provider blocks, we'll rewrite
|
||||||
// the first one, and remove the rest.
|
// the first one, and remove the rest.
|
||||||
first, rest = requiredProviderBlocks[0], requiredProviderBlocks[1:]
|
first, rest = requiredProviderBlocks[0], requiredProviderBlocks[1:]
|
||||||
|
|
||||||
|
// Set the terraform block here for later use to update the
|
||||||
|
// required version constraint.
|
||||||
|
tfBlock = parentBlocks[first]
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, find or a create a terraform block, and add a new
|
// Otherwise, find or a create a terraform block, and add a new
|
||||||
// empty required providers block to it.
|
// empty required providers block to it.
|
||||||
var tfBlock *hclwrite.Block
|
|
||||||
for _, rootBlock := range root.Blocks() {
|
for _, rootBlock := range root.Blocks() {
|
||||||
if rootBlock.Type() == "terraform" {
|
if rootBlock.Type() == "terraform" {
|
||||||
tfBlock = rootBlock
|
tfBlock = rootBlock
|
||||||
|
@ -404,6 +413,14 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is the "versions.tf" file, add a new version constraint to
|
||||||
|
// the first terraform block. If this isn't the "versions.tf" file,
|
||||||
|
// we'll update that file separately.
|
||||||
|
versionsFilename := path.Join(dir, "versions.tf")
|
||||||
|
if filename == versionsFilename {
|
||||||
|
tfBlock.Body().SetAttributeValue("required_version", cty.StringVal(">= 0.13"))
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the rest of the blocks (and the parent block, if it's empty)
|
// Remove the rest of the blocks (and the parent block, if it's empty)
|
||||||
for _, rpBlock := range rest {
|
for _, rpBlock := range rest {
|
||||||
tfBlock := parentBlocks[rpBlock]
|
tfBlock := parentBlocks[rpBlock]
|
||||||
|
@ -440,6 +457,84 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the file we just updated was not a "versions.tf" file, add or
|
||||||
|
// update that file to set the required version constraint in the first
|
||||||
|
// terraform block.
|
||||||
|
if filename != versionsFilename {
|
||||||
|
var file *hclwrite.File
|
||||||
|
|
||||||
|
// If the versions file doesn't exist, just create a new empty file
|
||||||
|
if _, err := os.Stat(versionsFilename); os.IsNotExist(err) {
|
||||||
|
file = hclwrite.NewEmptyFile()
|
||||||
|
} else if err != nil {
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Unable to read configuration file",
|
||||||
|
fmt.Sprintf("Error when reading configuration file %q: %s", versionsFilename, err),
|
||||||
|
))
|
||||||
|
c.showDiagnostics(diags)
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
// Versions file already exists, so load and parse it
|
||||||
|
config, err := ioutil.ReadFile(versionsFilename)
|
||||||
|
if err != nil {
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Unable to read configuration file",
|
||||||
|
fmt.Sprintf("Error when reading configuration file %q: %s", versionsFilename, err),
|
||||||
|
))
|
||||||
|
c.showDiagnostics(diags)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
var parseDiags hcl.Diagnostics
|
||||||
|
file, parseDiags = hclwrite.ParseConfig(config, filename, hcl.InitialPos)
|
||||||
|
diags = diags.Append(parseDiags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if diags.HasErrors() {
|
||||||
|
c.showDiagnostics(diags)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find or create a terraform block
|
||||||
|
root := file.Body()
|
||||||
|
var tfBlock *hclwrite.Block
|
||||||
|
for _, rootBlock := range root.Blocks() {
|
||||||
|
if rootBlock.Type() == "terraform" {
|
||||||
|
tfBlock = rootBlock
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tfBlock == nil {
|
||||||
|
tfBlock = root.AppendNewBlock("terraform", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the required version attribute
|
||||||
|
tfBlock.Body().SetAttributeValue("required_version", cty.StringVal(">= 0.13"))
|
||||||
|
|
||||||
|
// Write the config back to the file
|
||||||
|
f, err := os.OpenFile(versionsFilename, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Unable to open configuration file for writing",
|
||||||
|
fmt.Sprintf("Error when reading configuration file %q: %s", filename, err),
|
||||||
|
))
|
||||||
|
c.showDiagnostics(diags)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
_, err = file.WriteTo(f)
|
||||||
|
if err != nil {
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Unable to rewrite configuration file",
|
||||||
|
fmt.Sprintf("Error when rewriting configuration file %q: %s", filename, err),
|
||||||
|
))
|
||||||
|
c.showDiagnostics(diags)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// After successfully writing the new configuration, remove all other
|
// After successfully writing the new configuration, remove all other
|
||||||
// required provider blocks from remaining configuration files.
|
// required provider blocks from remaining configuration files.
|
||||||
for _, path := range rewritePaths {
|
for _, path := range rewritePaths {
|
||||||
|
@ -600,8 +695,8 @@ func (c *ZeroThirteenUpgradeCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: terraform 0.13upgrade [module-dir]
|
Usage: terraform 0.13upgrade [module-dir]
|
||||||
|
|
||||||
Generates a "providers.tf" configuration file which includes source
|
Updates module configuration files to add provider source attributes and
|
||||||
configuration for every non-default provider.
|
merge multiple required_providers blocks into one.
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ func TestZeroThirteenUpgrade_success(t *testing.T) {
|
||||||
"preserves comments": "013upgrade-preserves-comments",
|
"preserves comments": "013upgrade-preserves-comments",
|
||||||
"multiple blocks": "013upgrade-multiple-blocks",
|
"multiple blocks": "013upgrade-multiple-blocks",
|
||||||
"multiple files": "013upgrade-multiple-files",
|
"multiple files": "013upgrade-multiple-files",
|
||||||
"existing providers.tf": "013upgrade-existing-providers-tf",
|
"existing versions.tf": "013upgrade-existing-versions-tf",
|
||||||
"skipped files": "013upgrade-skipped-files",
|
"skipped files": "013upgrade-skipped-files",
|
||||||
}
|
}
|
||||||
for name, testPath := range testCases {
|
for name, testPath := range testCases {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# This is a file called providers.tf which does not originally have a
|
|
||||||
# required_providers block.
|
|
||||||
resource foo_resource a {}
|
|
|
@ -1,7 +1,9 @@
|
||||||
# This is a file called providers.tf which does not originally have a
|
# This is a file called versions.tf which does not originally have a
|
||||||
# required_providers block.
|
# required_providers block.
|
||||||
resource foo_resource a {}
|
resource foo_resource a {}
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
required_providers {
|
required_providers {
|
||||||
bar = {
|
bar = {
|
||||||
source = "hashicorp/bar"
|
source = "hashicorp/bar"
|
|
@ -0,0 +1,7 @@
|
||||||
|
# This is a file called versions.tf which does not originally have a
|
||||||
|
# required_providers block.
|
||||||
|
resource foo_resource a {}
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.12"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -9,4 +9,5 @@ terraform {
|
||||||
source = "hashicorp/foo"
|
source = "hashicorp/foo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -13,4 +13,5 @@ terraform {
|
||||||
# https://www.terraform.io/docs/configuration/providers.html#provider-source
|
# https://www.terraform.io/docs/configuration/providers.html#provider-source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -10,4 +10,5 @@ terraform {
|
||||||
source = "hashicorp/foo"
|
source = "hashicorp/foo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -12,4 +12,5 @@ terraform {
|
||||||
version = "0.5"
|
version = "0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -13,4 +13,5 @@ terraform {
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -4,4 +4,5 @@ terraform {
|
||||||
source = "hashicorp/foo"
|
source = "hashicorp/foo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
Loading…
Reference in New Issue