Variable question

Here is what I am trying to do - and I know it cannot be done with TF but hoping there is something I can do with terragrunt

here is the module code:

resource “aws_security_group” “access_me” {
lifecycle {
create_before_destroy = true
}

name = “sg_{lower(var.name)}_access" description = "{title(var.name)} Security Group”
vpc_id = “vpc-111111”

ingress = ["${var.ingress}"]

egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}

tags {
Name = “sg_${lower(var.name)}_access”
}
}

Here is the wrapper code:

ingress = [
{
from_port = 22
to_port = 22
protocol = “tcp”
self = true
description = “Ingress”
},
{
from_port = 22
to_port = 22
protocol = “tcp”
description = “Ingress”
security_groups = ["${data.terraform_remote_state.another_tf.access_granted}"]
},
]
}

Error:

Error: module.this_tf.aws_security_group.access_me: “ingress.0.from_port”: required field is not set

Error: module.this_tf.aws_security_group.access_me: “ingress.0.protocol”: required field is not set

Error: module.this_tf.aws_security_group.access_me: “ingress.0.to_port”: required field is not set

Is there anyway around this? I am trying to avoid using rules (requirement for end user)

thanks!
J

Hi J,

I think what you are trying to do is possible with terraform. I am guessing the problem may be arising from how you defined the inputs for the module. For reference, I was able to make this scenario work with the following setup:

Module (./secgroup/main.tf)

provider "aws" {
  region = "us-west-2"
}

resource "aws_security_group" "access_me" {
  lifecycle {
    create_before_destroy = true
  }

  name        = "sg_${lower(var.name)}_access"
  description = "${title(var.name)} Security Group"
  vpc_id      = "vpc-id"

  ingress = ["${var.ingress}"]

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags {
    Name = "sg_${lower(var.name)}_access"
  }
}

variable "name" {}

variable "ingress" {
  type = "list"
}

Consumer code (./main.tf)

module "secgroup" {
  source = "./secgroup"
  name   = "test"

  ingress = [
    {
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      self        = true
      description = "Ingress"
    },
    {
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      description = "Ingress"
      cidr_blocks = ["0.0.0.0/0"]
    },
  ]
}

Note how I labeled the ingress variable as a list, so that terraform will pass it in as a list object. Otherwise, it will be interpolated into a string.

Hope this helps!

Yori

Yes it is possible to do it that way. But, I would like to add a security group that is computed:

security_groups = ["${data.terraform_remote_state.another_tf.access_granted}"]

Hi J,

Ah I see what you mean now and I have verified the issue. Apologies for misunderstanding your original question!

After looking into this, this is most likely a bug in terraform and I would recommend filing an issue on https://github.com/hashicorp/terraform/. Unfortunately, this particular feature isn’t something that terragrunt handles specifically, so if it doesn’t work with terraform, then it will not work with terragrunt.

Sorry that I couldn’t be of much help here.

Yori

Thanks! I was hoping that terragrunt could work out some mojo to overcome this bug :smiley: