DEV Community

Cover image for πŸ‘· How to make conditionnal resources in terraform?
Thomas Betous
Thomas Betous

Posted on

Terraform Conditional Resource πŸ‘· How to make conditionnal resources in terraform?

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. The count meta-argument allows to specify how many instances you want to create.

πŸ‘‰ Step 1 : Create your input parameter

variable "lambda_type" {
  type    = "string"
  default = "java"
}
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Step 2 : Create your resources

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}"
}
Enter fullscreen mode Exit fullscreen mode

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

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}"
}
Enter fullscreen mode Exit fullscreen mode

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.

πŸ‘‰ Step 4 : Plan and apply your terraform

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

# 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"
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ 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
Enter fullscreen mode Exit fullscreen mode

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
  • Share this post !

Thank You for showing interest and reading this πŸŽ‰

Top comments (9)

Collapse
 
speculatrix profile image
Paul M • Edited

a great solution and identified exactly what I needed, to create different IAM role/polices according to whether an environment was dev, pre-prod or live-production, so I needed to turn on things according to the variable var.environment_name. easy peasy!

Collapse
 
tomharrisonjr profile image
Tom Harrison

One simple solution is:

  1. create a variable, e.g.
variable "make_lambda" {
  type = bool
  default = true
  description = "Make the Lambda resource unless false"
}
Enter fullscreen mode Exit fullscreen mode

Set the variable in a suitable context, then, use count in the resource name with ternary operator:

resource "aws_lambda_function" "my_lambda" {
  count = var.make_lambda ? 1 : 0
  filename = "lambda.jar"
  ... etc
}
Enter fullscreen mode Exit fullscreen mode

The value of count determines how many instances of a resource will be created. While its intent is for things like clusters of machines, in this usage we'll either create 1 or 0 of the resource depending on the value of the boolean.

Collapse
 
orcalock profile image
Warlock Orca • Edited

You can do something like:

resource "aws_lambda_function" "my_lambda" {
  filename = "lambda.jar"
  function_name = "${local.my_function_name}"
  handler = "${var.lambda_type == "java" ? "Handler" : "index.handler"}"
  runtime = "${var.lambda_type == "java" ? "java8" : "nodejs10.x"}"
}

and no need to create 2 resources, and data to refer the one that got created.

Collapse
 
tbetous profile image
Thomas Betous • Edited

I havn't tested your suggestion but it seems to be a great solution ! I'll definitvly test that next time !

Thanks for your comment.

Collapse
 
chiefy profile image
Christopher "Chief" Najewicz

This saved me from going insane in a weird upgrade from 0.12.29->0.12.30 THANK YOU!

Collapse
 
tbetous profile image
Thomas Betous

Thanks for reading ! I am glad this helped you !

Collapse
 
archmangler profile image
Traiano Welcome

What if I want to create a resource on multiple conditions (I cannot use count twice, and I cannot use terraform 0.12+) ?

Collapse
 
archmangler profile image
Traiano Welcome

Well, glad to say, 2 years later, this is not an issue anymore, once we've upgraded to TF 14 :-p

Collapse
 
griffinator76 profile image
Nathan Griffiths

I was looking for a way to optionally create S3 triggers for Lambda functions and this gave me the perfect solution, thanks!