Terraform: ingress_with_source_security_group_id vs. computed_ingress_with_source_security_group_id

Viewed 370

Terraform module terraform-aws-modules/security-group/aws supports two input variables.

1. ingress_with_source_security_group_id

description: List of ingress rules to create where 'source_security_group_id' is used

example: (source code)

  ingress_with_source_security_group_id = [
    {
      rule                     = "mysql-tcp"
      source_security_group_id = data.aws_security_group.default.id
    },
    {
      from_port                = 10
      to_port                  = 10
      protocol                 = 6
      description              = "Service name"
      source_security_group_id = data.aws_security_group.default.id
    },
  ]


2. computed_ingress_with_source_security_group_id

description: List of computed ingress rules to create where 'source_security_group_id' is used

Example (source code)

  computed_ingress_with_source_security_group_id = [
    {
      rule                     = "postgresql-tcp"
      source_security_group_id = module.main_sg.security_group_id
    },
    {
      from_port                = 23
      to_port                  = 23
      protocol                 = 6
      description              = "Service name"
      source_security_group_id = module.main_sg.security_group_id
    },
  ]

Questions

What's the difference between them?

What are computed ingress rules?

2 Answers

This is explained in Note about "value of 'count' cannot be computed" and is related to limitations of TF 0.11. From the link:

Computed values are values provided as outputs from module. Non-computed values are all others - static values, values referenced as variable and from data-sources.

When you need to specify computed value inside security group rule argument you need to specify it using an argument which starts with computed_ and provide a number of elements in the argument which starts with number_of_computed_

I get it.
@ryan, im sure you know this by now, but for me i was confused also. So hopefully this helps others.

Computed, seems to mean "im going to need to use output data in my group, and wont have all the data available at the time of writing the code". Essentially, it means your going to reference module outputs for values. Module outputs arent available until after they are ran.

So in this example, notice module.main_sg.security_group_id. This is the part that needs computing, because its coming from another module output. E.g. it wont have that value until terraform runs, where it can then grab the output from that module.

  computed_ingress_with_source_security_group_id = [
    {
      rule                     = "postgresql-tcp"
      source_security_group_id = module.main_sg.security_group_id
    },
    {
      from_port                = 23
      to_port                  = 23
      protocol                 = 6
      description              = "Service name"
      source_security_group_id = module.main_sg.security_group_id
    },
  ]

So, if you dont use computed_ here, the code breaks, beacuse it cant get the value of module.main_sg.security_group_id.

When you have all the values available before the code runs, as in your first example, e.g.source_security_group_id = data.aws_security_group.default.id then you dont need to use computed_. This means it wont have to pass through extra functionality to resolve the values, because they are already statically specified somewhere. In this case its statically specified in a data resource, etc..

So computed means, when terraform runs this code, it will need to wait until it gets the output data, before calculating what this security groups values will actually be, because those values are dynamic, and rely on the terraform code to run before it can see them, hence it will need to "compute" them when it runs.

I have another example.

Here this code needs a value from another module, you cant tell that, because its grabbing that in the main.tf.

    computed_ingress_with_cidr_blocks = [{
      from_port   = 53
      to_port     = 53
      protocol    = "udp"
      description = "Domain Name System (DNS) access"
      cidr_blocks = var.priv_cidr_block
    },{ 
    ...

The cidr block is taken from the vpc module.

Then the egress rule is as follows

  egress_with_cidr_blocks = [{
      from_port   = 9389
      to_port     = 9389
      protocol    = "tcp"
      description = "OPEN egress, all ports, all protocols"
      cidr_blocks = "0.0.0.0/0"
  }]```

Notice, theres only static values in there, so no need to "compute" any values, it already is, what it is...   

HTH. 
Related