问题描述
我在尝试在 terraform 中自动化标记过程时遇到了一个特定问题。我已经设置了一个环境变量,它本质上是我们将用于应用程序中提供的所有资源的所有标签的列表。看起来像这样...
export TF_VAR_taglist='{JiraEpic = "ETOS-56","AssignedResearcherPri" = "Isaac",AssignedResearcherSec = "Matt"}'
设置环境变量后,我在 variables.tf 文件中添加了一个名为“taglist”的变量,用于获取上述环境变量。看起来像这样...
variable "taglist"{}
最后,我有另一个 locals.tf 文件,我在其中设置了 common_tags 变量。像这样...
locals { common_tags ="${var.taglist}" }
当我应用 terraform 时,在尝试正确映射标签时构建失败。这是我收到的错误...
Error: Incorrect attribute value type
on kube_master_worker_nodes_ec2.tf line 9,in resource "aws_instance" "master":
9: tags = local.common_tags
|----------------
| local.common_tags is "{JiraEpic = \"ETOS-56\",AssignedResearcherPri = \"Isaac \",AssignedResearcherSec = \"Matt\"}"
Inappropriate value for attribute "tags": map of string required.
然后我决定像这样在 variables.tf 文件中将变量的类型定义为 map(string
variable "taglist"{ type = map(string) }
我曾希望这能让 terraform 将此变量识别为字符串映射而不仅仅是字符串文字,但我错了,这些是应用该定义时遇到的错误。
Error: Missing attribute separator
on <value for var.taglist> line 1:
(source code not available)
Expected a newline or comma to mark the beginning of the next attribute.
Error: No value for required variable
on variables.tf line 11:
11: variable "taglist"{
The root module input variable "taglist" is not set,and has no default value.
Use a -var or -var-file command line argument to provide a value for this
variable.
我真的被困在这个问题上,我觉得我已经接近了。任何人都可以对此提供一些见解以及我应该如何解决它?
解决方法
Terraform 使用变量的类型约束来决定如何解释其值的字符串表示。默认情况下,Terraform 将假定该值需要一个原始类型,例如字符串或数字,因为这是通过命令行或环境变量设置的变量的最典型情况。
由于您的标签列表是一个列表,您需要 Terraform 将其解释为地图表达式而不是字符串。您可以通过告诉 Terraform 您期望哪种类型的值来告诉 Terraform 这样做:
variable "taglist" {
type = map(string)
}
您可以在 Terraform 文档部分 Complex-typed Values 中阅读更多相关信息。
然后您需要确保环境变量中的值是有效的 object expression 以避免语法错误。如果您从 shell 命令行设置环境变量,那么您需要注意转义/引用,以确保 Terraform 将看到所有引号完整且没有任何额外元字符的值。
结果通常很难看清,这就是 Terraform 文档建议使用 .tfvars
文件来设置复杂类型变量的原因,而不是 -var
命令行选项或环境变量。但是,由于您使用的是自动化,您可能会发现更容易生成 .tfvars.json
文件,该文件使用标准 JSON 格式,因此使用大多数编程语言中可用的 JSON 库更容易生成。这是您在问题中显示的值的 .tfvars.json
等价物:
{
"taglist": {
"JiraEpic": "ETOS-56","AssignedResearcherPri": "Isaac","AssignedResearcherSec": "Matt"
}
}
请注意,主观上我会发现一个变量的名称以 list
结尾,而实际上它需要一个地图,这很令人困惑。这个变量的一个更典型的名字就是 tags
,不过如果提到它的类型以将它与其他变量区分开来很有用,那么我建议改用 tag_map
以减少混淆。
我首先要感谢 Martin Atkins 让我想到在我的环境变量中使用冒号而不是等号,因为那是唯一的问题。该变量未正确表示为 JSON 对象,因此 terraform 将其解释为字符串。
我变了
export TF_VAR_taglist='{JiraEpic = "ETOS-56","AssignedResearcherPri" = "Isaac",AssignedResearcherSec = "Matt"}'
到这里
export TF_VAR_taglist='{"JiraEpic":"ETOS-56","AssignedResearcherPri":"Isaac","AssignedResearcherSec":"Matt"}'
构建现在像猫薄荷上的小猫一样发出咕噜声。