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"
}
π 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}"
}
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}"
}
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"
π 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
- Share this post !
Thank You for showing interest and reading this π
Top comments (9)
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!
One simple solution is:
Set the variable in a suitable context, then, use
count
in the resource name with ternary operator: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.
You can do something like:
and no need to create 2 resources, and data to refer the one that got created.
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.
This saved me from going insane in a weird upgrade from 0.12.29->0.12.30 THANK YOU!
Thanks for reading ! I am glad this helped you !
What if I want to create a resource on multiple conditions (I cannot use count twice, and I cannot use terraform 0.12+) ?
Well, glad to say, 2 years later, this is not an issue anymore, once we've upgraded to TF 14 :-p
I was looking for a way to optionally create S3 triggers for Lambda functions and this gave me the perfect solution, thanks!