【问题标题】:How to check, if Terraform will create resource如何检查 Terraform 是否会创建资源
【发布时间】:2021-10-30 21:31:54
【问题描述】:

我在我的工作流程中使用 Terraform + AWS Lambda,并且我想在每个计划或应用操作期间使用我现有实例的 ARN 调用一些 lambda。我使用这种结构:

locals {
   ...
   centralized_nodes = {...}
   tags_map = {...}

   backup_map = {        
   for node in keys(local.centralized_nodes):
   node => aws_instance.centralized_node[node].arn
   if can(local.tags_map[node]["backup"]) && !(can(aws_instance.centralized_node[node].root_block_device.0.tags["backup"]))
   }
   ...
}
resource "aws_instance" "centralized_node" {
    ...
    for_each                 = local.centralized_nodes
    ...
}
data "aws_lambda_invocation" "lambda_backup" {
  for_each = local.backup_map  
  function_name = "lambdafunc"
  input = jsonencode({          
        "resources"            = [each.value]         
    })
}

在我尝试将节点描述对象添加到 centralized_nodes 映射并创建新实例之前,它运行良好。当我添加这个时,terraform 在规划过程中向我显示错误:

Error: Invalid for_each argument
│ 
│   on resources.tf line 223, in data "aws_lambda_invocation" "lambda_backup":
│  223:   for_each = local.backup_map  
│     ├────────────────
│     │ local.backup_map will be known only after apply
│ 
│ The "for_each" 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 for_each depends on.

现在我正在寻找 terraform 检查资源是否存在或将被创建。我尝试向地图生成器添加参数以排除未创建的实例(在我的工作流程中可以),如下所示:

if can(local.tags_map[node]["backup"]) && !(can(aws_instance.centralized_node[node].root_block_device.0.tags["backup"])) && can(aws_instance.centralized_node[node].arn)

但它不起作用,terraform认为它可以达到未创建实例的ARN值,但稍后。

请帮我找到避免此类错误的方法。

【问题讨论】:

  • 你想达到什么目的?看起来您正在尝试将 Terraform 用于它不打算用于的东西。为什么不在您的脚本中使用 AWS CLI 在运行 Terraform 之前调用 Lambda。保持简单。
  • 我使用基于 ebs 卷标签的 AWS 快照备份功能。如果备份卷标签被破坏,这部分代码应该自动修复它们。此外,我无法使用 terraform 附加这些标签,因为它们包含实例和卷 ID,这就是我使用 Lambda 进行标签管理的原因。

标签: amazon-web-services aws-lambda terraform hcl


【解决方案1】:

似乎您的local.centralized_nodes 不是由而是自动生成的。如果是这样,你 can't use itfor_each

map的keys(或者一组字符串情况下的所有值)必须是已知值,否则你会得到for_each有之前无法确定的依赖的错误信息应用,并且可能需要一个 -target。

您可以尝试将您的代码转换为使用count,因为count 没有这样的限制。但是,count 有其自身的问题,可能会阻止您实现目标。

【讨论】:

    【解决方案2】:

    我找到了检查实例和卷等资源是否已经存在的唯一方法。它使用 aws_instance 和 aws_instances 数据源。 这是我的解决方案:

    locals {
       ...
       centralized_nodes = {...}
       tags_map = {...}
       instance_name_root_volume_tags_map = {
            for name, value in {for id, value in data.aws_instance.instance_id_arn_map : value.tags["Name"] => value}:
            name => data.aws_ebs_volume.volume_instance_id_map[value.id].tags
       } 
       backup_map = {        
       for name, value in {for id, value in data.aws_instance.instance_id_arn_map : value.tags["Name"] => value}:
            name => value.arn
            if !can(local.instance_name_root_volume_tags_map[name]["backup"]) && can({for node, value in local.tags_map: value["Name"] => value}[name]["backup"]) )
       }
       ...
    }
    resource "aws_instance" "centralized_node" {
        ...
        for_each                 = local.centralized_nodes
        ...
    }
    data "aws_lambda_invocation" "lambda_backup" {
      for_each = local.backup_map  
      function_name = "lambdafunc"
      input = jsonencode({          
            "resources"            = [each.value]         
        })
    }
    data "aws_instances" "existant_instances_array" {
      filter {
        name   = "tag:Name"
        values =  [for tagmap in local.hiera_tags_map : tagmap["Name"]] 
      }
    }
    data "aws_instance" "instance_id_arn_map" {
      for_each  = toset(data.aws_instances.existant_instances_array.ids)
      instance_id = each.value
    }
    data "aws_ebs_volume" "volume_instance_id_map" {
      for_each  = data.aws_instance.instance_id_arn_map
      filter {
          name = "attachment.instance-id"
          values = [each.value.id]
      }
      filter {
          name = "attachment.device"
          values = ["/dev/sda1"]
      }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 2023-01-23
      • 2020-11-07
      • 2022-12-29
      • 2019-03-12
      • 2019-09-13
      相关资源
      最近更新 更多