cloudposse / terraform-aws-security-group

Terraform module to provision an AWS Security Group
https://cloudposse.com/accelerate
Apache License 2.0
36 stars 35 forks source link

"element types must all match for conversion to list" error when using nat_gateway_public_ips output from cloudposse/dynamic-subnets/aws module #39

Closed karaluh closed 2 years ago

karaluh commented 2 years ago

Found a bug? Maybe our Slack Community can help.

Slack Community

Describe the Bug

DISCLAIMER: I know the NAT-GW IP from dynamic subnets module lacks CIDR, I left it as it is to not complicate the example because the lack of CIDR doesn't cause the issue I'm reporting here.

Executing terraform apply from the code below ends with an error:

╷
│ Error: Invalid value for input variable
│
│   on main.tf line 51, in module "sg":
│   51:   rules = [
│   52:     {
│   53:       type        = "ingress"
│   54:       from_port   = 0
│   55:       to_port     = 2222
│   56:       protocol    = "tcp"
│   57:       cidr_blocks = module.subnets.nat_gateway_public_ips
│   58:       self        = null
│   59:       description = "2222"
│   60:     },
│   61:     {
│   62:       type        = "egress"
│   63:       from_port   = 0
│   64:       to_port     = 0
│   65:       protocol    = "-1"
│   66:       cidr_blocks = ["0.0.0.0/0"]
│   67:       self        = null
│   68:       description = "All output traffic"
│   69:     }
│   70:   ]
│
│ The given value is not suitable for module.sg.var.rules declared at .terraform\modules\sg\variables.tf:76,1-17: element types must all match for conversion to list.
╵

Environment (please complete the following information):

Terraform v1.2.9 on windows_amd64

Additional Context

module "vpc" {
  source = "cloudposse/vpc/aws"

  ipv4_primary_cidr_block = "10.0.0.0/16"
  assign_generated_ipv6_cidr_block = false
}

module "subnets" {
  source = "cloudposse/dynamic-subnets/aws"
  vpc_id              = module.vpc.vpc_id
  ipv4_cidr_block     = ["10.0.0.0/16"]
  availability_zones  = ["eu-west-1a"]
}

module "sg" {
  source  = "git::https://github.com/cloudposse/terraform-aws-security-group?ref=2.0.0-rc1"
  vpc_id      = module.vpc.vpc_id

  rules = [
    {
      type        = "ingress"
      from_port   = 0
      to_port     = 2222
      protocol    = "tcp"
      cidr_blocks = module.subnets.nat_gateway_public_ips
      self        = null
      description = "2222"
    },
    {
      type        = "egress"
      from_port   = 0
      to_port     = 0
      protocol    = "-1"
      cidr_blocks = ["0.0.0.0/0"]
      self        = null
      description = "All output traffic"
    }
  ]
}
Nuru commented 2 years ago

This is not a bug in this module, this is a consequence of how the Terraform type system works. Please see "Why the input is so complex" in https://github.com/cloudposse/terraform-aws-security-group#rules-and-rules_map-inputs and also https://github.com/hashicorp/terraform/issues/31102

Probably the easiest thing to do is simply wrap the cidr_blocks inputs with tolist(). Alternately, this module provides a rules_map input to avoid exactly this problem. (BTW, the nat_gateway_public_ips output is deprecated, so use nat_ips instead.)

module "sg" {
  source  = "git::https://github.com/cloudposse/terraform-aws-security-group?ref=2.0.0-rc1"
  vpc_id      = module.vpc.vpc_id

  rules_map = {
    ingress = [{
      key         = "ingress"
      type        = "ingress"
      from_port   = 0
      to_port     = 2222
      protocol    = "tcp"
      cidr_blocks = module.subnets.nat_gateway_public_ips
      self        = null
      description = "2222"
    }],
    egress = [{
      key         = "egress"
      type        = "egress"
      from_port   = 0
      to_port     = 0
      protocol    = "-1"
      cidr_blocks = ["0.0.0.0/0"]
      self        = null
      description = "All output traffic"
    }]
  }
}