Как я могу использовать azurerm_resource_group_template_deployment для ресурса бюджета Azure, но игнорировать изменения даты начала и окончания?

Может быть связано: azurerm_resource_group_template_deployment игнорирует файл параметров

Я хотел бы использовать ресурс azurerm_resource_group_template_deployment из Terraform версии 0.37. Но есть проблема, заключающаяся в том, что Terraform хочет повторно применять ресурс каждый месяц, поэтому я подумал, что могу сказать игнорировать изменения даты начала и окончания, но для этого (в отличие от устаревшего ресурса azurerm_template_deployment) потребуется вычислительная операция, а именно jsondecode, что не разрешено. т.е. следующий код не будет работать.

terraform {
  required_version = "~> 0.13.0"
  required_providers {
    azurerm = "~> 2.37.0"
  }
}

provider azurerm {
  features {}
}

locals {
  budget_start_date = formatdate("YYYY-MM-01", timestamp())
  budget_end_date = formatdate("YYYY-MM-01", timeadd(timestamp(), "17568h"))
  budget_params = jsonencode({
    "budgetName" = "budgettest",
    "amount" = "4000",
    "timeGrain" = "Annually",
    "startDate" = local.budget_start_date,
    "endDate" = local.budget_end_date,
    "firstThreshold" = "75",
    "secondThreshold" = "100",
    "thirdThreshold" = "50",
    "contactGroups" = ""
  }) 
  }

resource "azurerm_resource_group" "rg" {
  # A subscription cannot have more than 980 resource groups:
  # https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits
  name = "example-rg"
  location = "westeurope"
}

resource "azurerm_resource_group_template_deployment" "dsw_budget" {
  name = "test-budget-template"
  resource_group_name = azurerm_resource_group.rg[0].name
  deployment_mode = "Incremental"

  template_content = file("${path.module}/arm/budget_deploy.json")

  parameters_content = local.budget_params
  
  lifecycle {
    ignore_changes = [
      jsondecode(parameters_content)["startDate"],
      jsondecode(parameters_content)["endDate"]
    ]
  }

}

Для полноты, содержание budget_deploy.json:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "budgetName": {
      "type": "string",
      "defaultValue": "MyBudget"
    },
    "amount": {
      "type": "string",
      "defaultValue": "1000"
    },
    "timeGrain": {
      "type": "string",
      "defaultValue": "Monthly",
      "allowedValues": [
        "Monthly",
        "Quarterly",
        "Annually"
      ]
    },
    "startDate": {
      "type": "string"
    },
    "endDate": {
      "type": "string"
    },
    "firstThreshold": {
      "type": "string",
      "defaultValue": "90"
    },
    "secondThreshold": {
      "type": "string",
      "defaultValue": "110"
    },
    "thirdThreshold": {
      "type": "string",
      "defaultValue": "80"
    },
    "contactEmails": {
      "type": "string",
      "defaultValue": ""
    },
    "contactGroups": {
      "type": "string",
      "defaultValue": ""
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "variables": {
    "groups": "[split(parameters('contactGroups'),',')]"
  },
  "resources": [
    {
      "name": "[parameters('budgetName')]",
      "type": "Microsoft.Consumption/budgets",
      "location": "[parameters('location')]",
      "apiVersion": "2019-10-01",
      "properties": {
        "timePeriod": {
          "startDate": "[parameters('startDate')]",
          "endDate": "[parameters('endDate')]"
        },
        "timeGrain": "[parameters('timeGrain')]",
        "amount": "[parameters('amount')]",
        "category": "Cost",
        "notifications": {
          "NotificationForExceededBudget1": {
            "enabled": true,
            "operator": "GreaterThan",
            "threshold": "[parameters('firstThreshold')]",
            "contactGroups": "[variables('groups')]"
          },
          "NotificationForExceededBudget2": {
            "enabled": true,
            "operator": "GreaterThan",
            "threshold": "[parameters('secondThreshold')]",
            "contactGroups": "[variables('groups')]"
          },
          "NotificationForExceededBudget3": {
            "enabled": true,
            "operator": "GreaterThan",
            "threshold": "[parameters('thirdThreshold')]",
            "contactGroups": "[variables('groups')]"
          }
        }
      }
    }
  ]
}

Есть ли способ, которым я все еще могу достичь своей цели? - Спасибо!

Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
0
961
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не думаю, что это правильно, как вы используете ignore_changes. Взгляните на жизненный цикл ignore_changes в для каждого ресурса. Это должно быть свойство ресурса, который вы хотите создать, а не значение. Кроме того, если вы хотите изменить ресурсы через шаблон Azure в Terraform, лучше использовать Incrementaldeployment_mode, а не изменять свойство, которое вы хотите игнорировать изменения.

Да, вы правы, к сожалению, я сделал ошибку копирования-вставки. Теперь все должно быть в порядке. Тем не менее, теперь я думаю, что лучший способ, вероятно, сохранить тег даты начала и даты окончания в Azure и использовать источник данных, чтобы увидеть, установлен ли тег уже или нет. Если он установлен, всегда используйте это значение. Или в terraform есть возможность не изменять значение переменной после ее установки? Вероятно, это противоречит принципам переменных, но в данном случае это было бы полезно...

mgross 16.12.2020 22:15

@mgross В ссылке, которую я указал в ответе, есть пример тегов в ignore_changes.

Charles Xu 17.12.2020 02:48

@mgross Есть новости по этому вопросу? Это решает вашу проблему?

Charles Xu 18.12.2020 09:45

Я не уверен, что у нас возникло недопонимание: я просто хочу, чтобы дата начала и окончания не менялись для существующей группы ресурсов, пока она не будет прекращена. Вот почему я разместил ответ ниже о том, как я думаю, что решу это.

mgross 18.12.2020 16:19

@mgross Как это работает, пока не объявлено устаревшим в azurerm_template_deployment? Даты начала и окончания являются тегами для группы?

Charles Xu 21.12.2020 03:33

Нет, я могу использовать ignore_changes = [parameters["startDate"], parameters["endDate"] ], потому что параметры не обязательно должны быть закодированы в json.

mgross 21.12.2020 08:43

@mgross Для свойств группы нет даты начала и окончания. Это должен быть тег для группы.

Charles Xu 21.12.2020 10:37

@mgross Я думаю, что раньше вы использовали игнорирование параметров в шаблоне, но если вы не хотите изменять теги существующей группы, вам нужно сделать это так, как я сказал.

Charles Xu 22.12.2020 08:13
Ответ принят как подходящий

Я прибегал к использованию тегов для даты окончания и начала бюджета. ignore_changes будет работать для устаревшего azurerm_template_deployment, поскольку в этом случае параметры имеют тип map, а не тип json, например:

terraform {
  required_version = "~> 0.13.0"
  required_providers {
    azurerm = "~> 2.37.0"
  }
}

provider azurerm {
  features {}
}

locals {
  budget_start_date = formatdate("YYYY-MM-01", timestamp())
  budget_end_date = formatdate("YYYY-MM-01", timeadd(timestamp(), "17568h"))
  budget_params = {
    "budgetName" = "budgettest",
    "amount" = "4000",
    "timeGrain" = "Annually",
    "startDate" = local.budget_start_date,
    "endDate" = local.budget_end_date,
    "firstThreshold" = "75",
    "secondThreshold" = "100",
    "thirdThreshold" = "50",
    "contactGroups" = ""
  }
  }

resource "azurerm_resource_group" "rg" {
  # A subscription cannot have more than 980 resource groups:
  # https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits
  name = "example-rg"
  location = "westeurope"
}

resource "azurerm_template_deployment" "dsw_budget" {
  name = "test-budget-template"
  resource_group_name = azurerm_resource_group.rg[0].name
  deployment_mode = "Incremental"

  template_content = file("${path.module}/arm/budget_deploy.json")

  parameters_content = local.budget_params
  
  lifecycle {
    ignore_changes = [
      parameters["startDate"],
      parameters["endDate"]
    ]
  }

}

Теперь это невозможно с azurerm_resource_group_template_deployment, так как содержимое json должно быть передано, и поэтому в ignore_changes необходимо будет выполнить json-декодирование, которое является вычислительной операцией, что не разрешено.

Поэтому, чтобы решить мою проблему фиксации дат начала и окончания, я прибегнул к использованию тегов для даты начала и окончания и источнику данных, запрашивающему их:

terraform {
  required_version = "~> 0.13.0"
  required_providers {
    azurerm = "~> 2.37.0"
  }
}

provider azurerm {
  features {
    template_deployment {
      delete_nested_items_during_deletion = false
    }
  }
}

data "azurerm_resources" "aml" {
  resource_group_name = "${var.tk_name_id}-${local.stage}-rg"
  type = "Microsoft.MachineLearningServices/workspaces"
}


locals {
  budget_start_date_tag = try(element(data.azurerm_resources.aml.resources[*].tags.budget_start_date, 0), "NA")
  budget_end_date_tag = try(element(data.azurerm_resources.aml.resources[*].tags.budget_end_date, 0), "NA")
  should_test_budget = local.is_test_stage_boolean && var.test_budget
  budget_start_date = local.budget_start_date_tag != "NA" ? local.budget_start_date_tag : (local.should_test_budget ? "START DATE FAIL!" : formatdate("YYYY-MM-01", timestamp()))
  budget_end_date = local.budget_end_date_tag != "NA" ? local.budget_end_date_tag : (local.should_test_budget ? "END DATE FAIL!" : formatdate("YYYY-MM-01", timeadd(timestamp(), "17568h")))
  budget_date_tags = {
     "budget_start_date" : local.budget_start_date,
     "budget_end_date" : local.budget_end_date
  }
}

#--------------------------------------------------------------------------------------------------------------------
# DSW: Resource Group 
# --------------------------------------------------------------------------------------------------------------------
resource "azurerm_resource_group" "rg" {
  # A subscription cannot have more than 980 resource groups:
  # https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits
  count = local.no_addresses_available_boolean ? 0 : 1
  name = "test-rg"
  location = var.location
  tags = local.budget_date_tags
}

resource "azurerm_machine_learning_workspace" "aml_workspace" {
  name = local.aml_ws_name
  resource_group_name = azurerm_resource_group.rg[0].name
  location = azurerm_resource_group.rg[0].location
  application_insights_id = azurerm_application_insights.aml_insights.id
  key_vault_id = azurerm_key_vault.aml_kv.id
  storage_account_id = azurerm_storage_account.aml_st.id
  container_registry_id = azurerm_container_registry.aml_acr.id
  sku_name = "Basic"
  tags = merge(var.azure_tags, local.budget_date_tags)
  identity {
    type = "SystemAssigned"
  }
}

@Charles Xu Я еще не совсем проверил это, и я также не уверен, что это лучшее решение?

Обновлено: Теперь я фактически сталкиваюсь с циклической зависимостью, потому что источник данных явно не существует до создания группы ресурсов: https://github.com/hashicorp/terraform/issues/16380.

@Charles Xu Это решение работает сейчас. Я понял, что не могу использовать ни теги бюджета, ни теги группы ресурсов. Поэтому я также открыл: github.com/terraform-providers/terraform-provider-azurerm/…. Поэтому мне пришлось выбрать другой ресурс, то есть рабочую область машинного обучения Azure. Использование тегов бюджета позволяет мне зафиксировать дату начала и окончания бюджета, как только они будут установлены.

mgross 24.12.2020 15:14

Другие вопросы по теме