Terraform: Do all the optional arguments have a default value to represent it enable or not

Created on 9 Sep 2016  ยท  6Comments  ยท  Source: hashicorp/terraform

Here is my scenario, I use module a lot, and need to set the default value for some optional arguments, but sometimes, when to handle two conflict optional arguments, add or not to add the optional argument will cause to be a total different resource, so I need to create two modules with and without this optional argument.

Example

when to create a module for AWS_SECURITY_GROUP_RULE

  cidr_blocks - (Optional) List of CIDR blocks. Cannot be specified with source_security_group_id.
  source_security_group_id - (Optional) The security group id to allow access to/from, depending on the type. Cannot be specified with cidr_blocks.

Expect

module "aws_security_group_rule" "allow_all" {
    type = "ingress"
    from_port = 0
    to_port = 65535
    protocol = "tcp"
    cidr_blocks = ["${var.cider_blocks}"]
    source_security_group_id = "${var.source_sg_id}"

    security_group_id = "sg-123456"
}

variable "cider_blocks" {
  type = "list"
  default = []
}

variable "source_sg_id" {
  type = "string"
  default = ""
}

Actual

These two optional arguments is conflict, so I need to create two modules like:

module "aws_security_group_rule" "allow_all" {
    type = "ingress"
    from_port = 0
    to_port = 65535
    protocol = "tcp"
    cidr_blocks = ["${var.cider_blocks}"]

    security_group_id = "sg-123456"
}

and

module "aws_security_group_rule" "allow_all" {
    type = "ingress"
    from_port = 0
    to_port = 65535
    protocol = "tcp"
    source_security_group_id = "${var.soure_sg_id}"

    security_group_id = "sg-123456"
}

Is there anyway to solve issue like this? Maybe all the optional arguments should have a default value to identify it enabled or not and add them to the document will be better.

Thank you for your time.

provider-sdk question

Most helpful comment

I have a similar problem:

in the module for our aws_ecs_task_definition we have the optional task_role_arn, but not all services have a task role and I can't find a solution to set the default value to omitted or None.

resource "aws_ecs_task_definition" "task_definition" {
  depends_on            = [
    "data.template_file.task_definition_template"
  ]
  family                = "${var.service_name}-${var.environment}"
  container_definitions = "${data.template_file.task_definition_template.rendered}"
  task_role_arn         = "${aws_iam_role.ecs_task_role.arn}"

  lifecycle {
    create_before_destroy = true
  }
}

All 6 comments

Hi @spotlight-dev! One question I have here - is this an example or actual code you are trying to use? You generally do a lot better by composing modules of related application functionality, not as units of reusability.

@jen20 I am the guy spotlight-dev :) Thank you for your reply.

It is the actual code I used in the project, and I almost create module for every aws resource, and then reuse it in the actual resource definition. So I thought the optional parameter should have a default value to behave like a feature switch.

It is the wrong way to use module? And I also referred to https://github.com/hashicorp/best-practices/tree/master/terraform, use the similar directory layout. Anything suggestion about the best practice.

composing modules of related application functionality, not as units of reusability

Is there an alternative suggestion about how to do the latter? My use case is that I'm working on reusable Jenkins deployment code, to be leveraged by different teams in my (large) organization. There are Terraform modules that I instruct users to include, though the specific needs of each deployment might be different. For example: whether their Jenkins instance(s) need an AWS IAM Instance Profile or not. The "make variables for everything a user may want to configure" approach would (I think) require what @hanks describes.

My other thought about how to accomplish this was to instruct users to use Terraform overrides, but it wasn't clear to me if it's possible to have a resource outside of a module corresponding to a resource within a module. In other words, I would be looking to do something like

# override.tf
resource "aws_instance" "module.aws_instance.jenkins" {
  iam_instance_profile = "foo"
}

This would give a lot more flexibility, as not all of the arguments would need to be exposed as variables. Thoughts?

I have a similar problem:

in the module for our aws_ecs_task_definition we have the optional task_role_arn, but not all services have a task role and I can't find a solution to set the default value to omitted or None.

resource "aws_ecs_task_definition" "task_definition" {
  depends_on            = [
    "data.template_file.task_definition_template"
  ]
  family                = "${var.service_name}-${var.environment}"
  container_definitions = "${data.template_file.task_definition_template.rendered}"
  task_role_arn         = "${aws_iam_role.ecs_task_role.arn}"

  lifecycle {
    create_before_destroy = true
  }
}

Hi all! Sorry for the long silence here.

Terraform 0.12 introduced a mechanism to conditionally omit an argument:

  task_role_arn = length(aws_iam_role.ecs_task_role) > 0 ? aws_iam_role.ecs_task_role.arn[0] : null

The general pattern here is to use the conditional operator ? : with one of the result expressions set to null. When used as a resource argument, null is equivalent to omitting the argument altogether. Internally, providers can't even tell the difference between a null value and omitting the argument altogether.

For more complex situations this can still require some creative interface design for your module variables, but the mechanism for conditionally omitting arguments is now present, so we're going to close this out. Thanks for sharing these use-cases!

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings