Terraform Неверный аргумент подсчета, который зависит от другого ресурса - PullRequest
1 голос
/ 12 февраля 2020

Я получаю следующую ошибку при попытке составить план или заявку на сценарий 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.

Я понимаю, что это сбрасывается, потому что он не знает счет для числа правил брандмауэра, чтобы создать, пока app_service не будет создан. Я могу просто запустить apply с аргументом -target=azurerm_app_service.app_service, а затем запустить другое приложение после создания app_service.

Однако это не очень хорошо для нашего процесса CI, если мы хотим создать целое новую среду из наших скриптов terraform, мы хотели бы просто сказать terraform просто go построить ее без необходимости указывать ей каждую цель для построения по порядку.

Есть ли способ в terraform просто сказать go построить все, что нужно для того, чтобы не добавлять цели?

Также ниже приведен пример сценария 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))
}

1 Ответ

1 голос
/ 13 февраля 2020

Чтобы это работало без обходного пути -target, описанного в сообщении об ошибке, необходимо переосмыслить проблему в терминах значений, которые Terraform может знать только из конфигурации, а не значений, которые генерируются поставщиками во время применения.

Хитрость заключается в том, чтобы выяснить, какие значения в вашей конфигурации Azure API использует для принятия решения , сколько IP-адресов возвращать и полагаться на этих вместо. Я не знаю Azure достаточно хорошо, чтобы дать вам конкретный c ответ, но на Входящие / Исходящие IP-адреса я вижу, что это, скорее, операционная деталь Azure Служб приложений чем-то, чем вы можете управлять сами, и поэтому, к сожалению, эта проблема не может быть решена.

Если на самом деле нет способа предсказать из конфигурации, сколько адресов будет в possible_outbound_ip_addresses, альтернативой является разделение вашей конфигурации. на две части, где одна зависит от другой. Первая конфигурирует вашу Службу приложений и все остальное, что имеет смысл управлять вместе с ней, а затем вторая может использовать azurerm_app_service источник данных для извлечения данных о предполагаемой уже существующей службе приложения. и создайте правила брандмауэра на его основе.

В любом случае вам потребуется дважды запустить Terraform, чтобы сделать необходимые данные доступными. Преимущество использования -target заключается в том, что вам нужно всего лишь один раз выполнить забавный рабочий процесс во время начальной начальной загрузки, и поэтому вы потенциально можете выполнить первоначальное создание вне CI, чтобы получить объекты, которые были изначально созданы, а затем использовать CI для текущих изменений. До тех пор, пока объект службы приложения никогда не будет заменен, последующие планы Terraform уже будут знать, сколько IP-адресов установлено, и поэтому должны иметь возможность выполнить их как обычно.

...