如果数据中的用户不存在,地形会失败吗?我需要通过数据块指定非生产环境中的用户:
data "aws_iam_user" "labUser" {
user_name = "gitlab_user"
}
然后我使用这个用户来授予用户权限:
resource "aws_iam_role" "ApiAccessRole_abc" {
name = "${var.stack}-ApiAccessRole_abc"
tags = "${var.tags}"
assume_role_policy = <<EOF
{
"Version": "2019-11-29",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"AWS": [
"${aws_iam_user.labUser.arn}"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
生产环境中不存在该用户。如果这个用户不存在,地形会崩溃吗?在两种环境中使用相同地形的好方法是什么?
在Terraform中,您在这里展示的data
块既是一种获取数据的机制,也是作者(您)的断言,即为了使此配置适用,期望存在特定的外部对象。
在您的例子中,答案是确保对象存在的断言只出现在应该存在的情况下。"大局"对这个问题的回答是查看模块组合指南,并考虑是否应该将模块的这一部分分解为一个单独的模块,如果它不是总是嵌入其中的模块的一部分,但我也将展示一个较小的解决方案,使用条件表达式来获得您想要的行为,而无需任何重构:
variable "lab_user" {
type = string
default = null
}
data "aws_iam_user" "lab_user" {
count = length(var.lab_user[*])
user_name = var.lab_user
}
resource "aws_iam_role" "api_access_role_abc" {
count = length(data.aws_iam_user.lab_user)
name = "${var.stack}-ApiAccessRole_abc"
tags = var.tags
assume_role_policy = jsonencode({
Version = "2019-11-29"
Statement = [
{
Sid = ""
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
AWS = [data.aws_iam_user.lab_user[count.index].arn]
}
},
]
})
}
上面有一些不同的东西,我想提请注意:
- 我将实验室用户名作为可选变量,而不是硬编码值。您可以通过为
lab_user
变量分配不同的值来改变环境之间的行为,或者在不需要"实验室用户"的环境中完全不设置它。 - 在
data "aws_iam_user"
中,我将计数设置为length(var.lab_user[*])
。这里的[*]
操作符要求Terraform将可能为空的字符串变量var.lab_user
转换为零或一个元素的列表,然后使用该列表的长度来决定要进行多少aws_iam_user
查询。如果var.lab_user
是null
,那么长度将为零,因此不会进行查询。 - 最后,我设置
aws_iam_role
资源的count
以匹配aws_iam_user
数据结果的长度,因此在任何情况下,预期有一个用户也将创建一个角色。
如果你反思模块组成指南,并得出结论,这个实验室用户应该是一个单独的关注在一个单独的模块,那么你就可以从"gitlab用户"中删除这种条件复杂性。模块本身,并根据该环境是否需要这样的用户,让调用模块调用该模块或不调用该模块。效果将是相同的,但是决策将发生在配置的不同部分,因此它将实现不同的关注点分离。哪一种关注点分离最适合您的系统,最终,您需要根据您对系统的了解以及您对系统未来发展的期望为自己做出权衡。
正如评论中建议的那样,它将失败。
我可以建议的一种方法是提供用户名作为从文件dev.tfvars和prod.tfvars外部传递的变量,并运行terraform:
terraform apply --var-file example.tfvars
然后在你的数据资源中,你可以有一个计数或for_each来检查变量是否被填充(如果var没有被传递,你可以跳过数据插值)
count = var.enable_gitlab_user ? 1 : 0
AWS的直接方法是从主体中的IAM用户切换到基于标签的条件甚至角色链。您可以看看这篇AWS博客文章,从中获得一些想法。