Terraform 推测计划中的循环错误
Cyclic Error in Speculative Plan in Terraform
如果我在我的代码中放入以下行,我会收到以下错误:
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
错误:
Error: Cycle: local.network_acls_ip_rules (expand), module.key-vault.var.key_vault_network_acls_ip_rules (expand), module.key-vault.azurerm_key_vault.default, module.key-vault.output.key_vault (expand), azurerm_app_service.fe, azurerm_app_service.api
如果我不输入上面的行,我不会得到这个错误
我的前端应用服务的完整代码是:
resource "azurerm_app_service" "fe" {
location = module.resourcegroup.resource_group.location
resource_group_name = module.resourcegroup.resource_group.name
tags = local.tags
app_service_plan_id = azurerm_app_service_plan.default.id
name = module.name_app_service_fe.location.app_service.name_unique
identity { type = "SystemAssigned" }
auth_settings {
enabled = true
default_provider = "AzureActiveDirectory"
issuer = format("https://sts.windows.net/%s/", data.azurerm_client_config.default.tenant_id)
runtime_version = "~1"
token_store_enabled = true
unauthenticated_client_action = "RedirectToLoginPage"
allowed_external_redirect_urls = module.application_webapp_fe.application.self.reply_urls
additional_login_params = {
"response_type" = "code id_token",
"resource" = module.application_webapp_fe.application.self.application_id
}
active_directory {
client_id = module.application_webapp_fe.application.self.application_id
client_secret = module.application_webapp_fe.service_principal.secret.value
allowed_audiences = []
}
}
site_config {
always_on = true
app_command_line = ""
default_documents = []
dotnet_framework_version = "v4.0"
ftps_state = "Disabled"
health_check_path = ""
http2_enabled = true
linux_fx_version = "STATICSITE|1.0"
local_mysql_enabled = false
managed_pipeline_mode = "Integrated"
min_tls_version = "1.2"
#pre_warmed_instance_count = 0
python_version = "3.4"
remote_debugging_enabled = false
remote_debugging_version = "VS2019"
use_32_bit_worker_process = false
websockets_enabled = false
windows_fx_version = ""
cors {
allowed_origins = []
support_credentials = false
}
}
app_settings = {
"WEBSITE_DNS_SERVER" = "168.63.129.16"
"WEBSITE_VNET_ROUTE_ALL" = "1"
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
}
lifecycle {
ignore_changes = [
"site_config",
"auth_settings"
]
}
}
Key Vault 已有秘密名称:
Webapp-FE-Secret
secret的值是我的前端应用注册的Service Principal
下面是我的 Key Vault 模块的代码:
module "key-vault" {
version = "~> 1.0"
source = " xxxxx "
providers = { azurerm = azurerm, random = random }
tenant_id = data.azurerm_client_config.default.tenant_id
resource_group_name = module.resourcegroup.resource_group.name
key_vault_location = module.resourcegroup.resource_group.location
key_vault_environment = var.project.environment.name
key_vault_tags = module.resourcegroup.resource_group.tags
key_vault_name = substr(replace(var.project.name, "-", ""), 0, 16)
key_vault_network_acls_ip_rules = concat(local.network_acls_ip_rules, module.project.azure.cidrs.global.contoso_enterprise_egress.all.coreinf)
key_vault_network_acls_virtual_network_subnet_ids = [local.tfe_vnet_id]
key_vault_secrets = {
CosmosDB-PrimaryKey = azurerm_cosmosdb_account.default.primary_key
CosmosDB-PrimaryReadOnlykey = azurerm_cosmosdb_account.default.primary_readonly_key
CosmosDB-PrimaryKey-ConnectionString = azurerm_cosmosdb_account.default.connection_strings[0]
CosmosDB-PrimaryReadOnlykey-ConnectionString = azurerm_cosmosdb_account.default.connection_strings[1]
StorageAccount-PrimaryKey = module.storageaccount.storage_account.self.primary_access_key
StorageAccount-SecondaryKey = module.storageaccount.storage_account.self.secondary_access_key
StorageAccount-ConnectionString-PrimaryKey = module.storageaccount.storage_account.self.primary_connection_string
StorageAccount-ConnectionString-SecondaryKey = module.storageaccount.storage_account.self.secondary_connection_string
StorageAccount-FunctionApp-PrimaryKey = module.storageaccount-func-app.storage_account.self.primary_access_key
StorageAccount-FunctionApp-SecondaryKey = module.storageaccount-func-app.storage_account.self.secondary_access_key
StorageAccount-FunctionApp-ConnectionString-PrimaryKey = module.storageaccount-func-app.storage_account.self.primary_connection_string
StorageAccount-FunctionApp-ConnectionString-SecondaryKey = module.storageaccount-func-app.storage_account.self.secondary_connection_string
Webapp-FE-Secret = module.application_webapp_fe.service_principal.secret.value
Webapp-API-Secret = module.application_webapp_api.service_principal.secret.value
Function-App-Secret = module.application_func_01.service_principal.secret.value
frontendappid = module.application_webapp_fe.application.self.application_id
frontendappurl = module.application_webapp_fe.application.self.homepage
frontendhost = format("https://%s", azurerm_app_service.fe.default_site_hostname)
appi-default-instrumentation-key = azurerm_application_insights.default["api"].instrumentation_key
appi-default-app-id = azurerm_application_insights.default["api"].app_id
appi-default-fe-instrumentation-key = azurerm_application_insights.default["fe"].instrumentation_key
appi-default-fe-app-id = azurerm_application_insights.default["fe"].app_id
functionappid = module.application_func_01.application.self.application_id
functionappurl = module.application_func_01.application.self.homepage
functionhost = format("https://%s", azurerm_function_app.default.default_hostname)
webapiappid = module.application_webapp_api.application.self.application_id
webapiappuri = module.application_webapp_api.application.self.homepage
webapihost = format("https://%s", azurerm_app_service.api.default_site_hostname)
}
}
本地区块:
locals {
network_acls_ip_rules = distinct(
concat(
formatlist("%s/32", split(",", azurerm_app_service.api.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.api.outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_function_app.default.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_function_app.default.outbound_ip_addresses))
)
)
}
谁能帮我解决这个问题。
值:"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET
已手动放入前端应用程序中,目前在 TF 状态下丢失。所以我想将它包含在我的代码中,这样 Terraform 就不会在我每次对我的代码进行迭代时消失
通过包括这一行:
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
您已经创建了一个循环引用,因为前端应用程序和 Keyvault 相互依赖(例如,一个不能先于另一个构建)
发生循环引用是因为 local.network_acl_ip_rules
中也有这些行
formatlist("%s/32", split(",", azurerm_app_service.fe.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.outbound_ip_addresses)),
因此需要创建前端应用程序服务以填充创建 Keyvault 所需的那些 IP 值。但是无法创建前端,因为它需要应用程序设置中的 Keyvault 名称。
快速解决方法是将 Keyvault 名称硬编码到应用程序设置中。
长期“修复”将是使用 az cli 或 powershell 脚本在 terraform 之外更新 appsettings
或 network_acls
并从 terraform 调用脚本...
如果我在我的代码中放入以下行,我会收到以下错误:
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
错误:
Error: Cycle: local.network_acls_ip_rules (expand), module.key-vault.var.key_vault_network_acls_ip_rules (expand), module.key-vault.azurerm_key_vault.default, module.key-vault.output.key_vault (expand), azurerm_app_service.fe, azurerm_app_service.api
如果我不输入上面的行,我不会得到这个错误
我的前端应用服务的完整代码是:
resource "azurerm_app_service" "fe" {
location = module.resourcegroup.resource_group.location
resource_group_name = module.resourcegroup.resource_group.name
tags = local.tags
app_service_plan_id = azurerm_app_service_plan.default.id
name = module.name_app_service_fe.location.app_service.name_unique
identity { type = "SystemAssigned" }
auth_settings {
enabled = true
default_provider = "AzureActiveDirectory"
issuer = format("https://sts.windows.net/%s/", data.azurerm_client_config.default.tenant_id)
runtime_version = "~1"
token_store_enabled = true
unauthenticated_client_action = "RedirectToLoginPage"
allowed_external_redirect_urls = module.application_webapp_fe.application.self.reply_urls
additional_login_params = {
"response_type" = "code id_token",
"resource" = module.application_webapp_fe.application.self.application_id
}
active_directory {
client_id = module.application_webapp_fe.application.self.application_id
client_secret = module.application_webapp_fe.service_principal.secret.value
allowed_audiences = []
}
}
site_config {
always_on = true
app_command_line = ""
default_documents = []
dotnet_framework_version = "v4.0"
ftps_state = "Disabled"
health_check_path = ""
http2_enabled = true
linux_fx_version = "STATICSITE|1.0"
local_mysql_enabled = false
managed_pipeline_mode = "Integrated"
min_tls_version = "1.2"
#pre_warmed_instance_count = 0
python_version = "3.4"
remote_debugging_enabled = false
remote_debugging_version = "VS2019"
use_32_bit_worker_process = false
websockets_enabled = false
windows_fx_version = ""
cors {
allowed_origins = []
support_credentials = false
}
}
app_settings = {
"WEBSITE_DNS_SERVER" = "168.63.129.16"
"WEBSITE_VNET_ROUTE_ALL" = "1"
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
}
lifecycle {
ignore_changes = [
"site_config",
"auth_settings"
]
}
}
Key Vault 已有秘密名称:
Webapp-FE-Secret
secret的值是我的前端应用注册的Service Principal
下面是我的 Key Vault 模块的代码:
module "key-vault" {
version = "~> 1.0"
source = " xxxxx "
providers = { azurerm = azurerm, random = random }
tenant_id = data.azurerm_client_config.default.tenant_id
resource_group_name = module.resourcegroup.resource_group.name
key_vault_location = module.resourcegroup.resource_group.location
key_vault_environment = var.project.environment.name
key_vault_tags = module.resourcegroup.resource_group.tags
key_vault_name = substr(replace(var.project.name, "-", ""), 0, 16)
key_vault_network_acls_ip_rules = concat(local.network_acls_ip_rules, module.project.azure.cidrs.global.contoso_enterprise_egress.all.coreinf)
key_vault_network_acls_virtual_network_subnet_ids = [local.tfe_vnet_id]
key_vault_secrets = {
CosmosDB-PrimaryKey = azurerm_cosmosdb_account.default.primary_key
CosmosDB-PrimaryReadOnlykey = azurerm_cosmosdb_account.default.primary_readonly_key
CosmosDB-PrimaryKey-ConnectionString = azurerm_cosmosdb_account.default.connection_strings[0]
CosmosDB-PrimaryReadOnlykey-ConnectionString = azurerm_cosmosdb_account.default.connection_strings[1]
StorageAccount-PrimaryKey = module.storageaccount.storage_account.self.primary_access_key
StorageAccount-SecondaryKey = module.storageaccount.storage_account.self.secondary_access_key
StorageAccount-ConnectionString-PrimaryKey = module.storageaccount.storage_account.self.primary_connection_string
StorageAccount-ConnectionString-SecondaryKey = module.storageaccount.storage_account.self.secondary_connection_string
StorageAccount-FunctionApp-PrimaryKey = module.storageaccount-func-app.storage_account.self.primary_access_key
StorageAccount-FunctionApp-SecondaryKey = module.storageaccount-func-app.storage_account.self.secondary_access_key
StorageAccount-FunctionApp-ConnectionString-PrimaryKey = module.storageaccount-func-app.storage_account.self.primary_connection_string
StorageAccount-FunctionApp-ConnectionString-SecondaryKey = module.storageaccount-func-app.storage_account.self.secondary_connection_string
Webapp-FE-Secret = module.application_webapp_fe.service_principal.secret.value
Webapp-API-Secret = module.application_webapp_api.service_principal.secret.value
Function-App-Secret = module.application_func_01.service_principal.secret.value
frontendappid = module.application_webapp_fe.application.self.application_id
frontendappurl = module.application_webapp_fe.application.self.homepage
frontendhost = format("https://%s", azurerm_app_service.fe.default_site_hostname)
appi-default-instrumentation-key = azurerm_application_insights.default["api"].instrumentation_key
appi-default-app-id = azurerm_application_insights.default["api"].app_id
appi-default-fe-instrumentation-key = azurerm_application_insights.default["fe"].instrumentation_key
appi-default-fe-app-id = azurerm_application_insights.default["fe"].app_id
functionappid = module.application_func_01.application.self.application_id
functionappurl = module.application_func_01.application.self.homepage
functionhost = format("https://%s", azurerm_function_app.default.default_hostname)
webapiappid = module.application_webapp_api.application.self.application_id
webapiappuri = module.application_webapp_api.application.self.homepage
webapihost = format("https://%s", azurerm_app_service.api.default_site_hostname)
}
}
本地区块:
locals {
network_acls_ip_rules = distinct(
concat(
formatlist("%s/32", split(",", azurerm_app_service.api.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.api.outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_function_app.default.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_function_app.default.outbound_ip_addresses))
)
)
}
谁能帮我解决这个问题。
值:"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET
已手动放入前端应用程序中,目前在 TF 状态下丢失。所以我想将它包含在我的代码中,这样 Terraform 就不会在我每次对我的代码进行迭代时消失
通过包括这一行:
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = format("@Microsoft.KeyVault(VaultName=%s;SecretName=Webapp-FE-Secret)", module.key-vault.key_vault.self.name)
您已经创建了一个循环引用,因为前端应用程序和 Keyvault 相互依赖(例如,一个不能先于另一个构建)
发生循环引用是因为 local.network_acl_ip_rules
formatlist("%s/32", split(",", azurerm_app_service.fe.possible_outbound_ip_addresses)),
formatlist("%s/32", split(",", azurerm_app_service.fe.outbound_ip_addresses)),
因此需要创建前端应用程序服务以填充创建 Keyvault 所需的那些 IP 值。但是无法创建前端,因为它需要应用程序设置中的 Keyvault 名称。
快速解决方法是将 Keyvault 名称硬编码到应用程序设置中。
长期“修复”将是使用 az cli 或 powershell 脚本在 terraform 之外更新 appsettings
或 network_acls
并从 terraform 调用脚本...