Migrate from count to for_each

Good morning,

We are in the process of re-writing our Terraform modules to make use of “for_each” instead of “count” and we are finding difficulties migrating networks deployed with the old module to the new one. I would like to know if there is an official procedure for this.

The main problems we are finding and solution approach we are taking:

  1. If you try to apply the new code in an already existing vnet Terraform will plan to destroy every subnet and create it with the new nomenclature:

destroy: module.network.azurerm_subnet.subnet[0]
add: module.network.azurerm_subnet.subnet["westeurope-dev-app"]

  1. Ok, don’t panic, lets rename all the subnets in the state file instead of destroy/add them:

terraform state mv 'module.network.azurerm_subnet.subnet[0]' 'module.network.azurerm_subnet.subnet["westeurope-dev-app"]'

The main problem is that “count” deploys a ‘list’ of resources while “for_each” creates a ‘map’ and the mv command only renames the resource but it doesn’t change the list to a map so once you finish renaming subnets you end up with an empty list to the eyes of Terraform because it cannot access its elements (a list element should be accessed by position ‘number’, not by ‘key’". You will also experience some Terraform crashes after this movement because of “nill interface”…

Clue is in the state file:

"each": "map", versus "each": "list",

  1. Ok, after many try/test we found two ways to “fix” this new problem:
  • By removing only one subnet from the state file and importing it again Terraform changes from list to map and everything seems fine, is it?

terraform state rm 'module.network.azurerm_subnet.subnet["westeurope-dev-app"]'
terraform import 'module.network.azurerm_subnet.subnet["westeurope-dev-app"]' "/subscriptions/BLAHBLAH/providers/Microsoft.Network/virtualNetworks/westeurope-vnet/subnets/westeurope-dev-app"

  • Edit state file with your favourite vi flavour and change from list to map. Is this correct?

We would like to script a solution to be able to migrate all our networks but we would appreciate some official confirmation from Hashicorp to be sure we are not fixing something and breaking another.

1 Like

I believe you have hit a bug that has been bothering me (and many others) as well. See https://github.com/hashicorp/terraform/issues/23847 and https://github.com/hashicorp/terraform/issues/23676
The only thing I’ve been able to do is manually edit the state file to get around this issue until someone fixes it.

Now that it has been a few years. How was this problem solved or should be solved?

Hi @logicminds,

If you are referring to the linked issues above, they have since been resolved. Are you having a specific problem with refactoring in a current release? The state mv command should handle most cases, and moved blocks have been added for refactoring.

I was referring to the original question and suggestion of possible resolutions via the links. Currently I have 0.13.4 and a module that uses count for one of the resources and need to switch to the each method.

Question is how to update my state at the same time as updating my code? Because switching just the code causes havoc.

Looks like I can do
terraform state mv ‘packet_device.worker[0]’ ‘packet_device.worker[“device_name”]’ ?

Yup, you would use a state mv command like that to rename the individual instances so that they match the updated configuration.