<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marius Tolzmann</title>
    <description>The latest articles on DEV Community by Marius Tolzmann (@mariux).</description>
    <link>https://dev.to/mariux</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F172355%2F7e2f9eaf-6ae6-43fb-8dcf-d23362916004.jpeg</url>
      <title>DEV Community: Marius Tolzmann</title>
      <link>https://dev.to/mariux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariux"/>
    <language>en</language>
    <item>
      <title>The Ultimate Guide on How to Write Terraform Modules — Part 1</title>
      <dc:creator>Marius Tolzmann</dc:creator>
      <pubDate>Tue, 21 Apr 2020 22:50:47 +0000</pubDate>
      <link>https://dev.to/mariux/the-ultimate-guide-on-how-to-write-terraform-modules-part-1-2fc2</link>
      <guid>https://dev.to/mariux/the-ultimate-guide-on-how-to-write-terraform-modules-part-1-2fc2</guid>
      <description>&lt;h1&gt;
  
  
  Building a Foundation
&lt;/h1&gt;

&lt;p&gt;This is an opinionated view on how to write awesome Terraform modules that follow best practices as defined in &lt;a href="https://www.terraform.io/docs/modules/index.html"&gt;"Creating Modules"&lt;/a&gt; and introduce new best practices that we follow when writing new modules.&lt;br&gt;
As we are making heavy use of latest Terraform features the minimum version of Terraform that should be used is v0.12.20 [Jan 22, 2020] as this version introduces support for the functions &lt;a href="https://www.terraform.io/docs/configuration/functions/try.html"&gt;try()&lt;/a&gt; and &lt;a href="https://www.terraform.io/docs/configuration/functions/can.html"&gt;can()&lt;/a&gt; and also includes support for resource-level &lt;a href="https://www.terraform.io/docs/configuration/expressions.html"&gt;for_each&lt;/a&gt; (introduced in v0.12.6 and fully functional since v0.12.9 [Sep 17 2019]).&lt;br&gt;
All assumptions and issues mentioned are based on the latest Terraform version as of writing this article is v0.12.24 [Mar 19, 2020].&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents of Part 1
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Basic Module Structure Recap&lt;/li&gt;
&lt;li&gt;Introducing &lt;code&gt;module_depends_on&lt;/code&gt; Attribute&lt;/li&gt;
&lt;li&gt;Introducing &lt;code&gt;module_enabled&lt;/code&gt; Attribute&lt;/li&gt;
&lt;li&gt;Conclusion and outlook&lt;/li&gt;
&lt;li&gt;In the next Parts of this series&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Basic Module Structure Recap
&lt;/h2&gt;

&lt;p&gt;When creating new modules the general best practices as described in Hashicorps official Terraform documentation in the &lt;a href="https://www.terraform.io/docs/modules/index.html"&gt;creating modules&lt;/a&gt; section should be followed. The basics are not covered here again, as we think, repeating the content in different words will not result in a better version. Also, the use of submodules will not be covered again. Everything explained in the following sections applies to submodules as well.&lt;/p&gt;

&lt;p&gt;A general terraform module structure should have the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input variables should be defined in &lt;code&gt;variables.tf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Resources and Data sources should be defined in &lt;code&gt;main.tf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Output values should be defined in &lt;code&gt;outputs.tf&lt;/code&gt; (we will cover details in Part 2 of this series)&lt;/li&gt;
&lt;li&gt;Dependencies on a specific version of terraform and all used providers should be
maintained in &lt;code&gt;versions.tf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Documentation is key and every module should have a &lt;code&gt;README.md&lt;/code&gt; describing
the general usage, input variables, and outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For running examples in this article, we created a module that follows those best practices. The module is named &lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/modules/terraform-null-resource"&gt;terraform-null-resource&lt;/a&gt; and can be found &lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/modules/terraform-null-resource"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Introducing &lt;code&gt;module_depends_on&lt;/code&gt; Attribute
&lt;/h2&gt;

&lt;p&gt;The current version of Terraform does not support the &lt;code&gt;depends_on&lt;/code&gt; attribute for modules. The &lt;code&gt;depends_on&lt;/code&gt; attribute in resources should be used for hidden dependencies that terraform is not able to spot based on direct usage of references between resources.&lt;/p&gt;

&lt;p&gt;In some cases, a &lt;code&gt;depends_on&lt;/code&gt; hint would be useful also in more complex modules. To work around the limitations we introduced a &lt;code&gt;module_depends_on&lt;/code&gt; attribute in modules that enables resources inside the module to explicitly depend on external resources outside of the module.&lt;/p&gt;

&lt;p&gt;Without this feature, internal and external resources will be created in parallel and results might be random and subject to race conditions in rare cases.&lt;/p&gt;

&lt;p&gt;The implementation of this workaround is straight-forward and can be introduced in existing modules without a breaking change.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a variable named &lt;code&gt;module_depends_on&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add or extend a &lt;code&gt;depends_on&lt;/code&gt; attribute for all resources in the module&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Create a variable named &lt;code&gt;module_depends_on&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Add a new variable named &lt;code&gt;module_depends_on&lt;/code&gt; to the module's &lt;code&gt;variables.tf&lt;/code&gt; file. The type of the variable is set to &lt;code&gt;list(any)&lt;/code&gt; to mimic the &lt;code&gt;depends_on&lt;/code&gt; terraform feature as close as possible. The default value of this variable should be an empty list stating that no external dependencies exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"module_depends_on"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"(optional) A list of external resources the module depends_on. Default is []."&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Add or extend a &lt;code&gt;depends_on&lt;/code&gt; attribute for all resources in the module
&lt;/h3&gt;

&lt;p&gt;The easiest way to make sure the expected results are achieved is to make all module resources depend on the external resources. But as this will reduce parallelism due to not satisfying dependencies you might want to consider just adding a &lt;code&gt;depends_on&lt;/code&gt; attribute to some resources.&lt;/p&gt;

&lt;p&gt;Terraforms HCL interpolation algorithms for variables do not require any fancy dependency definition. It is sufficient to let the resources just depend on the variable itself. See an example of a &lt;code&gt;null&lt;/code&gt; resource on how to implement this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"label"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;omitted&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module_depends_on&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  See &lt;code&gt;module_depends_on&lt;/code&gt; in action
&lt;/h3&gt;

&lt;p&gt;We've created a test module (&lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/modules/terraform-null-resource"&gt;terraform-null-resource&lt;/a&gt;) and an &lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/examples/module_depends_on"&gt;example to show the &lt;code&gt;module_depends_on&lt;/code&gt;&lt;/a&gt; in action. The example will create a bunch of &lt;code&gt;null_resource&lt;/code&gt; resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# Case 1:&lt;/span&gt;
&lt;span class="c1"&gt;# Default module usage without hidden external dependencies&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# Resources in this module will be created/destroyed as soon as possible&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"has-no-dependency"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/mineiros-io/article-examples/terraform/modules/terraform-null-resource"&lt;/span&gt;

  &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ASAP!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# This resource will be created/destroyed as soon as possible&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"is-no-dependency"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# Case 2:&lt;/span&gt;
&lt;span class="c1"&gt;# Make use of module_depends_on to define hidden external dependencies&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# Apply: Resources in this module will be created after the creation of the&lt;/span&gt;
&lt;span class="c1"&gt;# null_resource.is-external-dependency is completed.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Destroy: Resources in this module will be destroyed before the destruction of the&lt;/span&gt;
&lt;span class="c1"&gt;# null_resource.is-external-dependency is started.&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"has-external-dependency"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/mineiros-io/article-examples/terraform/modules/terraform-null-resource"&lt;/span&gt;

  &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Let's wait!"&lt;/span&gt;

  &lt;span class="nx"&gt;module_depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;null_resource&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dependency&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# Apply: This resource will be created before the creation of the resources&lt;/span&gt;
&lt;span class="c1"&gt;# module.has-external-dependency.* is started&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Destroy: Destruction of this resource will be deferred after all&lt;/span&gt;
&lt;span class="c1"&gt;# module.has-external-dependency.* resources have been destroyed completely&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"is-external-dependency"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This sets up a dependency on &lt;code&gt;null_resource.is-external-dependency&lt;/code&gt; for &lt;code&gt;module.has-external-dependency&lt;/code&gt;. So resources within the module will be created after &lt;code&gt;null_resource.is-external-dependency&lt;/code&gt;. In this case &lt;code&gt;module.has-external-dependency.null_resource.single[0]&lt;/code&gt; will be created last and &lt;code&gt;null_resource.is-external-dependency&lt;/code&gt; will be destroyed last.&lt;/p&gt;

&lt;p&gt;To try this out repeat the following steps to clone and initialize the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/mineiros-io/article-examples.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;article-examples/terraform/examples/module_depends_on
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now apply the module and destroy it afterwards. The resources that will be created are null_resource resources and not real infrastructure so not costs will be generated. The used backend will be Terraform's &lt;a href="https://www.terraform.io/docs/backends/types/local.html"&gt;local backend&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
module.has-no-dependency.null_resource.single[0]: Creating...
null_resource.is-external-dependency: Creating...
null_resource.is-no-dependency: Creating...
null_resource.is-external-dependency: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2158780084618493749]
null_resource.is-no-dependency: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1313529758799204548]
module.has-no-dependency.null_resource.single[0]: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;933328012311274445]
module.has-external-dependency.null_resource.single[0]: Creating...
module.has-external-dependency.null_resource.single[0]: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3613129016092343865]

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 4 added, 0 changed, 0 destroyed.

&lt;span class="nv"&gt;$ &lt;/span&gt;terraform destroy &lt;span class="nt"&gt;-refresh&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
null_resource.is-no-dependency: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1313529758799204548]
module.has-external-dependency.null_resource.single[0]: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3613129016092343865]
module.has-external-dependency.null_resource.single[0]: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s
module.has-no-dependency.null_resource.single[0]: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;933328012311274445]
module.has-no-dependency.null_resource.single[0]: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s
null_resource.is-no-dependency: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s
null_resource.is-external-dependency: Destroying... &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2158780084618493749]
null_resource.is-external-dependency: Destruction &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s

Destroy &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 4 destroyed.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the protocol above you can see how all resources are created and destroyed as soon as possible and in parallel but only the setup dependency is deferred to the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;module_enabled&lt;/code&gt; Attribute
&lt;/h2&gt;

&lt;p&gt;At the time of writing, there aren't any existing workarounds for the missing &lt;code&gt;count&lt;/code&gt; or &lt;code&gt;for_each&lt;/code&gt; support. If you only like to trigger a module to be active or inactive based on the evaluation of an expression we recommend you implement a variable e.g. &lt;code&gt;module_enabled&lt;/code&gt; to trigger the desired behavior.&lt;br&gt;
Once &lt;code&gt;module_enabled&lt;/code&gt; is set to false no resources in the module should be created. Some module providers implement this with different naming like &lt;code&gt;create&lt;/code&gt; or &lt;code&gt;enabled&lt;/code&gt; but we decided to prefix this so conflicts are less likely.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing &lt;code&gt;module_enabled&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;So how would the implementation of &lt;code&gt;module_enabled&lt;/code&gt; look like? Every resource within a module should either implement &lt;code&gt;count&lt;/code&gt; or &lt;code&gt;for_each&lt;/code&gt; depending on the value of &lt;code&gt;var.module_enabled&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To implement the &lt;code&gt;module_enabled&lt;/code&gt; feature some simple changes to the base example need to be made:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a variable &lt;code&gt;module_enabled&lt;/code&gt; that defaults to &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change all resources to depend on the state of &lt;code&gt;var.module_enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adjust outputs&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Add a variable &lt;code&gt;module_enabled&lt;/code&gt; that defaults to &lt;code&gt;true&lt;/code&gt;.
&lt;/h4&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"module_enabled"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"(optional) Whether to create resources within the module or not. Default is true."&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Change all resources to depend on the state of &lt;code&gt;var.module_enabled&lt;/code&gt;.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; for single resources that do not use &lt;code&gt;count&lt;/code&gt; or &lt;code&gt;for_each&lt;/code&gt; this will add a &lt;code&gt;count&lt;/code&gt; of either 1 or 0.&lt;/p&gt;

&lt;p&gt;If this is an already exiting and published module this  will introduce a major breaking change as resources will be destroyed and recreated under a new name:&lt;/p&gt;

&lt;p&gt;In the given example &lt;code&gt;module.somename.null_resource.single&lt;/code&gt; will be destroyed and &lt;code&gt;module.somename.null_resource.single[0]&lt;/code&gt; will be created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"single"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module_enabled&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# ATTENTION: BREAKING CHANGE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"count"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module_enabled&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;examplelist&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"for_each"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module_enabled&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;toset&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;examplelist&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Adjust Outputs
&lt;/h4&gt;

&lt;p&gt;For the introduced breaking change on single resources, you need to adjust the outputs also. In addition to that, we recommend exporting the final value of &lt;code&gt;module_enabled&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"module_enabled"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Whether the module is enabled or not."&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module_enabled&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"single"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The single null_resource object."&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;null_resource&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;single&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  See &lt;code&gt;module_enabled&lt;/code&gt; in action
&lt;/h1&gt;

&lt;p&gt;We created a test module (&lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/modules/terraform-null-resource"&gt;terraform-null-resource&lt;/a&gt;) and an &lt;a href="https://github.com/mineiros-io/article-examples/tree/master/terraform/examples/module_enabled"&gt;example to show the &lt;code&gt;module_enabled&lt;/code&gt;&lt;/a&gt; in action. The example will create a bunch of &lt;code&gt;null_resource&lt;/code&gt; resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# The resources in this module will be created.&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"hello-world"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/mineiros-io/article-examples/terraform/modules/terraform-null-resource"&lt;/span&gt;

  &lt;span class="nx"&gt;string&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;
  &lt;span class="nx"&gt;list_of_strings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world!"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# No resources in this module will be created&lt;/span&gt;
&lt;span class="c1"&gt;# ------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"the-cake-is-a-lie"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/mineiros-io/article-examples/terraform/modules/terraform-null-resource"&lt;/span&gt;

  &lt;span class="nx"&gt;module_enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="nx"&gt;string&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello Portal!"&lt;/span&gt;
  &lt;span class="nx"&gt;list_of_strings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"portal!"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To try this out repeat the following steps to clone and initialize the example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/mineiros-io/article-examples.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;article-examples/terraform/examples/module_enabled
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we run &lt;code&gt;terraform apply&lt;/code&gt; on the module. The resources that will be created are of the type &lt;a href="https://www.terraform.io/docs/providers/null/resource.html"&gt;null_resource&lt;/a&gt;. Since null resources won't deploy any real infrastructure components, no costs will be caused. The backend used will be Terraform's &lt;a href="https://www.terraform.io/docs/backends/types/local.html"&gt;local backend&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
module.hello-world.null_resource.count[1]: Creating...
module.hello-world.null_resource.single[0]: Creating...
module.hello-world.null_resource.for_each[&lt;span class="s2"&gt;"world!"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: Creating...
module.hello-world.null_resource.for_each[&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: Creating...
module.hello-world.null_resource.single[0]: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30127531696241687]
module.hello-world.null_resource.count[0]: Creating...
module.hello-world.null_resource.count[1]: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8363602364283639683]
module.hello-world.null_resource.for_each[&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3274290552939669927]
module.hello-world.null_resource.for_each[&lt;span class="s2"&gt;"world!"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;57837020342794834]
module.hello-world.null_resource.count[0]: Creation &lt;span class="nb"&gt;complete &lt;/span&gt;after 0s &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7157558843500998853]

Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 5 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the protocol above you can see that Terraform creates the resources that are associated with the enabled module only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and outlook
&lt;/h2&gt;

&lt;p&gt;Terraform has some limitations as of today. Introducing &lt;code&gt;module_depends_on&lt;/code&gt; and &lt;code&gt;module_enabled&lt;/code&gt; can easily work around these limitations. When creating new modules we recommend implementing those features so that users of the module can enable/disable modules programmatically for specific environments. Also to avoid race conditions when creating resources in parallel and having a hidden dependency on external resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Future of &lt;code&gt;module_depends_on&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Future versions of Terraform will most likely include &lt;code&gt;depends_on&lt;/code&gt; for modules, which will make the full module and thus all resources in the module depend on external resource and deffer internal resource creation after the depending resources are created.&lt;/p&gt;

&lt;p&gt;But even if native support for &lt;code&gt;depends_on&lt;/code&gt; will be available the &lt;code&gt;module_depends_on&lt;/code&gt; approach might be able to deliver a more fine-grained dependency definition by allowing to only make some resources in a module depend on external resources and not all of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Future of &lt;code&gt;module_enabled&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Once Terraform implements &lt;code&gt;count&lt;/code&gt; support for modules, the &lt;code&gt;module_enabled&lt;/code&gt; feature will not be needed for new modules anymore. Existing modules might need to keep the &lt;code&gt;module_enabled&lt;/code&gt; implementation available because adding a count to modules will rename the resource in the state file and trigger a destroy/create action on the resources in the module (e.g.  the &lt;code&gt;module.has-external-dependency.null_resource.single[0]&lt;/code&gt; will then be called &lt;code&gt;module.has-external-dependency[0].null_resource.single[0]&lt;/code&gt; when adding &lt;code&gt;count = 1&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  In the next Parts of this series
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Part 2 of this series will cover - non-tech best practices
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;What kind of module do you want to write?&lt;/li&gt;
&lt;li&gt;Rethinking module outputs&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Part 3 of this series will cover - improving the state
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why you should use &lt;code&gt;for_each&lt;/code&gt; instead of &lt;code&gt;count&lt;/code&gt; in resources?&lt;/li&gt;
&lt;li&gt;Computed vs. Non-Computed Variables&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Part 4 of this series will cover - deep tech issue workarounds
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;How to work around HCLs limitations and existing issues&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  We are here to share our knowledge!
&lt;/h2&gt;

&lt;p&gt;If you need help or more information, don’t hesitate to comment or just send us an email at &lt;a href="mailto:hello@mineiros.io"&gt;hello@mineiros.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>iac</category>
      <category>devops</category>
      <category>bestpractice</category>
    </item>
  </channel>
</rss>
