【问题标题】:Terraform import: invalid indexTerraform 导入:无效索引
【发布时间】:2021-10-25 19:49:08
【问题描述】:

我正在尝试将已弃用的资源 'azurerm_sql_server' 替换为 'azurerm_mssql_server' 并在这种情况下出现“无效索引”错误。

情况的简化演示(使用 Terraform v0.14.5 和 v1.0.5):

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=2.49.0"
    }
  }
}

provider "azurerm" {
  features {}
}

locals {
  prefix = toset(["primary", "secondary"])
}

resource "azurerm_resource_group" "rg" {
  name     = "rgtest"
  location = "Canada Central"
}

resource "random_password" "sql_admin_password" {
  length      = 16
  special     = true
  number      = true
  upper       = true
  lower       = true
  min_special = 2
  min_numeric = 2
  min_upper   = 2
  min_lower   = 2
}

resource "azurerm_sql_server" "instance" {
  for_each = local.prefix

  name                = "${each.value}-sqlsvr"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  version                      = "12.0"
  administrator_login          = "ssadmin"
  administrator_login_password = random_password.sql_admin_password.result
}

locals {
  primary_sql_srv   = azurerm_sql_server.instance["primary"].name
  secondary_sql_srv = azurerm_sql_server.instance["secondary"].name
}

# other TF resources using local.primary_sql_srv and local.secondary_sql_srv

基础架构已部署完毕,无意重新创建数据库服务器,因此我们需要更改资源并导入现有服务器。根据Terraform document,这可以通过“terraform state rm”和“terraform import”命令来完成。

所以,

  1. 更改配置脚本
...

resource "azurerm_mssql_server" "instance" {
...
locals {
  primary_sql_srv   = azurerm_mssql_server.instance["primary"].name
  secondary_sql_srv = azurerm_mssql_server.instance["secondary"].name
}
# other TF resources using local.primary_sql_srv and local.secondary_sql_srv
  1. 从状态文件中移除 azurerm_sql_server 资源,均成功
terraform.exe state rm azurerm_sql_server.instance[`\`"primary`\`"]
terraform.exe state rm azurerm_sql_server.instance[`\`"secondary`\`"]
  1. 导入主数据库服务器
> terraform.exe import azurerm_mssql_server.instance[`\`"primary`\`"] "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/primary-sqlsvr"

azurerm_mssql_server.instance["primary"]: Importing from ID "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/primary-sqlsvr"...
azurerm_mssql_server.instance["primary"]: Import prepared!
  Prepared azurerm_mssql_server for import
azurerm_mssql_server.instance["primary"]: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/primary-sqlsvr]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

当前状态列表

❯ terraform.exe state list

azurerm_mssql_server.instance["primary"]
azurerm_resource_group.rg
random_password.sql_admin_password
  1. 导入辅助数据库服务器
> terraform.exe import azurerm_mssql_server.instance[`\`"secondary`\`"] "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/secondary-sqlsvr"

azurerm_mssql_server.instance["secondary"]: Importing from ID "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/secondary-sqlsvr"...
azurerm_mssql_server.instance["secondary"]: Import prepared!
  Prepared azurerm_mssql_server for import
azurerm_mssql_server.instance["secondary"]: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgtest/providers/Microsoft.Sql/servers/secondary-sqlsvr]

Error: Invalid index

  on C:\Work\Projects\2021\20210812RenameResource\t1env\main.tf line 49, in locals:
  49:   secondary_sql_srv = azurerm_mssql_server.instance["secondary"].name
    |----------------
    | azurerm_mssql_server.instance is object with 1 attribute "primary"

The given key does not identify an element in this collection value.

第二次导入的状态刷新命中了本地块并且由于没有“辅助”服务器资源而失败。

所以对我来说,这是一个死锁,由于刷新错误,我无法导入“辅助”服务器资源,而刷新错误是由于缺少“辅助”服务器资源引起的。

我能想到的两种方法:

  1. 手动将“辅助”服务器资源添加到状态文件中,这绝对不合适
  2. 删除 'locals' 块,这在演示中是可以的,但对依赖项的实际代码进行了很多更改。

请问有什么想法吗?谢谢。

【问题讨论】:

  • 这是terraform import 中的一个错误,它是在 0.13 版中引入的,我希望现在可以修复。它错误地尝试在配置中验证localsimport 期间不存在状态,而不是忽略它是不可能的。这是什么版本的 Terraform?
  • 嗨,马特,谢谢。我刚刚将版本添加到问题中,v0.14.5。我会在演示中试用最新版本。
  • 如果最新版本还没有修复,那么我可以讨论解决方法。
  • 嗨,马特,刚刚用 v1.0.5 测试过,同样的错误。有哪些解决方法?谢谢。

标签: terraform


【解决方案1】:

这是terraform import 0.13 版中引入的一个错误。在terraform import 执行期间,它将尝试验证包含资源命名空间的配置中的local 变量是否存在不存在状态。基本上有三种解决方法:

  1. 暂时降级到不存在此错误的 Terraform 0.12。

这确实不是一个好选择,因为版​​本存储在状态中,并且您可能无法针对与更高版本同步的状态执行 terraform CLI 命令。

  1. 手动修改状态以包含资源。

这也不是一个很好的选择,因为这可能会破坏状态和/或导致其他明显的畸形问题。

  1. 暂时注释掉相关的locals 和任何引用local 变量值的代码。

这是我最后一直使用的。您可以在引用导入资源的导出资源属性的相关locals 周围以/* ... */ 样式进行多行注释,并且您还需要在配置的任何其他引用local 的区域中这样做变量。导入完成后,您可以取消注释代码。

【讨论】:

  • 如果有 GH 上的错误问题,您是否有链接?
  • @Marcin 我从来没有为此申请过,也没有检查过。我相信我最近刚刚完成了另外两个文件的提交,当时对它们感到厌烦。
  • 感谢您告诉我。是的,制作 GH 问题有时是全职工作:-)
  • @MattSchuchard 感谢您的解决方法,我会尝试第三个。棘手的是这些代码位于一个共享模块中,被 100 多个应用环境使用,情况如此复杂。
  • @JWU 我应该提一下,您链接到的文档建议使用state rm 后跟import,只有在 API 资源 ID 格式也发生更改时才准确。如果这不是真的并且只有提供者资源名称发生了变化,那么您实际上可以改为使用state mv,这样可以避免所有这些混乱。也许可以快速尝试一下,看看效果如何。
猜你喜欢
  • 1970-01-01
  • 2019-02-13
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-16
  • 2021-10-01
相关资源
最近更新 更多