Terraform模块创建如何按条件终止?precondition使用报错求助
问题描述
尝试在Terraform的module块中使用precondition钩子检查输入参数,代码如下:
module "groups" { source = "../path/to/groups" for_each = var.groups.groups name = each.key type = each.value.type policies = each.value.policies depends_on = [ module.policies ] lifecycle { precondition { condition = alltrue([ for item in self.policies : alltrue([ for p in item : contains(locals.policies_list, p) ]) ] ) error_message = format("Attempt to create a group with a non existing policy") } } }
Terraform版本信息:
{ "terraform_version": "1.3.7", "platform": "linux_amd64", "provider_selections": {}, "terraform_outdated": false }
运行时报错:
The block type name "lifecycle" is reserved for use by Terraform in a future version.
请问:Terraform的module创建是否不支持该功能?有没有办法实现基于上述条件让模块创建失败?
解决方案
1. 模块块不支持lifecycle/precondition
是的,当前Terraform版本(包括1.3.7)的module块不支持lifecycle块,报错信息明确说明该块类型为未来版本预留,暂未开放使用。
2. 实现参数校验的替代方案
方案一:在模块内部的变量定义中添加校验
修改模块的variables.tf文件,为policies变量添加validation块,在模块层面拦截无效参数:
variable "policies" { type = list(list(string)) # 根据实际参数类型调整 description = "Policies to attach to the group" validation { condition = alltrue([ for item in var.policies : alltrue([ for p in item : contains(locals.policies_list, p) ]) ]) error_message = "Attempt to create a group with a non existing policy." } }
注意:若locals.policies_list是调用模块的根模块本地值,需将其作为变量传入模块,因为模块无法直接访问根模块的本地值。
方案二:在调用模块前用断言检查
利用Terraform 1.3+支持的assert函数,在根模块中提前校验参数,不满足条件时直接终止执行:
# 提前校验所有传入的policies都属于合法列表 locals { validate_group_policies = assert( alltrue([ for group in var.groups.groups : alltrue([ for item in group.policies : alltrue([ for p in item : contains(locals.policies_list, p) ]) ]) ]), "Attempt to create a group with a non existing policy" ) } # 调用模块,此时断言已完成参数校验 module "groups" { source = "../path/to/groups" for_each = var.groups.groups name = each.key type = each.value.type policies = each.value.policies depends_on = [ module.policies ] }
该方案无需修改模块代码,直接在调用方完成校验,适合无法修改模块的场景。
方案三:在模块内部的资源块中使用precondition
如果模块内部有对应的业务资源(例如AWS的aws_iam_group),可将precondition添加到资源的lifecycle块中,在资源创建前校验参数:
# 模块内部的资源示例 resource "aws_iam_group" "this" { name = var.name lifecycle { precondition { condition = alltrue([ for item in var.policies : alltrue([ for p in item : contains(locals.policies_list, p) ]) ]) error_message = "Attempt to create a group with a non existing policy." } } }
这种方式会在资源创建阶段触发校验,同样能拦截无效参数。
内容的提问来源于stack exchange,提问作者pkaramol
相关产品推荐
相关产品推荐

