👷 How to make conditionnal resources in terraform?
Tags: terraform, cloud, beginners
Published: 2019-09-11 07:54:30

I’d like to share my experience about conditional resources in terraform with this short article.

## Use case 🤔

Here is my use case. I am currently experiment lambdas (AWS cloud functions) for a project. My problem is that I don’t know which programming language is the most suitable for my use case. This is why I would like to make a benchmark about execution time and memory consumption for each language.

What I want is to create a terraform configuration that is able to switch my lambda from javascript to java by setting a parameter to `"javascript"` or `"java"`.

## Solution 🤯

My solution was using [meta-arguments](https://www.terraform.io/docs/configuration/resources.html#meta-arguments). The [count](https://www.terraform.io/docs/configuration/resources.html#count-multiple-resource-instances-by-count) meta-argument allows to specify how many instances you want to create.

### 👉 Step 1 : Create your input parameter

```terraform
variable "lambda_type" {
  type    = "string"
  default = "java"
}
```

### 👉 Step 2 : Create your resources

```terraform
locals {
  my_function_name = "awesome-function"
}

resource "aws_lambda_function" "my_lambda_java" {
  filename         = "lambda.jar"
  function_name    = "${local.my_function_name}"
  handler          = "Handler"
  runtime          = "java8"
  count            = "${var.lambda_type == "java" ? 1 : 0}"
}

resource "aws_lambda_function" "my_lambda_javascript" {
  filename         = "lambda.jar"
  function_name    = "${local.my_function_name}"
  handler          = "index.handler"
  runtime          = "nodejs10.x"
  count            = "${var.lambda_type == "javascript" ? 1 : 0}"
}
```

Note the ternary condition to set `count` to 0 or 1 in function of `lambda_type` value.

### 👉 Step 3 : Create a data variable to access your conditional resources from the same id

```terraform
data "aws_lambda_function" "my_lambda" {
  function_name = "${local.my_function_name}"
  depends_on    = ["aws_lambda_function.my_lambda_java", "aws_lambda_function.my_lambda_javascript"]
}

// For instance if your lambda is attached to another resource, 
// you just have to use the same resource id for both (java & javascript)
resource "aws_lambda_permission" "my_lambda_permission" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = "${data.aws_lambda_function.my_lambda.arn}"
  principal     = "sns.amazonaws.com"
  source_arn    = "${aws_sns_topic.topic.arn}"
}
```

Please note that the `depends_on` property is really important. If you don't use that property, terraform will try to fetch lambda function that doesn't exist yet. Plus, this only work for terraform 0.12 which allows to [use `depends_on` with resource with `count = 0`](https://github.com/hashicorp/terraform/issues/15285#issuecomment-447971852).

### 👉 Step 4 : Plan and apply your terraform

Finally, you just have to apply your terraform configuration with the suitable parameter :

```bash
# For javascript
$ terraform plan --var "lambda-type=javascript"
# If the plan is correct to what you expect :
$ terraform apply --var "lambda-type=javascript"

# For java
$ terraform plan --var "lambda-type=java"
# If the plan is correct to what you expect :
$ terraform apply --var "lambda-type=java"
```

### 👉 Step 5 : Clean resources (optional)

If you did some tests by following this article, do not forget to clean your environment by destroying resources !

```
$ terraform destroy
```

## Congratulations ! 🎉

Congratulations ! You did it ! Now you can add resources conditionnaly and therefore make your terraform configuration more parameterizable !

If you liked this post, do not hesitate to :

- Follow me on twitter: [@tbetous](https://twitter.com/tbetous)
- Share this post !

Thank You for showing interest and reading this 🎉