Terraform 地图中的变量键
Variable keys in terraform maps
在 Terraform 中,我正在尝试创建一个模块,其中包含一个带有可变键的地图。我不确定这是否可行,但我尝试了以下但没有成功。
resource "aws_instance" "web" {
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
count = "${var.ec2_instance_count}"
tags {
Name = "${var.role} ${var_env}"
role = "${var.app_role}"
${var.app_role} = "${var_env}"
}
}
还有这个:
tags {
Name = "${var.role} ${var_env}"
}
tags."${var.role}" = "${var.env}"
有什么想法吗? Terraform 目前无法做到这一点吗?
terraform 插值语法支持(现在)lookup
function,允许您在地图中查找动态键。
使用它,我现在可以做类似的事情:
output "image_bucket_name" {
value = "${lookup(var.image_bucket_names, var.environment, "No way this should happen")}"
}
其中:
variable "image_bucket_names" {
type = "map"
default = {
development = "bucket-dev"
staging = "bucket-for-staging"
preprod = "bucket-name-for-preprod"
production = "bucket-for-production"
}
}
和environment
是一个简单的字符串变量。
我最近也需要动态设置标签键,并设法使用 zipmap
:
locals {
ec2_tag_keys = ["some/prefix/${var.some_var}", "another_tag"]
ec2_tag_vals = ["some value", "another value"]
}
resource "aws_instance", "foo" {
...
tags = "${zipmap(local.ec2_tag_keys, local.ec2_tag_vals)}"
}
它有点笨拙,但它确实有效。
我不确定它是什么时候添加的,但至少从 0.11.7 版本开始,Terraform 支持使用变量作为映射键。这是我目前如何将其用于 select AWS 实例类型的示例:
在 .tf
文件中:
variable "environment" {}
...
variable "instance_types_webserver" {
type = "map"
default = {
testing = "t2.small"
qa = "t2.medium"
staging = "t2.xlarge"
production = "t2.xlarge"
}
}
...
resource "aws_opsworks_instance" "verification" {
stack_id = "${aws_opsworks_stack.verification.id}"
layer_ids = ["${aws_opsworks_custom_layer.verification.id}"]
instance_type = "${var.instance_types_webserver["${var.environment}"]}"
state = "running"
count = 1
}
在 .tfvars
文件中:
...
environment = "testing"
...
以下适用于 terraform 版本 0.11.7。此解决方案使用 map function.
resource "aws_instance" "web" {
...
tags = "${map(
"Name", "${var.role} ${var_env}",
"role", "${var.app_role}",
"${var.app_role}", "${var_env}"
)}"
}
更新
接受的答案描述了如何在现有地图中进行动态查找。对于使用动态键构建映射,在HCL2(0.12)中,您可以在键中使用带引号的插值表达式:
resource "aws_instance" "web" {
count = "${var.ec2_instance_count}"
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
tags = {
Name = "${var.role} ${var.env}"
role = "${var.app_role}"
"${var.app_role}" = "${var.env}" # <------ like this
}
}
还有一次issue #21566 is fixed, you can replace "${var.app_role}"
with (var.app_role)
, which is the method described in the documentation.
(与下面相同的警告也适用于此:如果 var.app_role
包含这些文字键之一作为其值,那么它将替换它。)
旧答案
接受的答案描述了如何在现有地图中进行动态查找。在 HCL2 (0.12) 中,使用动态键构建映射有两种方式:
For expressions + merge
您可以使用 for expressions to dynamically build a map from one or more variables for your keys, and then use that in combination with the merge
function 构建混合静态和动态键的新地图:
variable "app_role" {
type = string
}
locals {
tags = merge(
{
Name = "${var.role} ${var.env}"
role = "${var.app_role}"
},
{
for k in [var.app_role]: k => "${var.env}"
}
)
}
zipmap
或者,您可以使用 zipmap
一次性构建它:
locals {
tags = zipmap(
[
"Name",
"role",
var.app_role
],
[
"${var.role} ${var.env}",
var.app_role,
var.env
]
)
}
然后您可以在资源中使用此地图:
resource "aws_instance" "web" {
count = "${var.ec2_instance_count}"
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
tags = local.tags // or inline the above here
}
需要注意的是,如果 var.app_role
等于 "Name"
或 "role"
,那么它将覆盖您的静态值。您可以通过交换 merge
中的参数或重新排序 zipmap
中的列表来避免这种情况,但这种冲突更可能是配置错误,应在应用前发现并修复。
在 Terraform 中,我正在尝试创建一个模块,其中包含一个带有可变键的地图。我不确定这是否可行,但我尝试了以下但没有成功。
resource "aws_instance" "web" {
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
count = "${var.ec2_instance_count}"
tags {
Name = "${var.role} ${var_env}"
role = "${var.app_role}"
${var.app_role} = "${var_env}"
}
}
还有这个:
tags {
Name = "${var.role} ${var_env}"
}
tags."${var.role}" = "${var.env}"
有什么想法吗? Terraform 目前无法做到这一点吗?
terraform 插值语法支持(现在)lookup
function,允许您在地图中查找动态键。
使用它,我现在可以做类似的事情:
output "image_bucket_name" {
value = "${lookup(var.image_bucket_names, var.environment, "No way this should happen")}"
}
其中:
variable "image_bucket_names" {
type = "map"
default = {
development = "bucket-dev"
staging = "bucket-for-staging"
preprod = "bucket-name-for-preprod"
production = "bucket-for-production"
}
}
和environment
是一个简单的字符串变量。
我最近也需要动态设置标签键,并设法使用 zipmap
:
locals {
ec2_tag_keys = ["some/prefix/${var.some_var}", "another_tag"]
ec2_tag_vals = ["some value", "another value"]
}
resource "aws_instance", "foo" {
...
tags = "${zipmap(local.ec2_tag_keys, local.ec2_tag_vals)}"
}
它有点笨拙,但它确实有效。
我不确定它是什么时候添加的,但至少从 0.11.7 版本开始,Terraform 支持使用变量作为映射键。这是我目前如何将其用于 select AWS 实例类型的示例:
在 .tf
文件中:
variable "environment" {}
...
variable "instance_types_webserver" {
type = "map"
default = {
testing = "t2.small"
qa = "t2.medium"
staging = "t2.xlarge"
production = "t2.xlarge"
}
}
...
resource "aws_opsworks_instance" "verification" {
stack_id = "${aws_opsworks_stack.verification.id}"
layer_ids = ["${aws_opsworks_custom_layer.verification.id}"]
instance_type = "${var.instance_types_webserver["${var.environment}"]}"
state = "running"
count = 1
}
在 .tfvars
文件中:
...
environment = "testing"
...
以下适用于 terraform 版本 0.11.7。此解决方案使用 map function.
resource "aws_instance" "web" {
...
tags = "${map(
"Name", "${var.role} ${var_env}",
"role", "${var.app_role}",
"${var.app_role}", "${var_env}"
)}"
}
更新
接受的答案描述了如何在现有地图中进行动态查找。对于使用动态键构建映射,在HCL2(0.12)中,您可以在键中使用带引号的插值表达式:
resource "aws_instance" "web" {
count = "${var.ec2_instance_count}"
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
tags = {
Name = "${var.role} ${var.env}"
role = "${var.app_role}"
"${var.app_role}" = "${var.env}" # <------ like this
}
}
还有一次issue #21566 is fixed, you can replace "${var.app_role}"
with (var.app_role)
, which is the method described in the documentation.
(与下面相同的警告也适用于此:如果 var.app_role
包含这些文字键之一作为其值,那么它将替换它。)
旧答案
接受的答案描述了如何在现有地图中进行动态查找。在 HCL2 (0.12) 中,使用动态键构建映射有两种方式:
For expressions + merge
您可以使用 for expressions to dynamically build a map from one or more variables for your keys, and then use that in combination with the merge
function 构建混合静态和动态键的新地图:
variable "app_role" {
type = string
}
locals {
tags = merge(
{
Name = "${var.role} ${var.env}"
role = "${var.app_role}"
},
{
for k in [var.app_role]: k => "${var.env}"
}
)
}
zipmap
或者,您可以使用 zipmap
一次性构建它:
locals {
tags = zipmap(
[
"Name",
"role",
var.app_role
],
[
"${var.role} ${var.env}",
var.app_role,
var.env
]
)
}
然后您可以在资源中使用此地图:
resource "aws_instance" "web" {
count = "${var.ec2_instance_count}"
ami = "${var.base_ami}"
availability_zone = "${var.region_a}"
instance_type = "${var.ec2_instance_size}"
security_groups = ["sec1"]
tags = local.tags // or inline the above here
}
需要注意的是,如果 var.app_role
等于 "Name"
或 "role"
,那么它将覆盖您的静态值。您可以通过交换 merge
中的参数或重新排序 zipmap
中的列表来避免这种情况,但这种冲突更可能是配置错误,应在应用前发现并修复。