Terraform条件表达式类型不一致问题求助(v0.14.8)
Terraform v0.14.8 AWS IAM角色条件表达式类型不一致错误解决求助
问题场景
使用Terraform v0.14.8编写AWS IAM角色资源代码时,在基于var.provision_capi_server_iam的内联三元表达式中执行terraform plan,出现类型不一致错误。已尝试将第75行的[]改为[{}],但问题未解决,求可行的解决建议。
代码片段
resource "aws_iam_role" "aws_iam_role_controllers" { assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = flatten([ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { Service = "ec2.amazonaws.com" } }, { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { AWS = "arn:aws:iam::xxxxxxxxxx:role/controllers.cluster-api-provider-aws.sigs.k8s.io" } }, var.provision_capi_server_iam ? [ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { AWS = "arn:aws:iam::${var.aws_account_id}:role/controllers.cluster-api-provider-aws.sigs.k8s.io" } }, { Action = "sts:AssumeRoleWithWebIdentity" Effect = "Allow" Sid = "" Principal = { Federated = "arn:aws:iam::${var.aws_account_id}:oidc-provider/${replace(data.aws_eks_cluster.eks_cluster[0].identity[0].oidc[0].issuer, "https://", "")}" } Condition = { "ForAnyValue:StringEquals" = { "${replace(data.aws_eks_cluster.eks_cluster[0].identity[0].oidc[0].issuer, "https://", "")}:sub" = [ "system:serviceaccount:capa-system:capa-controller-manager", "system:serviceaccount:capi-system:capi-controller-manager", "system:serviceaccount:capa-eks-control-plane-system:capa-eks-control-plane-controller-manager", "system:serviceaccount:capa-eks-bootstrap-system:capa-eks-bootstrap-controller-manager", ] } } } ] : [] ]) })
错误信息
Using a variables file to set an undeclared variable is deprecated and will become an error in a future release. If you wish to provide certain "global" settings to all configurations in your organization, use TF_VAR_... environment variables to set these instead. Warning: Values for undeclared variables In addition to the other similar warnings shown, 11 other variable(s) defined without being declared. Error: Inconsistent conditional result types on ../../../../../modules/capi-roles-and-policies/main.tf line 48, in resource "aws_iam_role" "aws_iam_role_controllers": 48: var.provision_capi_server_iam ? [ ... 75: ] : [] The true and false result expressions must have consistent types. The given expressions are tuple and tuple, respectively.
解决思路与方案
错误原因
Terraform 0.14的类型系统对三元表达式的类型一致性要求严格:true分支是包含两个结构明确的IAM Statement对象的元组,而false分支的空元组[]没有明确的元素类型约束,两者无法被推断为同一类型,从而触发错误。修改为[{}]无效,是因为空对象的结构与true分支的Statement对象结构不匹配(缺少Action、Effect等必填字段),类型依然不一致。
可行方案
方案1:重构代码结构,使用concat合并列表
将固定的Statement和条件性的Statement分别作为列表,用concat合并后再执行flatten,让Terraform更容易统一类型推断:
resource "aws_iam_role" "aws_iam_role_controllers" { assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = flatten(concat( // 固定的两个Statement [ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { Service = "ec2.amazonaws.com" } }, { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { AWS = "arn:aws:iam::xxxxxxxxxx:role/controllers.cluster-api-provider-aws.sigs.k8s.io" } } ], // 条件性的Statement列表 var.provision_capi_server_iam ? [ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { AWS = "arn:aws:iam::${var.aws_account_id}:role/controllers.cluster-api-provider-aws.sigs.k8s.io" } }, { Action = "sts:AssumeRoleWithWebIdentity" Effect = "Allow" Sid = "" Principal = { Federated = "arn:aws:iam::${var.aws_account_id}:oidc-provider/${replace(data.aws_eks_cluster.eks_cluster[0].identity[0].oidc[0].issuer, "https://", "")}" } Condition = { "ForAnyValue:StringEquals" = { "${replace(data.aws_eks_cluster.eks_cluster[0].identity[0].oidc[0].issuer, "https://", "")}:sub" = [ "system:serviceaccount:capa-system:capa-controller-manager", "system:serviceaccount:capi-system:capi-controller-manager", "system:serviceaccount:capa-eks-control-plane-system:capa-eks-control-plane-controller-manager", "system:serviceaccount:capa-eks-bootstrap-system:capa-eks-bootstrap-controller-manager", ] } } } ] : [] )) }) }
方案2:显式指定false分支的类型
通过类型构造器,强制将空元组转换为与true分支一致的元素类型:
// 在三元表达式的false分支,显式声明类型 var.provision_capi_server_iam ? [ // 两个Statement对象 ] : list(object({ Action = string Effect = string Sid = string Principal = map(string) Condition = optional(map(any)) }))([])
这种方式直接告诉Terraform,false分支的空列表元素类型与true分支一致,解决类型推断冲突。
内容的提问来源于stack exchange,提问作者sss
相关产品推荐
相关产品推荐

