Terraform未检测到Azure APIM中手动删除的操作与定义问题
我使用Terraform管理Azure APIM API,期望底层App Service变更时,通过App Service的Swagger URL自动更新对应APIM API定义。我的Terraform代码如下:
resource "azurerm_api_management_api" "apimapi" { api_management_name = var.api_management_name api_type = "http" description = null display_name = var.display_name name = lower(var.display_name) path = lower(var.display_name) protocols = ["https"] resource_group_name = var.resource_group_name revision = "1" revision_description = null service_url = var.service_url source_api_id = null subscription_required = true terms_of_service_url = null version = null version_description = null version_set_id = null subscription_key_parameter_names { header = "Ocp-Apim-Subscription-Key" query = "subscription-key" } import { content_format = "openapi+json" content_value = data.http.contracts.response_body } } data "http" "contracts" { url = "${var.service_url}swagger/v1/swagger.json" request_headers = { Accept = "application/json" } }
遇到的问题:手动删除该API中的任意操作(Operations)或定义(Definitions)后,运行terraform plan却提示「No changes. Your infrastructure matches the configuration.」,无法检测到变更并更新;但如果在Azure门户手动修改service_url这类属性,Terraform能正常检测到变更并建议更新。
核心原因
Terraform的AzureRM Provider在处理azurerm_api_management_api资源的import块时,不会将Swagger导入的操作、定义等细节作为资源状态的一部分跟踪。它仅校验资源的顶层属性(如service_url、display_name),不会对比导入的Swagger内容与当前APIM API实际操作/定义的差异。
简单来说,Terraform只记录了「要从指定Swagger导入API」这个配置动作,不会把导入后的具体操作、定义存入状态文件,因此无法检测到这些内容的手动删除变更。
解决方案
显式定义子资源
放弃import块批量导入的方式,改用azurerm_api_management_api_operation、azurerm_api_management_api_schema等子资源,逐个定义API的操作、模型等内容。这种方式下,Terraform会跟踪每个子资源的状态,一旦手动删除,terraform plan就能检测到并触发重建。强制触发重新导入
如果坚持使用import块批量导入,可以通过修改revision值(比如从1改为2),或添加/修改revision_description这类不影响功能的属性,强制Terraform重新执行Swagger导入操作,覆盖手动删除的内容。但这种方式需要手动调整参数,自动化程度较低。外部脚本配合触发更新
编写外部脚本定期对比Swagger内容与APIM当前API定义的差异,将Swagger内容的哈希值作为null_resource的triggers参数。当Swagger内容变更时,自动触发API的重新导入操作,实现自动化更新。
内容的提问来源于stack exchange,提问作者Ajinkya Bapat

