Terraform 输出:如何创建(地图?)以及如何使用地图?地图是正确的工具吗?
Terraform Outputs: How do I create a (map?) and how do I use the map? Is a map even the right tool?
我正在为一些 terraform 概念苦苦挣扎。
我成功地使用 aztfmod/azurecaf
提供程序来命名我的资源组,但这意味着我需要将该名称作为 companynet.resource_group
模块的输出,以便我可以再次使用该名称调用 companynet.key_vault
模块时。
# terraform.tfvars
resource_groups = {
rg1 = {
name = "resourcegroup1"
location = "eastus"
}
rg2 = {
name = "resourcegroup2"
location = "eastus"
}
}
# root main.tf
provider "azurerm" {
features {}
}
module "companynet" {
source = "./modules/companynet"
tenant_id = var.tenant_id
environment = var.environment
resource_groups = var.resource_groups
key_vaults = var.key_vaults
storage_accounts = var.storage_accounts
app_service_plans = var.app_service_plans
}
# modules/companynet/main.tf
module "resource_group" {
source = "../companynet.resource_group"
environment = var.environment
resource_groups = var.resource_groups
}
module "key_vault" {
source = "../companynet.key_vault"
tenant_id = var.tenant_id
environment = var.environment
resource_groups = "${module.resource_group.resource_groups.companynet}"
key_vaults = var.key_vaults
}
模块 resource_group
具有以下 main.tf
:
# modules/companynet.resource_group/main.tf
resource "azurecaf_name" "resource_group" {
for_each = var.resource_groups
name = each.value.name
resource_type = "azurerm_resource_group"
suffixes = ["${var.environment}", "001"]
}
resource "azurerm_resource_group" "resource_group" {
for_each = var.resource_groups
name = azurecaf_name.resource_group[each.key].result
location = each.value.location
}
但我不知道如何获得那个 resource_group 名称的输出。
我尝试了一些不同的方法,但都不起作用
# modules/companynet.resource_group/outputs.tf
output "resource_groups" {
value = azurerm_resource_group.resource_group[*].name
}
value = azurerm_resource_group.resource_group.name
value = azurerm_resource_group.resource_group.companynet.name
value = azurerm_resource_group.resource_group[companynet].name
每一个都会导致一个或另一个错误,都表明 modules/companynet.resource_group/outputs.tf
有问题
理想情况下,我会得到一个对象,然后我可以在另一个模块中对其进行迭代。我希望能够调用类似的东西来访问其他模块中的那些资源组名称,例如:
# modules/companynet.key_vault/main.tf
resource "azurerm_key_vault" "key_vault" {
for_each = var.key_vaults
name = azurecaf_name.key_vault[each.key].result
location = var.resource_groups.location
resource_groups = "${module.resource_group.resource_groups.[companynet]}"
sku_name = "standard"
tenant_id = var.tenant_id
}
azurerm_resource_group.resource_group
是用 for_each
声明的,因此该表达式引用一个对象映射,其中键与 for_each
表达式的键匹配,值是相应声明的资源实例。
在References to Resource Attributes中有各种在不同情况下引用资源属性的例子,包括以下关于使用for_each
的资源:
When a resource has the for_each
argument set, the resource itself becomes a map of instance objects rather than a single object, and attributes of instances must be specified by key, or can be accessed using a for
expression.
aws_instance.example["a"].id
returns the id of the "a"-keyed resource.
[for value in aws_instance.example: value.id]
returns a list of all of the ids of each of the instances.
第二项显示了如何使用 for
表达式生成 aws_instance.example
的 ID 的 list,但它没有准确显示如何生成地图,而是希望您参考有关 for
表达式的链接文档以了解相关信息:
The type of brackets around the for
expression decide what type of result it produces.
The above example uses [
and ],
which produces a tuple. If you use {
and }
instead, the result is an object and you must provide two result expressions that are separated by the =>
symbol:
{for s in var.list : s => upper(s)}
This expression produces an object whose attributes are the original elements from var.list
and their corresponding values are the uppercase versions. For example, the resulting value might be as follows:
{
foo = "FOO"
bar = "BAR"
baz = "BAZ"
}
A for
expression alone can only produce either an object value or a tuple value, but Terraform's automatic type conversion rules mean that you can typically use the results in locations where lists, maps, and sets are expected.
本节介绍如何生成对象,然后说明您可以在需要地图的位置使用结果。在实践中,通常可以在 Terraform 中互换使用 object-typed 值和 mapped-type 值,因为它们的共同点是它们都具有由字符串键标识的元素。不同之处在于对象类型的每个属性都可以有一个单独的类型,而映射的所有属性必须有相同的类型。
根据所有这些信息,我们可以生成一个 object 值来描述每个资源组的名称,如下所示:
output "resource_groups" {
value = { for k, g in azurerm_resource_group.resource_group : k => g.name }
}
对于大多数目的来说,这是一个 object-typed 结果而不是一个特定的地图并不重要,但是因为我们知道 .name
总是一个字符串,我们可以推断出所有该对象的属性具有 string-typed 值,因此使用 the tomap
function 显式转换为字符串映射也是有效的(这是 [...] 映射 [.. .] 是预期的”,根据上述文件):
output "resource_groups" {
value = tomap({
for k, g in azurerm_resource_group.resource_group : k => g.name
})
}
我正在为一些 terraform 概念苦苦挣扎。
我成功地使用 aztfmod/azurecaf
提供程序来命名我的资源组,但这意味着我需要将该名称作为 companynet.resource_group
模块的输出,以便我可以再次使用该名称调用 companynet.key_vault
模块时。
# terraform.tfvars
resource_groups = {
rg1 = {
name = "resourcegroup1"
location = "eastus"
}
rg2 = {
name = "resourcegroup2"
location = "eastus"
}
}
# root main.tf
provider "azurerm" {
features {}
}
module "companynet" {
source = "./modules/companynet"
tenant_id = var.tenant_id
environment = var.environment
resource_groups = var.resource_groups
key_vaults = var.key_vaults
storage_accounts = var.storage_accounts
app_service_plans = var.app_service_plans
}
# modules/companynet/main.tf
module "resource_group" {
source = "../companynet.resource_group"
environment = var.environment
resource_groups = var.resource_groups
}
module "key_vault" {
source = "../companynet.key_vault"
tenant_id = var.tenant_id
environment = var.environment
resource_groups = "${module.resource_group.resource_groups.companynet}"
key_vaults = var.key_vaults
}
模块 resource_group
具有以下 main.tf
:
# modules/companynet.resource_group/main.tf
resource "azurecaf_name" "resource_group" {
for_each = var.resource_groups
name = each.value.name
resource_type = "azurerm_resource_group"
suffixes = ["${var.environment}", "001"]
}
resource "azurerm_resource_group" "resource_group" {
for_each = var.resource_groups
name = azurecaf_name.resource_group[each.key].result
location = each.value.location
}
但我不知道如何获得那个 resource_group 名称的输出。
我尝试了一些不同的方法,但都不起作用
# modules/companynet.resource_group/outputs.tf
output "resource_groups" {
value = azurerm_resource_group.resource_group[*].name
}
value = azurerm_resource_group.resource_group.name
value = azurerm_resource_group.resource_group.companynet.name
value = azurerm_resource_group.resource_group[companynet].name
每一个都会导致一个或另一个错误,都表明 modules/companynet.resource_group/outputs.tf
理想情况下,我会得到一个对象,然后我可以在另一个模块中对其进行迭代。我希望能够调用类似的东西来访问其他模块中的那些资源组名称,例如:
# modules/companynet.key_vault/main.tf
resource "azurerm_key_vault" "key_vault" {
for_each = var.key_vaults
name = azurecaf_name.key_vault[each.key].result
location = var.resource_groups.location
resource_groups = "${module.resource_group.resource_groups.[companynet]}"
sku_name = "standard"
tenant_id = var.tenant_id
}
azurerm_resource_group.resource_group
是用 for_each
声明的,因此该表达式引用一个对象映射,其中键与 for_each
表达式的键匹配,值是相应声明的资源实例。
在References to Resource Attributes中有各种在不同情况下引用资源属性的例子,包括以下关于使用for_each
的资源:
When a resource has the
for_each
argument set, the resource itself becomes a map of instance objects rather than a single object, and attributes of instances must be specified by key, or can be accessed using afor
expression.
aws_instance.example["a"].id
returns the id of the "a"-keyed resource.[for value in aws_instance.example: value.id]
returns a list of all of the ids of each of the instances.
第二项显示了如何使用 for
表达式生成 aws_instance.example
的 ID 的 list,但它没有准确显示如何生成地图,而是希望您参考有关 for
表达式的链接文档以了解相关信息:
The type of brackets around the
for
expression decide what type of result it produces.The above example uses
[
and],
which produces a tuple. If you use{
and}
instead, the result is an object and you must provide two result expressions that are separated by the=>
symbol:{for s in var.list : s => upper(s)}
This expression produces an object whose attributes are the original elements from
var.list
and their corresponding values are the uppercase versions. For example, the resulting value might be as follows:{ foo = "FOO" bar = "BAR" baz = "BAZ" }
A
for
expression alone can only produce either an object value or a tuple value, but Terraform's automatic type conversion rules mean that you can typically use the results in locations where lists, maps, and sets are expected.
本节介绍如何生成对象,然后说明您可以在需要地图的位置使用结果。在实践中,通常可以在 Terraform 中互换使用 object-typed 值和 mapped-type 值,因为它们的共同点是它们都具有由字符串键标识的元素。不同之处在于对象类型的每个属性都可以有一个单独的类型,而映射的所有属性必须有相同的类型。
根据所有这些信息,我们可以生成一个 object 值来描述每个资源组的名称,如下所示:
output "resource_groups" {
value = { for k, g in azurerm_resource_group.resource_group : k => g.name }
}
对于大多数目的来说,这是一个 object-typed 结果而不是一个特定的地图并不重要,但是因为我们知道 .name
总是一个字符串,我们可以推断出所有该对象的属性具有 string-typed 值,因此使用 the tomap
function 显式转换为字符串映射也是有效的(这是 [...] 映射 [.. .] 是预期的”,根据上述文件):
output "resource_groups" {
value = tomap({
for k, g in azurerm_resource_group.resource_group : k => g.name
})
}