Home > other >  Terraform Resource Group ID as a Variable
Terraform Resource Group ID as a Variable

Time:12-09

I am currently migrating our cloud infrastructure over to Terraform; it's all gone well so far. Right now, though, I am trying to set up the SQL Server app, and the current setup, which I need to mirror to migrate, takes the existing resource group Object ID and appends it onto a unique string, for example, sqldatabase23456-resource group object id.

In arm this is done the following way:

"sqlServerAdministratorUsername": "[concat('l', uniqueString(resourceGroup().id))]",

Except I am making the resource group in Terraform, so the variable needs to use the meta argument depends on as the variable value can not exist before the resource group exists. I don't think this is possible when reading the depends on the material from Terraform; it only seems to work for resources, not other items. Link to document: https://www.terraform.io/docs/language/meta-arguments/depends_on.html

I have seen it slightly discussed on here:

Terraform, can a resource be passed as a variable into a module?

I am happy to build this SQL server as a module. I need this to work this way; otherwise, we won't migrate over to Terraform. As we can't change the current setup with SQL, too much depends on it.

I need to pass the values into the login part of SQL server code example below:

resource "azurerm_mssql_server" "example" {
  name                         = "mssqlserver"
  resource_group_name          = azurerm_resource_group.example.name
  location                     = azurerm_resource_group.example.location
  version                      = "12.0"
  administrator_login          = var.resourcegroup_withuniquestring
  administrator_login_password = var.resourcegroup_withuniquestring_password
  minimum_tls_version          = "1.2"

  tags = {
    environment = "production"
  }
}

CodePudding user response:

I don't really know what do you mean by variable in this context.

Terraform has locals. Locals can reference other Terraform resources, by this making the dependency implicit, so there is no need for depends_on. Example:

resource "random_string" "random" {
  length           = 16
  special          = true
  override_special = "/@£$"
}

locals {
  sql_server_administrator_name = join("", "sqldatabase", random_string.random.result, "-", azurerm_resource_group.example.name,
}

Locals can be referenced in other resources:

resource "azurerm_mssql_server" "example" {
  name                         = "mssqlserver"
  resource_group_name          = azurerm_resource_group.example.name
  location                     = azurerm_resource_group.example.location
  version                      = "12.0"
  administrator_login          = local.sql_server_administrator_name
  administrator_login_password = local.password
  minimum_tls_version          = "1.2"
}

CodePudding user response:

I actually figured this out using the prompting of Ervins anwser.

I used locals to put the resource group id as a variable but the problem with that is it will output a huge string that can not be used for account names, so here is the following steps that I took, to trim it down and make it usable.

I first made three local variables one to trim down the string and get the ID number of the resource group and disregard everything else.

Another to output the whole string so I could work out the string value and how many characters to count in.

And a Third to put both the unique string and the Resource Group ID number on the end.

Below is the code to trim the string.

resource_group_id = substr(("${azurerm_resource_group.Example_Terraform_Testing.id}"),15,36)

This is using the function substr in Terraform which allows you to chop up strings, as most of the functions will only let you work with maps, or lists.

Link to substr: https://www.terraform.io/docs/language/functions/substr.html

To work out the exact number I first used format as a local value then outputed the value through an output variable like this:

resource_group_id_full_value = format("${azurerm_resource_group.Example_Terraform_Testing.id}")

output "resource_group_id__full_value" { value = local.resource_group_id_full_value }

This will then output the whole string like this when running Terraform Plan or Apply: resource_group_id__full_value = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/Example_Terraform_Testing"

To user substr you need to count the characters from the first / and the first / is 0 all / are a value. Unlike other languages that disregard special characters.

Once I had that as a local value I could then append that onto my local variable string like this:

sql_admin_login = format("${random_string.myrandom.id}-${local.resource_group_id}")

This will then give me the format I wanted like this, "qpncxt-00000000-0000-0000-0000-000000000000" and meet the account name requirements set by Azure, to be unique and to not have any special characters in and not to be too long. Also the great thing about substr is If I need the value to be shorter I just put in a lower number in the string.

Here is my full code to get this working:

locals {
  # Ids for Resource Group, merged together with unique string
  resource_group_id_full_value = format("${azurerm_resource_group.Example_In_The_Cloud_Terraform_Testing.id}")
  resource_group_id            = substr(("${azurerm_resource_group.Example_Terraform_Testing.id}"), 15, 36)
  
  sql_admin_login    = format("${random_string.myrandom.id}-${local.resource_group_id}")
  sql_admin_password = format("${random_string.myrandom.id}-${local.resource_group_id}")
  sql_server_name    = format("sqlserver-${local.resource_group_id}")
}

resource "azurerm_mssql_server" "example_sql_server" {
  name                         = local.sql_server_name
  location                     = azurerm_resource_group.Example_Terraform_Testing.location
  resource_group_name          = azurerm_resource_group.Example_Terraform_Testing.name
  version                      = "12.0"
  administrator_login          = local.sql_admin_login
  administrator_login_password = local.sql_admin_password
  minimum_tls_version          = "1.2"


  tags = {
    environment = "production"
  }
}

Links used to work this out:

Terraform Local Values: https://www.terraform.io/docs/language/values/locals.html

Terraform String Functions: https://www.terraform.io/docs/language/functions/substr.html

  • Related