尝试在 terraform 脚本上执行计划或应用时出现以下错误。
Error: Invalid count argument
on main.tf line 157, in resource "azurerm_sql_firewall_rule" "sqldatabase_onetimeaccess_firewall_rule":
157: count = length(split(",", azurerm_app_service.app_service.possible_outbound_ip_addresses))
The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.
Run Code Online (Sandbox Code Playgroud)
我知道这会失败,因为在创建 app_service 之前它不知道要创建的防火墙规则的数量。我可以使用apply参数运行,-target=azurerm_app_service.app_service然后在创建 app_service 后运行另一个应用。
然而,这对于我们的 CI 流程来说并不是很好,如果我们想从 terraform 脚本创建一个全新的环境,我们只想告诉 terraform 去构建它,而不必告诉它每个目标按顺序构建。
terraform 中是否有一种方法可以只说按顺序构建所需的所有内容,而无需添加目标?
下面也是一个示例 terraform 脚本,它给出了上述错误:
provider "azurerm" {
version = "=1.38.0"
}
resource "azurerm_resource_group" "resourcegroup" {
name = "rg-stackoverflow60187000"
location = "West Europe"
}
resource "azurerm_app_service_plan" "service_plan" {
name = "plan-stackoverflow60187000"
resource_group_name = azurerm_resource_group.resourcegroup.name
location = azurerm_resource_group.resourcegroup.location
kind = "Linux"
reserved = true
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "app_service" {
name = "app-stackoverflow60187000"
resource_group_name = azurerm_resource_group.resourcegroup.name
location = azurerm_resource_group.resourcegroup.location
app_service_plan_id = azurerm_app_service_plan.service_plan.id
site_config {
always_on = true
app_command_line = ""
linux_fx_version = "DOCKER|nginxdemos/hello"
}
app_settings = {
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
}
}
resource "azurerm_sql_server" "sql_server" {
name = "mysqlserver-stackoverflow60187000"
resource_group_name = azurerm_resource_group.resourcegroup.name
location = azurerm_resource_group.resourcegroup.location
version = "12.0"
administrator_login = "4dm1n157r470r"
administrator_login_password = "4-v3ry-53cr37-p455w0rd"
}
resource "azurerm_sql_database" "sqldatabase" {
name = "sqldatabase-stackoverflow60187000"
resource_group_name = azurerm_sql_server.sql_server.resource_group_name
location = azurerm_sql_server.sql_server.location
server_name = azurerm_sql_server.sql_server.name
edition = "Standard"
requested_service_objective_name = "S1"
}
resource "azurerm_sql_firewall_rule" "sqldatabase_firewall_rule" {
name = "App Service Access (${count.index})"
resource_group_name = azurerm_sql_database.sqldatabase.resource_group_name
server_name = azurerm_sql_database.sqldatabase.name
start_ip_address = element(split(",", azurerm_app_service.app_service.possible_outbound_ip_addresses), count.index)
end_ip_address = element(split(",", azurerm_app_service.app_service.possible_outbound_ip_addresses), count.index)
count = length(split(",", azurerm_app_service.app_service.possible_outbound_ip_addresses))
}
Run Code Online (Sandbox Code Playgroud)
要在没有-target错误消息中描述的解决方法的情况下实现此目的,需要根据 Terraform 只能从配置中获知的值(而不是提供程序在应用时生成的值)来重新构建问题。
关键是要弄清楚 Azure API 使用配置中的哪些值来决定要返回多少个 IP 地址,并依赖这些值。我对 Azure 的了解不够深,无法给你一个具体的答案,但我在入站/出站 IP 地址上看到,这似乎是 Azure 应用服务的操作细节,而不是你可以自己控制的东西,因此不幸的是,这个问题可能无法解决。
如果确实无法从配置中预测 中有多少个地址possible_outbound_ip_addresses,则另一种方法是将您的配置分成两部分,其中一个部分依赖于另一个部分。第一个将配置您的应用程序服务以及与之一起管理的任何其他内容,然后第二个可能使用数据azurerm_app_service源来检索有关假定已存在的应用程序服务的数据,并基于它制定防火墙规则。
无论哪种方式,您都需要运行 Terraform 两次才能获得必要的数据。使用的一个优点-target是,您只需要在初始引导期间执行一次有趣的工作流程,因此您可以在 CI 之外进行初始创建以获得最初创建的对象,然后使用 CI 进行持续更改。只要应用程序服务对象从未被替换,后续的 Terraform 计划就已经知道设置了多少个 IP 地址,因此应该能够正常完成。
| 归档时间: |
|
| 查看次数: |
6950 次 |
| 最近记录: |