{"id":85,"date":"2016-11-22T17:40:06","date_gmt":"2016-11-22T17:40:06","guid":{"rendered":"http:\/\/67bricks.com\/blog\/?p=85"},"modified":"2017-01-03T16:37:01","modified_gmt":"2017-01-03T16:37:01","slug":"terraform-tricks-to-cope-with-conditionally-created-resources","status":"publish","type":"post","link":"https:\/\/blog.67bricks.com\/?p=85","title":{"rendered":"Terraform tricks to cope with conditionally created resources"},"content":{"rendered":"<p><a href=\"https:\/\/www.terraform.io\/\">Terraform<\/a> is a great tool and we use it extensively to spin up resources in <a href=\"https:\/\/aws.amazon.com\/\">AWS<\/a>. \u00a0It&#8217;s very easy to get started, the documentation is great and once you have built yourself a development environment it&#8217;s just a matter of changing a few config settings and you have yourself a staging and prod environment too.<\/p>\n<p>It gets more tricky when the different environments are not exactly copies of each other. For example, in development you might want to create a SNS topic to use for testing whereas in staging and production you might want to use an external one.<\/p>\n<p>Creating resources in some environments and not others can be controlled using the <a href=\"https:\/\/www.terraform.io\/intro\/examples\/count.html\">&#8220;count&#8221; parameter<\/a>\u00a0on a resource. So in the case of the SNS topic we only want to create in development, we can set an <code>sns_count<\/code> variable to be 1 in development and 0 elsewhere and use this to only create the topic in development.<\/p>\n<p>But suppose we want to use the <a href=\"http:\/\/docs.aws.amazon.com\/general\/latest\/gr\/aws-arns-and-namespaces.html\">ARN<\/a> of the created topic if it exists, or a fixed ARN of an external topic otherwise. Now it becomes even harder. Suppose that we are creating the SNS topic like this:<\/p>\n<pre>resource \"aws_sns_topic\" \"sns_topic\" {\r\n  name = \"our_topic\"\r\n  count = \"${var.sns_count}\"\r\n}\r\n<\/pre>\n<p>and we have a variable <code>topic_arn<\/code> that will contain a fixed topic ARN to use if we have not created one. Terraform <del>does not have any kind of conditional logic, but<\/del>\u00a0<strong>has a simple ternary function and<\/strong> there is <a href=\"https:\/\/www.terraform.io\/docs\/configuration\/interpolation.html#coalesce_string1_string2_\">a <code>coalesce<\/code> function<\/a> which takes the first non-empty string from a list. So you might think that the following string interpolation would work:<\/p>\n<pre>\"${coalesce(aws_sns_topic.sns_topic.arn, var.topic_arn)}\"\r\n<\/pre>\n<p>Unfortunately it doesn&#8217;t because in the case where we do not create the topic, Terraform complains that there is no <code>arn<\/code> attribute.<\/p>\n<p>So, to get around this we use this syntax instead:<\/p>\n<pre>\"${coalesce(join(\"\", aws_sns_topic.sns_topic.*.arn), var.topic_arn)}\"\r\n<\/pre>\n<p>The <code>.*.arn<\/code> syntax returns a list of the ARNs for all the created topics, which will be either one or none. So we flatten this to a string with <a href=\"https:\/\/www.terraform.io\/docs\/configuration\/interpolation.html#join_delim_list_\">the <code>join<\/code> function<\/a> and finally, it works as we want. Phew!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Terraform is a great tool and we use it extensively to spin up resources in AWS. \u00a0It&#8217;s very easy to get started, the documentation is great and once you have built yourself a development environment it&#8217;s just a matter of changing a few config settings and you have yourself a staging and prod environment too. &hellip; <a href=\"https:\/\/blog.67bricks.com\/?p=85\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Terraform tricks to cope with conditionally created resources&#8221;<\/span><\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,1],"tags":[24],"class_list":["post-85","post","type-post","status-publish","format-standard","hentry","category-nut-and-bolts","category-uncategorized","tag-terraform"],"_links":{"self":[{"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/posts\/85","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=85"}],"version-history":[{"count":3,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/posts\/85\/revisions"}],"predecessor-version":[{"id":92,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=\/wp\/v2\/posts\/85\/revisions\/92"}],"wp:attachment":[{"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=85"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=85"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.67bricks.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=85"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}