I have an existing instance with version 5.0. I created a new instance with version 6 from UI and want to import it into terraform (to replace the existing one). The old instance will be deleted eventually. If I use terraform import, do I have to terraform rm state of old instance first, then do import of new instance, then delete the old instance from UI (this is a 3-step process), or I can simply do import of new instance in one shot? Thank you.
What is not clear is if you want this new (v6) resource to have a new Terraform Resource Address or if you want this newly created resource to have the same resource address as the old (v5) resource. But below are some examples showing both and their impact:
In short:
-
If this is going to be imported into state as a new resource with new module config and terraform resource address then it will be treated as a new resource and the old and new resource can be managed by terraform independently
-
If this is going to be imported into state with the same Terraform resource address as the existing resource then:
- Yes - you will have to remove the state from the state file before the import will occur
- You need to ensure that the config in the module matches that for the imported resource for any attributes that will cause a destroy/recreate of the resource.
- The original resource (by being removed from the state) will no longer be managed by terraform and can then be managed directly.
Example 1
If this new instance is a completely new resource with a different resource/import ID and will be imported as a new resource with its own resource address into Terraform then it will be considered as a completely separate resource from the original:
resource "azurerm_storage_account" "examplev5" {
# Original / Exisiting Resource
name = "storageaccountnamev5"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_account" "examplev6" {
# New Resource (Pre-Created via Portal or CLI)
name = "storageaccountnamev6"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
import {
# Import New resource under terraform management into new resource address (examplev6)
to = azurerm_storage_account.examplev6
id = "/subscriptions/{removed}/resourceGroups/myResourceGroup1/providers/Microsoft.Storage/storageAccounts/storageaccountnamev6"
}
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
The original one can be destroyed by removing its config from your terraform module when you are ready.
Example 2
If the requirement is to import the new v6 resource into the same terraform resource address as the old v5 then there a few things to consider.
2a
Firstly, as the resource is already part of the terraform state, just adding an import block with the new resource id
will have no effect - once there is state for a given resource address in the state file the import block is effectively ignored:
resource "azurerm_storage_account" "examplev5" {
# Original / Exisiting Resource
name = "storageaccountnamev5"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
import {
# Import New resource under terraform management into new resource address (examplev6)
to = azurerm_storage_account.examplev5
id = "/subscriptions/{removed}/resourceGroups/myResourceGroup1/providers/Microsoft.Storage/storageAccounts/storageaccountnamev6" # <-- See different resource ID
}
No changes. Your infrastructure matches the configuration.
2b
Example 2a indicates that the state should be removed from the state file to enable the new v6 resource with the new ID to be imported to the same Terraform address:
> terraform state rm azurerm_storage_account.examplev5
Removed azurerm_storage_account.examplev5
Successfully removed 1 resource instance(s).
Now you can import to the address azurerm_storage_account.examplev5
Warning - you need to consider the configuration you have in your module. If you do not update your module to align with the resource to be imported (leaving the original V5 config untouched):
resource "azurerm_storage_account" "examplev5" {
# Original / Exisiting Resource
name = "storageaccountnamev5"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
import {
# Import New resource under terraform management into same resource address (examplev5)
to = azurerm_storage_account.examplev5
id = "/subscriptions/{removed}/resourceGroups/myResourceGroup1/providers/Microsoft.Storage/storageAccounts/storageaccountnamev6"
}
Then the following may happen:
Terraform will perform the following actions:
# azurerm_storage_account.examplev5 must be replaced
# (imported from "/subscriptions/8485270c-a6ea-4dd9-909b-b3bd1deafbab/resourceGroups/myResourceGroup1/providers/Microsoft.Storage/storageAccounts/storageaccountnamev6")
# Warning: this will destroy the imported resource
...
~ name = "storageaccountnamev6" -> "storageaccountnamev5" # forces replacement
...
Plan: 1 to import, 1 to add, 0 to change, 1 to destroy.
This is because an attribute (in this case the name) is different, and cannot be updated in place so terraform will import the state of your new resource, destroy it and recreate it using the configuration in your module.
2c
As long as you ensure your module config is updated to reflect the resource being imported such that no attributes will force a destroy/recreate then once you have removed the state from the state file (as shown in 2b), you should be able to import the new resource into the old resource address without impact:
resource "azurerm_storage_account" "examplev5" {
# Original / Existing Resource
name = "storageaccountnamev6" ## <-- Updated config to match resource to be imported
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
import {
# Import New resource under terraform management into old resource address (examplev5)
to = azurerm_storage_account.examplev5
id = "/subscriptions/{removed}/resourceGroups/myResourceGroup1/providers/Microsoft.Storage/storageAccounts/storageaccountnamev6"
}
Terraform will perform the following actions:
# azurerm_storage_account.examplev5 will be imported
...
Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
At this stage the original (v5) resource is no longer managed by terraform and should be dealt with via the portal/cli.
Hope that helps.
Happy Terraforming
Thank you @ExtelligenceIT . Very well explanation. We will use the same resource like
resource ibm_database test {
#other stuff ignored here.
version = 5 # new instance has version 6,
}
Thanks for sharing all of those details, @ExtelligenceIT!
One extra note that might be interesting in this case:
Instead of using terraform state rm
to ask Terraform to totally “forget” a particular object (and thus have to delete it manually outside of Terraform) another possibility is to use terraform state mv
to rebind the object to an address that isn’t described in the current configuration.
In a subsequent plan Terraform will then notice that the address isn’t matched by any resource instance declared in the configuration, and so propose to delete it.
Of course, an important downside of this approach is that Terraform will propose to deal with both the importing and the deleting in the same plan, which means there is some risk that deleting succeeds while importing fails, potentially leaving you with no object tracked by Terraform at all. Whether that’s significant for a particular case of course depends on what these objects represent in your system and which other objects are depending on it for their own behavior.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.