Skip to content

Azure Provider: Migrating from Deprecated Resources Guide

This guide shows how to migrate from a resource which has been deprecated or renamed to its replacement.

It's possible to migrate between the resources by updating your Terraform Configuration, removing the old state, and the importing the new resource in config.

In this guide, we'll assume we're migrating from the azurermAppService resource to the new azurermLinuxWebApp resource, but this should also be applicable for resources that have only been renamed where you can simply change the resource type name in your config.

Assuming we have the following Terraform Configuration:

/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as azurerm from "./.gen/providers/azurerm";
/*The following providers are missing schema information and might need manual adjustments to synthesize correctly: azurerm.
For a more precise conversion please use the --provider flag in convert.*/
new azurerm.appService.AppService(this, "example", {
  app_service_plan_id: "${azurerm_app_service_plan.main.id}",
  location: "${azurerm_resource_group.main.location}",
  name: "Example App Service",
  resource_group_name: "${azurerm_resource_group.main.name}",
  site_config: [
    {
      dotnet_framework_version: "v4.0",
      remote_debugging_enabled: true,
      remote_debugging_version: "VS2019",
    },
  ],
});
const azurermAppServicePlanExample = new azurerm.appServicePlan.AppServicePlan(
  this,
  "example_1",
  {
    kind: "Linux",
    location: "${azurerm_resource_group.main.location}",
    name: "Example App Service Plan",
    reserved: true,
    resource_group_name: "${azurerm_resource_group.main.name}",
    sku: [
      {
        size: "S1",
        tier: "Standard",
      },
    ],
  }
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
azurermAppServicePlanExample.overrideLogicalId("example");
const azurermResourceGroupExample = new azurerm.resourceGroup.ResourceGroup(
  this,
  "example_2",
  {}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
azurermResourceGroupExample.overrideLogicalId("example");

We can update the Terraform Configuration to use the new resource by updating the resources to the new azurermServicePlan and azurermLinuxWebApp schema:

/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as azurerm from "./.gen/providers/azurerm";
/*The following providers are missing schema information and might need manual adjustments to synthesize correctly: azurerm.
For a more precise conversion please use the --provider flag in convert.*/
const azurermResourceGroupExample = new azurerm.resourceGroup.ResourceGroup(
  this,
  "example",
  {}
);
const azurermServicePlanExample = new azurerm.servicePlan.ServicePlan(
  this,
  "example_1",
  {
    location: azurermResourceGroupExample.location,
    name: "Example App Service Plan",
    os_type: "Linux",
    resource_group_name: azurermResourceGroupExample.name,
    sku_name: "B1",
  }
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
azurermServicePlanExample.overrideLogicalId("example");
const azurermLinuxWebAppExample = new azurerm.linuxWebApp.LinuxWebApp(
  this,
  "example_2",
  {
    location: azurermServicePlanExample.location,
    name: "Example App Service",
    resource_group_name: azurermResourceGroupExample.name,
    service_plan_id: azurermServicePlanExample.id,
    site_config: [{}],
  }
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
azurermLinuxWebAppExample.overrideLogicalId("example");

As the Terraform Configuration has been updated - we now need to update the State. We can view the items Terraform is tracking in its statefile using the terraformStateList command, for example:

$ terraform state list
azurerm_app_service.example
azurerm_app_service_plan.example
azurerm_resource_group.example

In order to migrate from the old resource to the new resource we need to first remove the old resource from the state - and subsequently use Terraform's import functionality to migrate to the new resource.

To import a resource in Terraform we first require its Resource ID - we can obtain this from the command-line via:

$ echo azurerm_app_service_plan.example.id | terraform console
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/serverfarms/instance1
$ echo azurerm_app_service.example.id | terraform console
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/sites/instance1

Next we can remove the existing resource using terraformStateRm - for example:

$ terraform state rm azurerm_app_service.example azurerm_app_service_plan.example
Removed azurerm_autoscale_setting.example
Successfully removed 2 resource instance(s).

Now that the old resource has been removed from Terraform's Statefile we can now Import it into the Statefile as the new resource by running:

terraform import [resourcename].[identifier] [resourceid]

For example:

$ terraform import azurerm_service_plan.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/serverfarms/instance1
azurerm_monitor_autoscale_setting.test: Importing from ID "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/serverfarms/instance1"...
azurerm_monitor_autoscale_setting.test: Import prepared!
  Prepared azurerm_monitor_autoscale_setting for import
azurerm_monitor_autoscale_setting.test: Refreshing state... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/serverfarms/instance1]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

$ terraform import azurerm_linux_web_app.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/sites/instance1
azurerm_monitor_autoscale_setting.test: Importing from ID "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/sites/instance1"...
azurerm_monitor_autoscale_setting.test: Import prepared!
  Prepared azurerm_monitor_autoscale_setting for import
azurerm_monitor_autoscale_setting.test: Refreshing state... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Web/sites/instance1]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Once this has been done, running terraformPlan should show no changes:

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

At this point, you've switched over to using the new resource and should be able to continue using Terraform as normal.