Terraform 资源组 ID 作为变量

Posted

技术标签:

【中文标题】Terraform 资源组 ID 作为变量【英文标题】:Terraform Resource Group ID as a Variable 【发布时间】:2022-01-13 14:10:29 【问题描述】:

我目前正在将我们的云基础架构迁移到 Terraform;到目前为止一切顺利。不过,现在我正在尝试设置 SQL Server 应用程序,而我需要镜像以进行迁移的当前设置采用现有资源组对象 ID 并将其附加到唯一的字符串上,例如 sqldatabase23456-resource group object id.

在 arm 中,这是通过以下方式完成的:

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

除了我在 Terraform 中制作资源组,所以变量需要使用元参数depends on,因为在资源组存在之前变量值不能存在。在阅读来自 Terraform 的依赖材料时,我认为这是不可能的;它似乎只适用于资源,而不适用于其他项目。文档链接:https://www.terraform.io/docs/language/meta-arguments/depends_on.html

我已经看到这里稍微讨论过:

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

我很高兴将此 SQL 服务器构建为一个模块。我需要这个以这种方式工作;否则,我们不会迁移到 Terraform。由于我们无法使用 SQL 更改当前设置,因此过多地依赖它。

我需要将值传递到下面 SQL Server 代码示例的登录部分:

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"
  

【问题讨论】:

你知道 random_id 存在于 Terraform 中吗? registry.terraform.io/providers/hashicorp/random/latest/docs/… 是的,我知道,我在设置中的其他地方使用它。但此设置必须使用资源组 ID 和随机数。 【参考方案1】:

我真的不知道在这种情况下你所说的变量是什么意思。

Terraform 有locals。本地人可以引用其他 Terraform 资源,从而使依赖关系隐式,因此不需要depends_on。示例:

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 可以在其他资源中引用:

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"

【讨论】:

【参考方案2】:

我实际上是在 Ervins anwser 的提示下发现了这一点。

我使用 locals 将资源组 id 作为变量,但问题是它会输出一个不能用于帐户名称的巨大字符串,所以这是我采取的以下步骤,以减少它并使其可用。

我首先做了三个局部变量一个来修剪字符串并获取资源组的ID号,而忽略其他所有内容。

另一个输出整个字符串,这样我就可以计算出字符串值以及要计算的字符数。

第三个将唯一字符串和资源组 ID 号放在最后。

下面是修剪字符串的代码。

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

这是在 Terraform 中使用 substr 函数,它允许您分割字符串,因为大多数函数只允许您使用地图或列表。

链接到子字符串:https://www.terraform.io/docs/language/functions/substr.html

为了计算出确切的数字,我首先使用格式作为本地值,然后通过输出变量输出该值,如下所示:

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

这将在运行 Terraform Plan 或 Apply 时像这样输出整个字符串:resource_group_id__full_value = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/Example_Terraform_Testing"

对于用户substr,您需要从第一个 / 开始计数字符,并且第一个 / 是 0 所有 / 都是一个值。与其他忽略特殊字符的语言不同。

一旦我将它作为本地值,我就可以将它附加到我的本地变量字符串中,如下所示:

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

然后,这将为我提供我想要的格式,"qpncxt-00000000-0000-0000-0000-000000000000",并满足 Azure 设置的帐户名称要求,具有唯一性,并且不能包含任何特殊字符,并且不能太长。 substr 的另一个优点是如果我需要更短的值,我只需在字符串中输入一个较小的数字。

这是我完成这项工作的完整代码:

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"
  

用于解决此问题的链接:

Terraform 本地值:https://www.terraform.io/docs/language/values/locals.html

Terraform 字符串函数: https://www.terraform.io/docs/language/functions/substr.html

【讨论】:

以上是关于Terraform 资源组 ID 作为变量的主要内容,如果未能解决你的问题,请参考以下文章

你可以在 Terraform 中将块作为变量传递,引用资源嵌套块内容的类型吗?

Terraform:“inputMap”参数的值无效:lookup() 需要地图作为第一个参数

Terraform 模块 - 输出变量作为另一个模块的输入

如何使用 Terraform 在管理组范围上定义和分配 Azure 策略?

跨 terraform 环境共享资源

Terraform - Azure 作为提供者和受限访问帐户