terraform:基于关键字的地图筛选列表

terraform:基于关键字的地图筛选列表,terraform,terraform-provider-aws,terraform0.12+,hcl,Terraform,Terraform Provider Aws,Terraform0.12+,Hcl,我正在实现一个安全组模块,这样它将通过获取并过滤cidr和source_security_group_id来创建安全组规则 当前模块配置 安全组模块.tf main.tf 因此,这里的问题是,当我使用上面的映射列表调用模块中的安全组规则时,它应该检查它是source_sg_id还是cidr 然后过滤这些映射并将其传递给模块中的相应资源 例: 应查找这些规则,并将第一个规则传递给CIDR规则,第二个规则传递给源\安全\组\ id规则 我正在考虑制作如下 locals { sid_rules

我正在实现一个安全组模块,这样它将通过获取并过滤cidr和source_security_group_id来创建安全组规则

当前模块配置

安全组模块.tf main.tf 因此,这里的问题是,当我使用上面的映射列表调用模块中的安全组规则时,它应该检查它是source_sg_id还是cidr

然后过滤这些映射并将其传递给模块中的相应资源

例:

应查找这些规则,并将第一个规则传递给CIDR规则,第二个规则传递给源\安全\组\ id规则

我正在考虑制作如下

locals {

  sid_rules = some_function{var.security_group_rules, "source_security_group_id"}
  cidr_rules = some_function{var.security_group_rules, "cidr"}
}


resource "aws_security_group_rule" "cidr_rule" {
  count = count(local.cidr_rules)

  ....
  cidr_blocks       = local.cidr_rules[count.index].cidr_block
  ....
}


resource "aws_security_group_rule" "sid_rule" {
  count = count(local.sid_rules)

  ....
  source_security_group_id  = local.sid_rules[count.index].source_sg_id
  ....
}
因此,我正在寻找一种基于键从列表中筛选地图的方法


我尝试过查找,但对于字符串列表没有帮助。

考虑创建另一个模块来处理规则,并在该模块内设置安全组资源

module "security_groups" {
  count             = length(var.security_group_rules)
  source_sg_id_rule = var.security_group_rules[count.index].source_sg_id_rule
}
然后,在新模块中,使用count语句作为测试来创建可选项:

resource "aws_security_group_rule" "source_sg_id_rule" {
    count = length(var.source_sg_id_rule) == 0 ? 0 : 1

    type              = var.type
    from_port         = var.from_port
    to_port           = var.to_port
    protocol          = var.protocol
    source_security_group_id = var.source_security_group_id
    description       = var.description
    security_group_id = var.security_group_id
}

这将创建一个由一个或零个项目组成的数组,并删除任何零个项目的列表。

感谢@dan monego的回复

我用单模块itslef把它分类了

下面是模块文件

aws_sg_模块.tf 使用下面的模块块调用它

安全组.tf
我想出了一个聪明的办法

假设我正在尝试从宠物列表中只筛选猫
kind=“cat”

variable "pets" {
  type = list(object({
    name = string
    kind = string
  }))
  default = [
    {
      name = "Fido"
      kind = "dog"
    },
    {
      name = "Max"
      kind = "dog"
    },
    {
      name = "Milo"
      kind = "cat"
    },
    {
      name = "Simba"
      kind = "cat"
    }
  ]
}
  • 首先使用索引
    tostring(i)
    作为键,将宠物列表转换为宠物地图。 这将在步骤3中用于查找筛选的宠物
  • 接下来创建一个分别与条件匹配的键的过滤列表
    pet.kind==“cat”
    通过在
    pets\u地图中的键上循环,并设置与地图不匹配的相应键
    空字符串。然后压缩列表,从列表中删除空字符串
  • 在过滤过的钥匙上循环
    cats\u钥匙
    ,并从
    pets\u地图
    中查找相应的宠物。现在你 拥有猫宠物的筛选列表
    kind=“cat”
  • 您现在可以使用
    local.cats
    访问猫,这将为您提供以下地图

    {
      name = "Milo"
      kind = "cat"
    },
    {
      name = "Simba"
      kind = "cat"
    }
    
    下面是完整的示例

    variable "pets" {
      type = list(object({
        name = string
        kind = string
      }))
      default = [
        {
          name = "Fido"
          kind = "dog"
        },
        {
          name = "Max"
          kind = "dog"
        },
        {
          name = "Milo"
          kind = "cat"
        },
        {
          name = "Simba"
          kind = "cat"
        }
      ]
    }
    
    locals {
      pets_map = { for i, pet in var.pets : tostring(i) => pet }
      cats_keys = compact([for i, pet in local.pets_map : pet.kind == "cat" ? i : ""])
      cats     = [for key in local.cats_keys : lookup(local.pets_map, key)]
    }
    
    
    # Security group
    ##########################
    
    resource "aws_security_group" "this" {
      name                   = var.name
      description            = var.description
      vpc_id                 = var.vpc_id
      revoke_rules_on_delete = var.revoke_rules_on_delete
    
      tags = merge(
        {
          "Name" = format("%s", var.name)
        },
        local.default_tags,
        var.additional_tags
      )
    }
    
    resource "aws_security_group_rule" "cidr" {
      count = var.create ? length(var.cidr_sg_rules) : 0
    
      type              = var.cidr_sg_rules[count.index].type
      from_port         = var.cidr_sg_rules[count.index].from
      to_port           = var.cidr_sg_rules[count.index].to
      protocol          = var.cidr_sg_rules[count.index].protocol
      cidr_blocks       = var.cidr_sg_rules[count.index].cidr
      description       = var.cidr_sg_rules[count.index].description
      security_group_id = local.this_sg_id
    }
    
    resource "aws_security_group_rule" "source_sg" {
      count = var.create ? length(var.source_sg_rules) : 0
    
      type                     = var.source_sg_rules[count.index].type
      from_port                = var.source_sg_rules[count.index].from
      to_port                  = var.source_sg_rules[count.index].to
      protocol                 = var.source_sg_rules[count.index].protocol
      source_security_group_id = var.source_sg_rules[count.index].source_sg_id
      description              = var.source_sg_rules[count.index].description
      security_group_id        = local.this_sg_id
    }
    resource "aws_security_group_rule" "self" {
      count = var.create ? length(var.self_sg_rules) : 0
    
      self              = true
      type              = var.source_sg_rules[count.index].type
      from_port         = var.source_sg_rules[count.index].from
      to_port           = var.source_sg_rules[count.index].to
      protocol          = var.source_sg_rules[count.index].protocol
      description       = var.source_sg_rules[count.index].description
      security_group_id = local.this_sg_id
    }
    
    module "stack_sg" {
      source            = "./modules/aws_security_group"
      name                = "stack-sg"
    
      vpc_id = module.network.vpc_id
    
      cidr_sg_rules = [
        { type = "ingress", from = 80, to = 80, protocol = "tcp",  cidr = [module.network.vpc_cidr], description = "http" },
        { type = "egress", from = 0, to = 65535, protocol = "-1",  cidr = ["0.0.0.0/0"], description = "allow all " }
      ]
    
      source_sg_rules = [
        { type = "ingress", from = 0, to = 65535, protocol = "tcp", source_sg_id = module.alb_sg.sg_id, description = "alb" }
      ]
    }
    
    variable "pets" {
      type = list(object({
        name = string
        kind = string
      }))
      default = [
        {
          name = "Fido"
          kind = "dog"
        },
        {
          name = "Max"
          kind = "dog"
        },
        {
          name = "Milo"
          kind = "cat"
        },
        {
          name = "Simba"
          kind = "cat"
        }
      ]
    }
    
    locals {
      pets_map = { for i, pet in var.pets : tostring(i) => pet }
    }
    
    locals {
      cats_keys = compact([for i, pet in local.pets_map : pet.kind == "cat" ? i : ""])
    }
    
    locals {
      cats     = [for key in local.cats_keys : lookup(local.pets_map, key)]
    }
    
    {
      name = "Milo"
      kind = "cat"
    },
    {
      name = "Simba"
      kind = "cat"
    }
    
    variable "pets" {
      type = list(object({
        name = string
        kind = string
      }))
      default = [
        {
          name = "Fido"
          kind = "dog"
        },
        {
          name = "Max"
          kind = "dog"
        },
        {
          name = "Milo"
          kind = "cat"
        },
        {
          name = "Simba"
          kind = "cat"
        }
      ]
    }
    
    locals {
      pets_map = { for i, pet in var.pets : tostring(i) => pet }
      cats_keys = compact([for i, pet in local.pets_map : pet.kind == "cat" ? i : ""])
      cats     = [for key in local.cats_keys : lookup(local.pets_map, key)]
    }