{"id":110,"date":"2023-04-18T09:16:00","date_gmt":"2023-04-18T09:16:00","guid":{"rendered":"https:\/\/cloudtechner.com\/blog\/?p=110"},"modified":"2024-06-13T11:07:09","modified_gmt":"2024-06-13T11:07:09","slug":"using-loops-in-terraform-code","status":"publish","type":"post","link":"https:\/\/cloudtechner.com\/blog\/using-loops-in-terraform-code\/","title":{"rendered":"Using Loops in Terraform Code"},"content":{"rendered":"\n<p>Author: <a href=\"https:\/\/www.linkedin.com\/in\/vartika-srivastava-82b2b7b2\">Vartika Srivastava<\/a>, Senior Engineer &#8211; CloudDevOps<\/p>\n\n\n<div class=\"taxonomy-post_tag wp-block-post-terms\"><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/automation\/\" rel=\"tag\">Automation<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/infrastructure-as-a-code\/\" rel=\"tag\">Infrastructure as a Code<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/terraform\/\" rel=\"tag\">Terraform<\/a><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:980\/1*1WEW77XpBgSpQqrQrCRg3A.jpeg\" alt=\"\"\/><\/figure><\/div>\n\n\n<p id=\"4729\">Terraform is an infrastructure as code tool that allows users to define their infrastructure in terms of code.<\/p>\n\n\n\n<p id=\"af03\">Loops are an essential feature of Terraform that allows us to automate the repeated tasks in the infrastructure deployment process. Terraform supports the use of loops in various scenarios, including resource creation, configuration, and variable assignments. Some of the primary reasons for using loops in Terraform are:<\/p>\n\n\n\n<ul>\n<li><strong>Efficiency:<\/strong>&nbsp;With loops, we can manage multiple resources or environments using a single code block, which is an efficient way of creating and updating infrastructure.<\/li>\n\n\n\n<li><strong>Flexibility:<\/strong>&nbsp;We can leverage loops to make the code more flexible and scalable, allowing easy adjustments to the number of infrastructure resources based on requirements.<\/li>\n\n\n\n<li><strong>Consistency:<\/strong>&nbsp;Loops provide consistent configuration, especially when dealing with multiple resources, ensuring that all the infrastructure is the same, reducing errors and increasing reliability.<\/li>\n\n\n\n<li><strong>Reducing code redundancy:<\/strong>&nbsp;With loops, we eliminate the need for repetitive coding, which can reduce the code base size, making it more manageable and easier to read.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2439\"><strong>Types of Loops<\/strong><\/h3>\n\n\n\n<p id=\"a5af\">There are three types of loops in Terraform:<\/p>\n\n\n\n<ul>\n<li>count loop<\/li>\n\n\n\n<li>for_each loop<\/li>\n\n\n\n<li>for loop<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\" id=\"e300\">count loop<\/h5>\n\n\n\n<p id=\"6855\">The&nbsp;<strong><em>count<\/em><\/strong>&nbsp;loop creates a specified number of identical resources. It iterates over a list of integers with the specified count and creates a resource for each integer in the list.<\/p>\n\n\n\n<p id=\"3f64\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_instance\" \"example\" {<br>  ami           = \"ami-0c55b159cbfafe1f0\"<br>  instance_type = \"t2.micro\"<br>  count         = 2<br>}<\/code><\/pre>\n\n\n\n<p id=\"96f8\">In the above example, Terraform creates two EC2 instances.<\/p>\n\n\n\n<p id=\"404e\">When&nbsp;<em>count<\/em>&nbsp;is in use, each instance of a resource or module gets a separate index, representing its place in the order of creation. To get a value from a single resource created in this way, you must refer to it by its index value, e.g. if you wished to see the ID of the 1st instance, you would need to call it as such:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>output \"1stinstance_id\" {<br>default = aws_instance.example&#91;0].id<br>}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\" id=\"d173\">for_each loop<\/h5>\n\n\n\n<p id=\"afcc\">The&nbsp;<strong><em>for_each<\/em><\/strong>&nbsp;loop creates multiple resources with different attributes. It accepts a map or a set of objects as input and creates a separate resource for each map or set element. The resources can access values contained within, via&nbsp;<em>each.key<\/em>&nbsp;and&nbsp;<em>each.value<\/em>:<\/p>\n\n\n\n<p id=\"d43a\">Example using map:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>variable \"instances\" {<br>  type = map(object({<br>    ami           = string<br>    instance_type = string<br>  }))<br>  default = {<br>    example-instance-1 = {<br>      ami           = \"ami-014a674a1c7807f2a\"<br>      instance_type = \"t2.micro\"<br>    }<br>    example-instance-2 = {<br>      ami           = \"ami-014a674a1c7807f2a\"<br>      instance_type = \"t2.micro\"<br>    }<br>  }<br>}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_instance\" \"example\" {<br>  for_each = var.instances  ami           = each.value.ami<br>  instance_type = each.value.instance_type<br>}<\/code><\/pre>\n\n\n\n<p id=\"3391\">In the above example, Terraform creates two EC2 instances with different names and attributes.<\/p>\n\n\n\n<p id=\"7cc0\">Example using set of objects:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>variable \"users\" {<br>  type = set(string)<br>  default = &#91;\"alice\", \"bob\", \"charlie\"]<br>}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_iam_user\" \"example\" {<br>  for_each = var.users<br>  name = each.value<br>}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\" id=\"b7fc\">for loop<\/h5>\n\n\n\n<p id=\"4c8c\">The<strong><em>&nbsp;for<\/em><\/strong>&nbsp;loop is designed for selecting elements from complex collections and performing operations on them. Assume you have a list of words (strings), and you want to covert them all into capitals in on go.<\/p>\n\n\n\n<p id=\"fe25\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>country_list = &#91;<br>\"Amercia\",<br>\"jaPan\", <br>\"InDia\", <br>\"LonDON\"<br>]<\/code><\/pre>\n\n\n\n<p id=\"30b9\">To convert them all into capitals you would simply do below steps<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;for country in var.country_list : upper(country)]<\/code><\/pre>\n\n\n\n<p id=\"56e9\">And it would result in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\"AMERICA\", \"JAPAN\", \"INDIA\", \"LONDON\"]<\/code><\/pre>\n\n\n\n<p id=\"acb7\">The for expression\u2019s output is dependent on the type of input and the brackets around it. It would have produced a map if you had enclosed it in curly brackets and used a map as the input.<\/p>\n\n\n\n<p id=\"1f60\">In above example you have seen that we have given input as list and we got the output as list only.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"54f7\">Handling maps using for loop<\/h3>\n\n\n\n<p id=\"0260\">Let\u2019s see what happens if we give map as input and produce its output as list or give list as input and produce output as map using&nbsp;<strong><em>for&nbsp;<\/em><\/strong>loop<\/p>\n\n\n\n<p id=\"964f\"><strong>Map to List<\/strong><\/p>\n\n\n\n<p id=\"3c37\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>locals {<br>  list = {a = 1, b = 2, c = 3}<br>}<br>output \"result1\" {<br>  value = &#91;for k,v in local.list : \"${k}-${v}\" ]<br>}<br>output \"result2\" {<br>  value = &#91;for k in local.list : k ]<br>}<\/code><\/pre>\n\n\n\n<p id=\"7657\">Results:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>result1 = &#91;\"a-1\", \"b-2\", \"c-3\"]<br>result2 = &#91;1, 2, 3]<\/code><\/pre>\n\n\n\n<p id=\"4750\">In the above example,&nbsp;<strong>k<\/strong>&nbsp;denotes the key and&nbsp;<strong>v<\/strong>&nbsp;denotes the value. So, when the input source is a Map, you can access the key and value. We got output as list because of [] square brackets.<\/p>\n\n\n\n<p id=\"4a0e\"><strong>List to Map<\/strong><\/p>\n\n\n\n<p id=\"d8bf\">To return the map type output, the output value should be enclosed in {} curly brackets.<\/p>\n\n\n\n<p id=\"0633\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>locals {<br>  list = &#91;\"a\",\"b\",\"c\"]<br>}<br>output \"result\" {<br>  value = {for i in local.list : i =&gt; i }<br>}<\/code><\/pre>\n\n\n\n<p id=\"62a0\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>result = {<br>  \"a\" = \"a\"<br>  \"b\" = \"b\"<br>  \"c\" = \"c\"<br>}<\/code><\/pre>\n\n\n\n<p id=\"63c7\">As you can see, a Map is now the result output type. It\u2019s crucial to keep in mind that when returning a Map, we must include an expression with the =&gt;. You\u2019ll experience the following error if you don\u2019t:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Error: Invalid 'for' expression<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>  on main.tf line 5, in output \"result\":<br>   5:   value = {for i in local.list : i }<\/code><\/pre>\n\n\n\n<p id=\"efdc\"><strong>Map to Map<\/strong><\/p>\n\n\n\n<p id=\"30c3\">For Map to map result, the input and output both should be enclosed in curly {} brackets.<\/p>\n\n\n\n<p id=\"1db8\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>locals {<br>  list = {a = 1, b = 2, c = 3}<br>}<br>output \"result\" {<br>  value = {for k,v in local.list : k =&gt; v }<br>}<\/code><\/pre>\n\n\n\n<p id=\"c4fd\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>result = {<br>  \"a\" = 1<br>  \"b\" = 2<br>  \"c\" = 3<br>}<\/code><\/pre>\n\n\n\n<p id=\"88db\">So, when a&nbsp;<em>for&nbsp;<\/em>expression is wrapped around [] square brackets, then the result would be in list, when a&nbsp;<em>for&nbsp;<\/em>expression is wrapped<em>&nbsp;<\/em>around curly brackets {}, then the result would be in map and most importantly, when you are returning output as map, the expression elements should be separated by =&gt;.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"b799\">Handling filters using for loop<\/h3>\n\n\n\n<p id=\"94ee\">One more thing which is also very interesting about<em>&nbsp;<\/em><strong><em>for<\/em><\/strong><em>&nbsp;<\/em>loops is that you can use the&nbsp;<strong><em>for<\/em><\/strong>&nbsp;expression to filter the input anyway you like. You can conditionally operate on particular values or not, depending on your stated terms, by including an if clause.<\/p>\n\n\n\n<p id=\"17fa\"><strong>Filter Simple Elements<\/strong><\/p>\n\n\n\n<p id=\"4919\">You want to remove newline character from every element except&nbsp;<em>\u201cLondon.\u201d<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>country_list = &#91;<br>\"Amercia\\n\",<br>\"jaPan\\n\", <br>\"InDia\\n\", <br>\"London\"<br>]<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;for country in var.country_list : chomp(country) if country != \"London\"]<\/code><\/pre>\n\n\n\n<p id=\"d5fa\"><strong>Filter Map Elements<\/strong><\/p>\n\n\n\n<p id=\"d17e\">In this example, the elements are Maps. We\u2019ll transform the data to only return the values, but only if the b key\u2019s value is greater than 6.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>locals {<br>  list = &#91;<br>    {a = 1, b = 5},<br>    {a = 2, b = 6},<br>    {a = 3, b = 7},<br>    {a = 4, b = 8},<br>  ]<br>}<br>output \"list\" {<br>  value = &#91;for m in local.list : values(m) if m.b &gt; 6 ]<br>}<\/code><\/pre>\n\n\n\n<p id=\"11ec\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>list = &#91;<br>  &#91;3,7]<br>  &#91;4,8],<br>]<\/code><\/pre>\n\n\n\n<p id=\"f3a6\"><strong>Filter Inconsistent Map Elements<\/strong><\/p>\n\n\n\n<p id=\"b809\">Let\u2019s say the Map elements are a little bit inconsistent, like some of them lack the b key. We can filter for that.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>locals {<br>  list = &#91;<br>    {a = 1, b = 5},<br>    {a = 2},<br>    {a = 3},<br>    {a = 4, b = 8},<br>  ]<br>}<br>output \"list\" {<br>  value = &#91;for m in local.list : m if contains(keys(m), \"b\") ]<br>}<\/code><\/pre>\n\n\n\n<p id=\"cbf9\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>list = &#91;<br>  {\"a\" = 1, \"b\" = 5},<br>  {\"a\" = 4, \"b\" = 8},<br>]<\/code><\/pre>\n\n\n\n<p id=\"10f3\">Loops in Terraform can help in reducing manual work and keep the code DRY (Don\u2019t Repeat Yourself). It allows creating multiple resources based on various inputs and saves time and effort.<\/p>\n\n\n\n<p id=\"50e4\">Overall, Loops are a useful feature that enhances Terraform\u2019s functionality, making it possible to deploy standardized and scalable infrastructures with minimal effort.<\/p>\n\n\n\t<div id=\"respond\" class=\"comment-respond wp-block-post-comments-form\">\n\t\t<h3 id=\"reply-title\" class=\"comment-reply-title\">Leave a Reply <small><a rel=\"nofollow\" id=\"cancel-comment-reply-link\" href=\"\/blog\/wp-json\/wp\/v2\/posts\/110#respond\" style=\"display:none;\">Cancel reply<\/a><\/small><\/h3><form action=\"https:\/\/cloudtechner.com\/blog\/wp-comments-post.php\" method=\"post\" id=\"commentform\" class=\"comment-form\"><p class=\"comment-notes\"><span id=\"email-notes\">Your email address will not be published.<\/span> <span class=\"required-field-message\">Required fields are marked <span class=\"required\">*<\/span><\/span><\/p><p class=\"comment-form-comment\"><label for=\"comment\">Comment <span class=\"required\">*<\/span><\/label> <textarea id=\"comment\" name=\"comment\" cols=\"45\" rows=\"8\" maxlength=\"65525\" required=\"required\"><\/textarea><\/p><p class=\"comment-form-author\"><label for=\"author\">Name <span class=\"required\">*<\/span><\/label> <input id=\"author\" name=\"author\" type=\"text\" value=\"\" size=\"30\" maxlength=\"245\" autocomplete=\"name\" required=\"required\" \/><\/p>\n<p class=\"comment-form-email\"><label for=\"email\">Email <span class=\"required\">*<\/span><\/label> <input id=\"email\" name=\"email\" type=\"text\" value=\"\" size=\"30\" maxlength=\"100\" aria-describedby=\"email-notes\" autocomplete=\"email\" required=\"required\" \/><\/p>\n<p class=\"comment-form-url\"><label for=\"url\">Website<\/label> <input id=\"url\" name=\"url\" type=\"text\" value=\"\" size=\"30\" maxlength=\"200\" autocomplete=\"url\" \/><\/p>\n<p class=\"comment-form-cookies-consent\"><input id=\"wp-comment-cookies-consent\" name=\"wp-comment-cookies-consent\" type=\"checkbox\" value=\"yes\" \/> <label for=\"wp-comment-cookies-consent\">Save my name, email, and website in this browser for the next time I comment.<\/label><\/p>\n<p class=\"form-submit\"><span class=\"bloghash-submit-form-button\"><input name=\"submit\" type=\"submit\" id=\"submit\" class=\"submit\" value=\"Post Comment\" \/><\/span> <input type='hidden' name='comment_post_ID' value='110' id='comment_post_ID' \/>\n<input type='hidden' name='comment_parent' id='comment_parent' value='0' \/>\n<\/p><\/form>\t<\/div><!-- #respond -->\n\t\n\n\n<p><a href=\"https:\/\/medium.com\/@vartika.srivastava?source=post_page-----6a39340cb6ef--------------------------------\"><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Author: Vartika Srivastava, Senior Engineer &#8211; CloudDevOps Terraform is an infrastructure as code tool that allows users to define their infrastructure in terms of code. Loops are an essential feature&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[69,70,71],"tags":[66,67,68],"_links":{"self":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/110"}],"collection":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/comments?post=110"}],"version-history":[{"count":2,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions"}],"predecessor-version":[{"id":149,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions\/149"}],"wp:attachment":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/media?parent=110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/categories?post=110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/tags?post=110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}