3
votes

I have an ecs_cluster module which defines an ECS cluster. I want the module to be re-usable so I can create various clusters with different configurations. Hence I want to be able to optionally specify whether to create and attach an EBS volume in the launch configuration of the ECS hosts.

I initially tried using count in the ebs_block_device inside the launch configuration e.g.

variable "ebs_volume_device_name" { type = "string", default = "" }
variable "ebs_volume_type" { type = "string", default = "" }
variable "ebs_volume_size" { type = "string", default = "" }

resource "aws_launch_configuration" "launch_configuration" {
  name_prefix = "foo"
  image_id = "bar"
  # Irrelevant stuff removed for brevity...

  ebs_block_device {
    count = "${length(var.ebs_volume_device_name) > 0 ? 1 : 0}"
    device_name = "${var.ebs_volume_device_name }"
    volume_type = "${var.ebs_volume_type}"
    volume_size = "${var.ebs_volume_size}"
  }
} 

However this results in the following error:

module.ecs_cluster.aws_launch_configuration.launch_configuration: ebs_block_device.0: invalid or unknown key: count

I then tried specifying the launch_configuration resource twice, once with and once without the ebs block device e.g.

variable "ebs_volume_device_name" { type = "string", default = "" }
variable "ebs_volume_type" { type = "string", default = "" }
variable "ebs_volume_size" { type = "string", default = "" }

resource "aws_launch_configuration" "launch_configuration" {
  count = "${length(var.ebs_volume_device_name) == 0 ? 1 : 0}"
  name_prefix = "foo"
  image_id = "bar"
  # Irrelevant stuff removed for brevity...

  # No specification of ebs_block_device
}

resource "aws_launch_configuration" "launch_configuration" {
  count = "${length(var.ebs_volume_device_name) > 0 ? 1 : 0}"
  name_prefix = "foo"
  image_id = "bar"
  # Irrelevant stuff removed for brevity...

  ebs_block_device {

    device_name = "${var.ebs_volume_device_name }"
    volume_type = "${var.ebs_volume_type}"
    volume_size = "${var.ebs_volume_size}"
  }
}

However Terraform then complains because the resource is defined twice.

I can't change the id of either of the resources as I have an auto scaling group which depends upon the name of the launch configuration e.g.

resource "aws_autoscaling_group" "autoscaling_group" {
  name = "foo"
  launch_configuration = "${aws_launch_configuration.launch_configuration.name}"
}

I guess I could conditionally define 2 autoscaling groups and map one to each launch configuration but this feels really messy. Also these resources themselves have dependent resources such as cloudwatch metric alarms etc. It feels very unDRY to repeat all of this code twice with 2 separate conditions. Am I missing a trick here?

Grateful for any relevant Terraform wisdom!

2
Which AMI you are using?m0hit

2 Answers

5
votes

The count meta-attribute works only on resource-level, unfortunately. Having a conditional block within a resource (such as your ebs_block_device or for example logging or etc) is a problem commonly mentioned in terraform issues in github and as far as I can tell there isn't a solution yet.

In your case a 'trick' could be to have your autoscaling_group.launch_configuration property also have a ternary operator, i.e.

resource "aws_autoscaling_group" "autoscaling_group" {
  name = "foo"
  launch_configuration = "${length(var.ebs_volume_device_name) == 0 ? aws_launch_configuration.launch_configuration.name : aws_launch_configuration.launch_configuration2.name}"
}

Or better yet extract that logic in a launch_configuration module with an output name and then the above can look like

resource "aws_autoscaling_group" "autoscaling_group" {
      name = "foo"
      launch_configuration = "${module.launch_config.name}"
}

Not saying it isn't ugly but that's terraform's conditionals for you.

0
votes

It seems you don't actually need a condition here in aws_launch_configuration resource.

If you are using AWS ECS optimized which is based on the Amazon Linux then it will automatically attach a device volume at /dev/xvdcz with default volume_size=22gb by default.

You can pass the variable to something else(say 50gb) to this variable ${var.ebs_volume_device_name}, if you want to increase or decrease the size of that particular volume depending upon your need.