使用自定义Terraform Provider实现特定模块销毁后调用API的问题咨询
解决方案
以下提供两种可行方案,可根据实际场景选择:
方案1:调整Terraform配置(无需修改Provider代码)
核心是通过调整依赖关系和生命周期规则,反转销毁顺序:
- 给
module-a添加显式依赖指向custom_resource_destroy,给custom_resource_destroy添加特殊生命周期规则 - 调整后的核心配置如下:
module "module-a" { source = "./module-a" # 显式声明依赖,让销毁时先处理module-a,再处理destroy自定义资源 depends_on = [custom_resource_destroy.module-a-destroy] } resource "custom_resource_destroy" "module-a-destroy" { output = "${module.module-a.output}" lifecycle { create_before_destroy = true # 忽略output字段变更,避免module-a创建后触发自定义资源重建 ignore_changes = [output] } }
- 调整后直接执行
terraform destroy -target=module.module-a即可,Terraform会先销毁module-a的全部资源,再执行custom_resource_destroy的Delete逻辑触发API调用。
方案2:调整自定义Provider代码(适配性更强,不受依赖/参数影响)
核心是在销毁逻辑中添加资源校验步骤,确认module-a完全销毁后再发送API请求,不需要调整现有Terraform配置:
- 在
custom_resource_destroy的Delete方法中添加轮询校验逻辑,先查询module-a关联的所有资源是否已经销毁,校验通过后再发送业务API - 修改后的代码示例:
import ( "fmt" "time" ) func resourceCustomResourceDestroyDelete(d *schema.ResourceData, m interface{}) error { moduleOutput := d.Get("output").(string) // 可按需调整轮询间隔和超时时间 timeout := time.After(30 * time.Minute) ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for { select { case <-timeout: return fmt.Errorf("wait module-a destroy timeout") case <-ticker.C: // 此处替换为实际的资源校验逻辑,比如调用云厂商API查询module-a创建的资源是否全部清除 isDestroyed, err := checkModuleResourcesDestroyed(moduleOutput) if err != nil { return err } if isDestroyed { // 校验通过后发送销毁完成的API请求 return sendDestroyNotifyAPI(moduleOutput) } } } }
- 该方案不受
-target参数、依赖关系变更的影响,可靠性更高。
内容的提问来源于stack exchange,提问作者Sureshkumar Menon
相关产品推荐
相关产品推荐

