Terraform配置aws_iam_policy依赖后for_each仍报未知属性错误如何解决?
问题根源
你配置的depends_on完全不解决该问题,这个报错和资源依赖顺序无关,是Terraform的固有规则限制:for_each使用的集合中所有元素值必须在执行plan阶段就可以完全确定,不能引用需要apply之后才会生成的资源属性。
你当前传入模块的policies参数是三个IAM策略的ARN,而AWS IAM策略的ARN属于资源创建完成后才会生成的属性,plan阶段属于未知值。Terraform在解析模块内的toset(var.policies)时,无法确定集合的元素数量、每个元素的具体值,也就没法为aws_iam_role_policy_attachment预先生成实例索引,因此直接抛出报错。
额外提一句:你已经把IAM策略的ARN作为入参传入模块,Terraform会自动维护资源依赖关系,手动加的depends_on声明完全是多余的,可以直接删掉。
可行解决方案
方案1:改用count遍历(适合策略列表固定的场景)
将模块内的aws_iam_role_policy_attachment资源从for_each改为count遍历:
resource "aws_iam_role_policy_attachment" "me" { count = length(var.policies) role = aws_iam_role.me.name policy_arn = var.policies[count.index] }
该方案的缺点是如果后续调整policies列表的元素顺序,会触发已有绑定关系的销毁重建。
方案2:改用map类型传参(推荐)
把传入的policies参数从列表改为Map结构,用你自定义的、plan阶段已知的策略名称作为Map的键,ARN作为值:
模块调用侧调整:
module "admin" { source = "./my_repo/admin" policies = { common = aws_iam_policy.common.arn ses_sending = aws_iam_policy.ses_sending.arn athena_readonly = aws_iam_policy.athena_readonly.arn } }
模块内调整:
首先把var.policies的类型声明改为map(string),然后修改资源配置:
resource "aws_iam_role_policy_attachment" "me" { for_each = var.policies role = aws_iam_role.me.name policy_arn = each.value }
该方案中for_each使用的实例索引是你手动定义的已知键,plan阶段不需要等待ARN生成就可以完成解析,不会触发报错,后续调整策略列表也不会影响已有的绑定关系。
内容的提问来源于stack exchange,提问作者Daniele

