Terraform on Azure: create resource if doesn't exists and don't rename existing one

260 Views Asked by At

Step 0: I have a terraform script that creates resource groups from external parameters.

resource "azurerm_resource_group" "example" {
  name     = var.name
  location = "Your_Location"
}

Step 1: I define var.name = 'ABC1' so a resource group named ABC1 is created with success.

Step 2: I want to use the same script to create a resource group named ABC2 so I tried to set var.name = 'ABC2' and apply it.

But the result was that Terraform noticed that the name was changed so it deleted the ABC1 resource group and created ABC2 instead.

I'm using terraform from azure pipelines via TerraformTaskV4@4 task (init -> plan -> apply)

Is there any way to instruct terraform not to change the name of the resource but to create a new one, if the name does not exist?

4

There are 4 best solutions below

0
Buda Florin On BEST ANSWER

I write here for history. I managed to do this by having .tfstate files. So when I populate the var.name variable, I also define a

state-${{ parameters.name }}.tfstate

in the hosting azure pipeline. And because of this, terraform doesn't care about what is already created with a different var.name variable and if I reuse the same value it manages to link to previously created resources.

2
Dayron Remigio On

please try the following example.

local data

locals {
  resource_groups = {
    rg_1 = "eastus"
    rg_2 = "westus2"
  }
}

terraform configuration

resource "azurerm_resource_group" "rg" {
  for_each = local.resource_groups
  name     = each.key
  location = each.value
}

enter image description here

0
Vinay B On

I tried Terraform code to create a resource if doesn't exist and don't rename or delete existing one. This is achieved by adding one name at a time to the default list variables.

In Terraform, resources are identified by their addresses, which are derived from their types and names within the configuration. When you change a value such as var.name, Terraform interprets it as a modification to the existing resource, not as an instruction to create a new resource.

To overcome this issue we need to pass the variables as a string in defaults one at a time to achieve the requirement you're looking for.

For this, we need backend file configuration to store and manage the state file versioning which helps in accepting the new resource name into the file along with the existing one so that the new name won't replace one.

My terraform configuration:

provider "azurerm" {
  features {}
}

terraform {
  backend "azurerm" {
    resource_group_name   = "tfstatevk-res"
    storage_account_name  = "tfstateaccountvk"
    container_name        = "tfstate"
    key                   = "terraformvk.tfstate"
  }
}

variable "resource_group_names" {
  type = set(string)
  default = ["demorgvk1"]
}

resource "azurerm_resource_group" "example" {
  for_each = var.resource_group_names
  name     = each.key
  location = "East US"

    lifecycle {
    ignore_changes = [
      tags,
    ]
  }
}

Output:

enter image description here

enter image description here

when I add a new name in defaults in the same script, It compares the existing data with the new name. If the name doesn't match then it will update the existing state file with a new name by versioning the state in a blob container stored in a remote location storage account and keeping the preexisting resource safe without making any changes or deletion.

default = ["demorgvk1","demorgvk2"]

When I rerun the same code with the new default parameters

Terraform apply:

enter image description here

enter image description here

enter image description here

0
anshu anand On

here is one simplest solution is that you can use module.

now you will create two files to call this main file to create the rg. To check module, click here

You can check the image to define the module.

Best practice main file and module should be in different folders.

You will be able to create two rg without any disruptions if you don't want to use the loop (for_each and count).