Usage of Terraform to deploy resources in cloud is very common now a days. And normally we use CI-CD pipeline to automate this deployment process based on our requirements. In our team we use Jenkins and Terraform. Let’s walk you through a Terraform issue.
One of my fellow colleagues faced an issue while running a Jenkins pipeline lately. Terraform Plan stage was failing to parse a variable which type was list
and the error message was not leading us to any solution. Here I am going to walk you through the path we managed to resolve that issue.
The Scenario
In Terraform we have an input variable defined as –
variable "sources" { type = list(string) }
and Jenkins file is written so that, user can provide the values as a comma separated string while deploying the resources. Then Jenkins is creating a list of sources
from that comma separated string as –
def parse_source_ids(ids){ return ids.split(',') }
and being passed in terraform plan
like –
parsed_sources_ids = parse_source_ids(sources_ids) sh """terraform plan -input=false -out plan \ -var="environment=$environment" \ -var="sources=$parsed_sources_ids" """
This is an example command with actual value that ran-
terraform plan -input=false -out plan -var=environment=env -var=sources=[23e7ea8d-e82a-43eb-a208-f446128d5d9b, 562c4d0d-7538-40b8-a60e-8c0c1cf5c3b6]
Everything seems fine until it failed with an error message-
What?
The error message is very confusing. Clearly the error message doesn’t match with what we are seeing. There is something weird happening in the middle.
Then we were looking at the terrraform plan
command more carefully. We were thinking couple of things-
- The value of
environment
was passed correctly - The values in
sources
list are also string(as value of environment was also not enclosed by quote and parsed successfully) and correctly separated by comma - What if we enclose the source ids with quote?
- But they are already enclosed by quotes, aren’t they?
ids.split(',')
should do that right?
Google to Rescue
After thinking random things it’s time for Goggling. It was clear that Terraform is not able to parse the value as list of string. So, Tried some keywords like-
- How to pass a list of string to terraform plan as input variable
- Can’t pass a list of string to terraform plan as input variable
Finally found a Git issue that describes the problem and solution-
In Unix shells, quotes are interpreted by the shell to override the default behavior of splitting arguments with whitespace, and so the first “level” of quotes is consumed by the shell and thus isn’t passed to Terraform at all. The first example
terraform plan -var 'myvar=["zzzz"]'
works because the'
quotes prevent special interpretation of the inner"
quotes and so they are passed by the shell into the command line Terraform sees.Bellow variations won’t work-
terraform plan -var 'myvar=['zzzz']'
terraform plan -var "myvar=['zzzz']"
terraform plan -var myvar=['zzzz']
In short this is a unix shell behavior that consumed the quotes around the source ids in the list and if we put single quote '
around the sources
var like -
var='sources=$parsed_sources_ids'
and make sure double quotes are around the ids in the list then it should work.
Solution
Now we update the terraform plan
command-
parsed_sources_ids = parse_source_ids(sources_ids) sh """terraform plan -input=false -out plan \ -var="environment=$environment" \ -var='sources=$parsed_sources_ids'"""
and the input parser-
def parse_source_ids(ids){ return ids.split(',').collect { it + "," } }
It resolved the issue. Then a successful terraform command looked like-
terraform plan -input=false -out plan -var=environment=env -var=sources=["b8798218-0f2e-4dfb-8e31-0f5db44ca893"]
In conclusion, cloud resource deployment with Terraform and Jenkins is a standard procedure, but it has drawbacks of its own. When parsing a list variable in Terraform via a Jenkins pipeline, we ran into a problem where the Unix shell behavior was eating quotes around the list elements, which led to the failure of the Terraform Plan stage. We found that enclosing the list elements in double quotes and the variable in single quotes fixed the problem after doing some research and consulting internet resources. We were able to successfully implement the Terraform plan thanks to this solution, which guaranteed automated and seamless deployments. I appreciate your attention, and I hope this walkthrough aids in debugging similar problems in your pipelines for continuous integration and delivery.
Tadaaaa……….
Title Image credit – Jammin’ with Terraform, AWS & Jenkins