command: Fix 0.13upgrade bug with multiple blocks

If a configuration had multiple blocks in the versions.tf file, it would
be added to the `rewritePaths` list multiple times. We would then remove
it from this slice, but only once, and so the output file would later be
rewritten to remove the required providers block.

This commit uses a set instead of a list to prevent this case, and adds
a regression test.
This commit is contained in:
Alisdair McDiarmid 2020-05-07 17:42:40 -04:00
parent e2be704d81
commit 1fdcbc4825
7 changed files with 28 additions and 30 deletions

View File

@ -164,12 +164,12 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
// Build up a list of required providers, uniquely by local name
requiredProviders := make(map[string]*configs.RequiredProvider)
var rewritePaths []string
rewritePaths := make(map[string]bool)
// Step 1: copy all explicit provider requirements across
for path, file := range files {
for _, rps := range file.RequiredProviders {
rewritePaths = append(rewritePaths, path)
rewritePaths[path] = true
for _, rp := range rps.RequiredProviders {
if previous, exist := requiredProviders[rp.Name]; exist {
diags = diags.Append(&hcl.Diagnostic{
@ -254,18 +254,16 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
// Special case: if we only have one file with a required providers
// block, output to that file instead.
if len(rewritePaths) == 1 {
filename = rewritePaths[0]
for path := range rewritePaths {
filename = path
break
}
}
// Remove the output file from the list of paths we want to rewrite
// later. Otherwise we'd delete the required providers block after
// writing it.
for i, path := range rewritePaths {
if path == filename {
rewritePaths = append(rewritePaths[:i], rewritePaths[i+1:]...)
break
}
}
delete(rewritePaths, filename)
// Open or create the output file
out, openDiags := c.openOrCreateFile(filename)
@ -456,7 +454,7 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int {
// After successfully writing the new configuration, remove all other
// required provider blocks from remaining configuration files.
for _, path := range rewritePaths {
for path := range rewritePaths {
// Read and parse the existing file
config, err := ioutil.ReadFile(path)
if err != nil {

View File

@ -1,5 +1,2 @@
resource bar_instance a {}
resource baz_instance b {}
terraform {
required_version = "> 0.12.0"
}

View File

@ -1 +1,4 @@
terraform {
required_version = ">= 0.12"
}
resource foo_instance c {}

View File

@ -1,5 +1,9 @@
terraform {
required_providers {
foo = {
source = "hashicorp/foo"
version = "0.5"
}
bar = {
source = "registry.acme.corp/acme/bar"
}
@ -7,10 +11,6 @@ terraform {
source = "terraform-providers/baz"
version = "~> 2.0.0"
}
foo = {
source = "hashicorp/foo"
version = "0.5"
}
}
required_version = ">= 0.13"
}

View File

@ -1,10 +1,2 @@
resource bar_instance a {}
resource baz_instance b {}
terraform {
required_version = "> 0.12.0"
required_providers {
bar = {
source = "registry.acme.corp/acme/bar"
}
}
}

View File

@ -1,11 +1,7 @@
terraform {
required_version = ">= 0.12"
required_providers {
baz = "~> 2.0.0"
}
}
terraform {
required_providers {
foo = "0.5"
}
}
resource foo_instance c {}

View File

@ -0,0 +1,12 @@
terraform {
required_providers {
foo = "0.5"
}
}
terraform {
required_providers {
bar = {
source = "registry.acme.corp/acme/bar"
}
}
}