Expressions

We’ve deployed two Terraforms resource—a Resource Group and a Storage Account—but their definitions have some drawbacks:

  • The location fields are hard-coded and are set to two different regions
  • The Storage Account name is hard-coded too, and you had to to find a globally unique name manually
  • The Storage Account references the Resource Group by its hard-coded name, which means duplication and lack of safety

Let’s solve these problems.

Values as expressions

Values for resource arguments may be defined in terms of string literals, as we did before. They are contained in double-quotes, e.g., "westus".

The value can also be an expression. An expression has no double-quotes around it and can point to other resources. Here is an example:

  resource_group_name      = azurerm_resource_group.rg.name

This line specifies that the value for the argument resource_group_name should be set to name attribute of the resource rg of type azurerm_resource_group. In this case, this means that the Storage Account should take the name of the Resource Group from its resource definition. Even if you rename the Resource Group later on, you won’t have to change the definition of the Storage Account resource.

Note that the reference uses the Terraform resource name rg, not the Resource Group name terraform-workshop.

Terraform checks expressions before applying the definitions, and it’s able to catch errors like broken references.

Reference Name and Location of the Resource Group

Modify the definition of the Storage Account resource to reference the Resource Group in resource_group_name and location:

resource "azurerm_storage_account" "sa" {
  name                     = "<your unique SA name>"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

Run terraform apply again and look at the preview, you should see the suggestion to replace your Storage Account:

Terraform will perform the following actions:

  # azurerm_storage_account.sa must be replaced
...
      ~ location                          = "westus2" -> "westus" # forces replacement
...

It’s not possible to change the location of a Storage Account in-place. Because we changed the location, Terraform decides to replace the resource: delete the old instance and create a new one.

Always look for replacement notes in Terraform preview: sometimes they may come as a surprise and then you would want to investigate before re-creating a resource which may contain valuable data.

However, this time, it’s okay, so confirm the actions and wait for completions.

Generating a unique name

Previously, you had to come up with a globally unique name for the Storage Account. However, this account is not our primary target: we just need it to start working with Azure Functions. It would be perfectly fine to give it some unique machine-generated name just to be able to proceed. We can use a random_string Terraform resource to do this for us.

First, register the random provider:

provider "random" {
}

Run terraform init to install the binaries of the newly added provider. Then, define a random_string resource:

resource "random_string" "sa_name" {
  length = 10
  special = false
  upper = false
}

Storage Account names can only contain lowercase letters and digits, so we exclude special and uppercase characters. Now, update the definition of the Storage Account:

resource "azurerm_storage_account" "sa" {
  name                     = "sa${random_string.sa_name.result}"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

This time, we used a different syntax of using referenced value: string interpolation with a very JavaScript-like syntax. The resulting name should be something like saxpm31vuc7r—starting with sa and then 10 random characters.

Run terraform apply to recreate the Storage Account.

Note that the random_string resource produces stable values: they are not going to change between subsequent runs. Very useful for multiple deployments!

Checkpoint

List the resources in your Resource Group.

$ az resource list -g terraform-workshop -o table

Name          ResourceGroup       Location  Type
------------  ------------------- --------  ---------------------------------
saxpm31vuc7r  terraform-workshop  westus    Microsoft.Storage/storageAccounts

You should see a single Storage Account with a random name.

If you have any difficulties, compare your code with this sample.

Next Step