This is a helpful tip for anyone that has to import existing cloud resources into Terraform. We recently had to do this for an older app that lived in Azure DevOps and was migrated to GitHub.
Our resources were in Azure, but this applies to AWS too. The process is tedious, but it helps transfer their live state into version control.
The ultimate goal here is that after you import everything and run terraform plan
, there will be no differences. The basic workflow will be to:
- Start at your main resource, eg, in my case, it was an Azure App Service
- Import your resource into your terraform state
- Display the current state of the resource and copy it
- Paste the resource properties into your terraform file
Begin at a key resource
You might not know all the different resources that your app is using and that’s fine. In my case, I have an Azure App Service. If you go to terraform’s corresponding resource page, you can see that in the Example Usage section, it lists all resource dependencies that your resource has. You can then essentially reverse-engineer your architecture by traversing all dependencies.
In the case of the Azure App Service, it relies on an Azure App Service Plan, which in turn relies on an Azure Resource Group. Since you can reference each resource by their name in terraform, I recommend you start at the highest level, (Azure Resource Group) and import downwards in the hierarchy. That way, you can directly reference the parent resources like below where azurerm_resource_group.example.location
is referenced:
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_app_service_plan" "example" {
name = "example-appserviceplan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "Standard"
size = "S1"
}
}
Import your resources
Each time you find a new resource, you need to import it into your terraform state:
terraform import azurerm_app_service.example `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/sites/instance1`
For Azure, the ID of your resource can either be found in the Azure Portal or on the resource explorer.
Its live state is now in the terraform state file (.tfstate
), but your terraform resource declaration has no properties (azurerm_app_service.example
in your .tf
file).
Get live state properties for resources
You can get the current state of your resource by running the following on your newly imported resource:
terraform state show azurerm_app_service.example
This will display all the parameters for your resource that define how it is deployed. All you need to do is just copy these to a terraform file (.tf
) and modify them slightly.
Add the resource properties to a terraform file
You can copy the output of terraform state show
and paste it into a terraform file, but you must delete any attributes that cannot be modified via terraform. Specifically, these are any attributes listed under Attributes Reference on the page for the corresponding resource. For example, you will want to remove the id
attribute as that is something that Azure defines - you can’t change it. In the case of Azure App Service, I would also need to remove default_site_hostname
.
Just remove all of those and the terraform file should now match the state of the live resource. You can then run terraform plan
to verify this.
It won’t be perfect, but for our case, there was little that needed to be changed after following these steps. Most of the work went into defining variables and organizing the structure of the .tf
files.