{"id":2352,"date":"2021-12-19T14:14:31","date_gmt":"2021-12-19T20:14:31","guid":{"rendered":"https:\/\/www.ciraltos.com\/?p=2352"},"modified":"2023-03-23T05:31:42","modified_gmt":"2023-03-23T10:31:42","slug":"modules-and-outputs-with-terraform-and-azure","status":"publish","type":"post","link":"https:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/","title":{"rendered":"Modules and Outputs with Terraform and Azure"},"content":{"rendered":"\n<figure class=\"wp-block-image alignleft size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"176\" height=\"186\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/11\/Terraform_VerticalLogo_Color_RGB-2.png\" alt=\"\" class=\"wp-image-2303\"\/><\/figure>\n\n\n\n<p>Modules and outputs are two important concepts for creating quality, reusable Terraform code.&nbsp; This post and accompanying video put those concepts into practice.&nbsp; This is a lengthy subject, so grab a drink of your choice and settle in for the ride.&nbsp; Also, if you are getting started with Terraform, be sure to check out my other articles and videos on using Terraform.&nbsp; The information below assumes some knowledge of Terraform.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p><a rel=\"noreferrer noopener\" aria-label=\"Getting started with Terraform and Azure: Overview and Setup (opens in a new tab)\" href=\"https:\/\/www.ciraltos.com\/getting-started-with-terraform-and-azure-overview-and-setup\/\" target=\"_blank\">Getting started with Terraform and Azure: Overview and Setup<\/a><br><a rel=\"noreferrer noopener\" aria-label=\"Terraform Workflow with Azure: Write, Plan and Apply (opens in a new tab)\" href=\"https:\/\/www.ciraltos.com\/terraform-workflow-with-azure-write-plan-and-apply\/\" target=\"_blank\">Terraform Workflow with Azure: Write, Plan and Apply<\/a><br><a href=\"https:\/\/www.ciraltos.com\/input-variables-with-terraform-and-azure\/\">Input Variables with Terraform and Azure<\/a><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"ast-oembed-container\" style=\"height: 100%;\"><iframe loading=\"lazy\" title=\"Modules and Outputs with Terraform and Azure\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/0YLPfSLbp9Y?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<h1>What is a Module<\/h1>\n\n\n\n<p>A module is a piece of reusable code\nthat contains a collection of resources to create infrastructure.&nbsp; Every programing language has some version of\na module.&nbsp; In PowerShell they\u2019re called\nfunctions.&nbsp; When the code is called, we\npass in the inputs, and if all goes as planned, we get the results as outputs.<\/p>\n\n\n\n<p>Reusability is vital for a module.&nbsp; If you create a block of code that deploys\nsomething useful, it\u2019s great to reuse or share that code.<\/p>\n\n\n\n<h1>What a Module is Not<\/h1>\n\n\n\n<p>Let\u2019s talk about what a module is not.&nbsp; A module is not a single instance of a resource.&nbsp; It may be tempting to turn everything into a module.&nbsp; Create a module for a VNet, Storage Account or App Service for example.&nbsp; Each of those are single resource and not the makings for a module.<\/p>\n\n\n\n<p>A module is a collection of resources.&nbsp; To paraphrase the Terraform documentation;&nbsp; a module is not a thin wrapper around a single resource.&nbsp; If that\u2019s what you are deploying, use a resource block\u2014no sense in complicating things with a module.<\/p>\n\n\n\n<p>The name is a good indication if\nsomething should be a module.&nbsp; If the\nmodule name is simply \u201cAzure SQL,\u201d that may not be a good use case for a\nmodule.&nbsp; But if the module name is \u201cAzure\nApp Service SQL with Backend,\u201d that may be a better candidate for a module\nbecause it\u2019s a composite of resources.<\/p>\n\n\n\n<h1>What Makes Up a Module<\/h1>\n\n\n\n<p>A Terraform module is contained in a\ndirectory. For example, the root module we created in the previous videos was a\nmodule.&nbsp;&nbsp; All projects start with the\nroot module and the root module can call child modules.&nbsp; The child module is a container for other resources.&nbsp; <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"274\" height=\"404\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure.png\" alt=\"\" class=\"wp-image-2353\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure.png 274w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure-203x300.png 203w\" sizes=\"(max-width: 274px) 100vw, 274px\" \/><figcaption class=\"wp-element-caption\"> Module Folder Structure <\/figcaption><\/figure>\n\n\n\n<p>Child modules are optional, and a child\nmodule can have child modules.&nbsp; However,\nit is best to keep the module structure as flat as possible to keep things\nreadable.<\/p>\n\n\n\n<p>A module has input variables. These are\nvariables sent from the calling or root module.&nbsp;\nThe inputs are used to create resources.&nbsp;\nThe resources are what is deployed when the module is called.&nbsp; <\/p>\n\n\n\n<p>If all goes well, the module can return\none or more outputs.&nbsp; These are results\nfrom creating resources.&nbsp; The outputs can\nbe informational or used as input to subsequent modules.<\/p>\n\n\n\n<p>Outputs need to be specified.&nbsp; Child modules run in their own\nenvironment.&nbsp; The output from the module\nis not passed back to the parent module by default.&nbsp; If we need data from the child module to\nfinish a subsequent step, that&#8217;s a problem.&nbsp;\nAn output block specifies the information passed back to the parent\nmodule.<\/p>\n\n\n\n<h1>Module Components<\/h1>\n\n\n\n<p>Different environments may have\nslightly different variations on how modules are constructed.&nbsp; The following is a review of the standard\nmodule structure from the Terraform documentation.<\/p>\n\n\n\n<h2>Root Module<\/h2>\n\n\n\n<p>The root module is the main entry point for the module.&nbsp; A root module is the only requirement for a module.&nbsp; There must be e a directory with some Terraform code to create a functional module. <\/p>\n\n\n\n<h2>README <\/h2>\n\n\n\n<p>The module should have a readme file, either called README or README.md.&nbsp; The README.md file is a markdown file.<\/p>\n\n\n\n<p>A module can have child modules if that\nhelps with organization code.&nbsp; A module\nwith a readme file is intended to be reused.&nbsp;\nA module without a readme file is a dependency on the parent module.&nbsp; <\/p>\n\n\n\n<h2>License<\/h2>\n\n\n\n<p>A license should be included,\nespecially if publishing publicly.<\/p>\n\n\n\n<h2>Terraform Files<\/h2>\n\n\n\n<p>There will be a set of .tf files in the module.&nbsp; Two of them are main.tf, and variables.tf.&nbsp; We went over these in a previous post and video located <a href=\"https:\/\/www.ciraltos.com\/input-variables-with-terraform-and-azure\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"here (opens in a new tab)\">here<\/a>.&nbsp; <\/p>\n\n\n\n<p>There is also an <em>outputs.tf<\/em> file that defines the outputs.&nbsp; Descriptions should be included with variables and outputs.&nbsp; This will help the next person that has to reuse this code, and that next person may be you!<\/p>\n\n\n\n<h2>Examples<\/h2>\n\n\n\n<p>Finally, supply examples in a separate examples directory.&nbsp; <\/p>\n\n\n\n<p>Once done, the directory and file structure of a simple module will look like this:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Simple-Module-Folder-Structure.png\" alt=\"\" class=\"wp-image-2354\"\/><figcaption class=\"wp-element-caption\"> Simple Module Folder Structure <\/figcaption><\/figure>\n\n\n\n<p>Or, the module structure could be as\ncomplex as this, with each child module and example having their own set of\nfiles.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"274\" height=\"404\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure-1.png\" alt=\"\" class=\"wp-image-2355\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure-1.png 274w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Folder-Structure-1-203x300.png 203w\" sizes=\"(max-width: 274px) 100vw, 274px\" \/><\/figure>\n\n\n\n<h1>Lab<\/h1>\n\n\n\n<p>The lab below creates a couple of simple modules that go against some of the rules outlined above. &nbsp;Rules are meant to be broken, right?&nbsp; The example uses two, single resource modules. This demo aims to show how to pass inputs and outputs between modules.&nbsp; Demonstrating this is easier with a less complex example.<\/p>\n\n\n\n<p>The example creates a root module and\ntwo child modules.&nbsp; The first child\nmodule will create a resource group and output the resource group name.&nbsp; The resource group name is passed to the\nsecond module to create a storage account.&nbsp;\nThe second module will pass back a randomly generated storage account\nname.<\/p>\n\n\n\n<p>There are a couple of other items covered\nalong the way. First, an expression is used to concatenate values to create a resource\ngroup name.&nbsp; Also, a random resource is\nused to create a random string.&nbsp; After that,\nthe random string is used to create a unique storage account name. &nbsp;<\/p>\n\n\n\n<h1>Creating Modules Lab<\/h1>\n\n\n\n<p>The following lab is about parent, child modules and how to\npass information between them.&nbsp; In real\nlife, it may not make sense to create modules for a single resource.&nbsp; I tried a larger deployment but thought simpler\ncode makes for a better example.<\/p>\n\n\n\n<p>Start by going to VSCode or the editor of your choice and creating the directory structure.&nbsp; The root folder is ModuleExample, and the child folders are ResourceGroup and StorageAccount.&nbsp; Create a similar folder if you plan to follow along.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"608\" height=\"217\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Module-Structure.png\" alt=\"\" class=\"wp-image-2356\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Structure.png 608w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Structure-300x107.png 300w\" sizes=\"(max-width: 608px) 100vw, 608px\" \/><figcaption class=\"wp-element-caption\"> Module Structure <\/figcaption><\/figure>\n\n\n\n<p>By the way, the code used for this example is available on GitHub.  <br><a href=\"https:\/\/github.com\/tsrob50\/TerraformExamples\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"https:\/\/github.com\/tsrob50\/TerraformExamples (opens in a new tab)\">https:\/\/github.com\/tsrob50\/TerraformExamples<\/a><\/p>\n\n\n\n<p>Open the ModuleExample folder from VSCode.&nbsp; Create a <em>main.tf<\/em> file in the root\nmodule, right under the ModuleExample directory.<\/p>\n\n\n\n<p>Next, add our provider.&nbsp;\nThe provider is found by going to the terraform registry at\nregistry.terraform.io.&nbsp; Select Azure,\nthen <em>Use Provider<\/em> at the top right corner.&nbsp; <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Use-Provider.png\" alt=\"\" class=\"wp-image-2357\"\/><figcaption class=\"wp-element-caption\"> Use Provider <\/figcaption><\/figure>\n\n\n\n<p>Update configuration options with features and the open,\nclosing squiggly brackets.&nbsp; Once\nfinished, the main.tf will look like this.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"369\" height=\"346\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/New-main-tf.png\" alt=\"\" class=\"wp-image-2358\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/New-main-tf.png 369w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/New-main-tf-300x281.png 300w\" sizes=\"(max-width: 369px) 100vw, 369px\" \/><figcaption class=\"wp-element-caption\"> New main.tf <\/figcaption><\/figure>\n\n\n\n<p>Save and close once finished, we\u2019ll come back to that\nshortly.<\/p>\n\n\n\n<h1>Resource Group Module<\/h1>\n\n\n\n<p>In this section, we create the Resource Group module.&nbsp; Start by going into our ResourceGroup folder and create a <em>main.tf<\/em> and a <em>variable.tf<\/em> file.<\/p>\n\n\n\n<p>Open the <em>main.tf<\/em> and add a Resource Group resource block.&nbsp; Examples of resource blocks can be found in in the Terraform Registry.<\/p>\n\n\n\n<p>A resource group requires two settings, a name and a\nlocation.&nbsp; It is possible to pass in the\nname as a variable, but let\u2019s do this a little differently.&nbsp; Coming up, we create a storage account in\naddition to the resource group.&nbsp; This\nexample uses the same \u201cbase name\u201d for both to create two resources based on the\nsame variable.&nbsp; <\/p>\n\n\n\n<p>Open the <em>variables.tf<\/em> file under the  ResourceGroup module.&nbsp; <\/p>\n\n\n\n<p>Create two variables, one for the base name and one for the location.&nbsp; Don\u2019t forget to add a description to your\noutputs.&nbsp; Once finished, the <em>variables.tf<\/em>\nfile will look like the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"938\" height=\"348\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-variables-tf.png\" alt=\"\" class=\"wp-image-2360\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-variables-tf.png 938w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-variables-tf-300x111.png 300w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-variables-tf-768x285.png 768w\" sizes=\"(max-width: 938px) 100vw, 938px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Module variables.tf <\/figcaption><\/figure>\n\n\n\n<p>Save the file once updated and go back to <em>main.tf<\/em> in\nthe ResourceGroup module.<\/p>\n\n\n\n<p>Update the location from the manually entered setting to the\nvariable <em>var.location.<\/em>&nbsp; <\/p>\n\n\n\n<p>Next, we have the base name, <em>var.base_name<\/em>.&nbsp; We will append an \u201cRG\u201d at the end of the variable to create a resource group name. The following steps will concatenate a variable with a sting for the resource group name.<\/p>\n\n\n\n<p>Remove the existing string used for the name value and add\ndouble-quotes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \u201c\u201d<\/pre>\n\n\n\n<p>Next, we add the value of the variable by starting with a\ndollar sign and a pair of squiggly brackets<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \u201c${}\u201d<\/pre>\n\n\n\n<p>Add the variable for the base name between the squiggly brackets.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \u201c${var.base_name}\u201d<\/pre>\n\n\n\n<p>Immediately after the closing squiggly brackets, add the\ntext \u201cRG\u201d.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \u201c${var.base_name}RG\u201d<\/pre>\n\n\n\n<p>once finished, the <em>main.tf<\/em> file for the  ResourceGroup module will look like the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"720\" height=\"174\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Resource-block.png\" alt=\"\" class=\"wp-image-2361\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Resource-block.png 720w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Resource-block-300x73.png 300w\" sizes=\"(max-width: 720px) 100vw, 720px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Resource Block <\/figcaption><\/figure>\n\n\n\n<p>The name is now the value of <em>var.base_name\u00ad<\/em> followed\nby the string \u201cRG\u201d.<\/p>\n\n\n\n<p>Save and close the files and we\u2019ll move on to creating a\nmodule block.<\/p>\n\n\n\n<h1>Create a Module\nBlock<\/h1>\n\n\n\n<p>Next, open the <em>main.tf<\/em> under ModuleExample.&nbsp; There are multiple <em>main.tf<\/em> files in different directories for these examples, be sure you are working on the correct one.<\/p>\n\n\n\n<p>Next, create a module block.&nbsp; A module block starts with the word <em>module<\/em>.&nbsp; The finished block will look like the image\nbelow.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"582\" height=\"216\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-Block.png\" alt=\"\" class=\"wp-image-2362\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-Block.png 582w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Module-Block-300x111.png 300w\" sizes=\"(max-width: 582px) 100vw, 582px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Module Block  <\/figcaption><\/figure>\n\n\n\n<p>After <em>module<\/em> is the local name, <em>ResourceGroup<\/em>\nfor this example.<\/p>\n\n\n\n<p>The <em>source<\/em> argument provides the location of the module.&nbsp; The above example uses a relative path to the <em>ResourceGroup<\/em> directory.&nbsp; Notice it\u2019s in quotes and uses the Linux style directory structure.<\/p>\n\n\n\n<p>The b<em>ase_name <\/em>and <em>location<\/em>\nargument provides the input variables we created for the Resource Group module.<\/p>\n\n\n\n<p>Save the file and open the terminal to\ntest.&nbsp; Be sure the terminal is in the <em>ModuleExample<\/em>\ndirectory and run a <em>terraform init<\/em>.<\/p>\n\n\n\n<p>Next run <em>terraform plan.<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"286\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1024x286.png\" alt=\"\" class=\"wp-image-2363\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1024x286.png 1024w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-300x84.png 300w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-768x214.png 768w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name.png 1083w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Name <\/figcaption><\/figure>\n\n\n\n<p>The output shows a new resource group\nwill be created with the name<em> TerraformExample01RG<\/em>, indicating the\nexpression worked.&nbsp; We don\u2019t need to\napply at this point.&nbsp; Next, create the Storage\nAccount Module.<\/p>\n\n\n\n<h1>Storage Account\nModule<\/h1>\n\n\n\n<p>Close the main.tf from the <em>ModuleExample<\/em>\ndirectory and go to the storage account module.<\/p>\n\n\n\n<p>Next, create the <em>main.tf<\/em> and <em>variable.tf<\/em>\nfile for the storage account module.&nbsp; In\nthe <em>main.tf<\/em> file, add the minimum required for the Storage Account resource.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"729\" height=\"278\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource.png\" alt=\"\" class=\"wp-image-2364\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource.png 729w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource-300x114.png 300w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><figcaption class=\"wp-element-caption\"> Storage Account Resource <\/figcaption><\/figure>\n\n\n\n<p>We need to supply three items: the <em>base_name<\/em>\nused as part of the Storage Account name, the location, and the resource group\nname.&nbsp; <\/p>\n\n\n\n<p>Open the <em>variables .tf<\/em> file and add the <em>base_<\/em>name, <em>resource_group_name,<\/em> and <em>location <\/em>variables, as shown below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"584\" height=\"409\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-Base-Name-and-Location-Variables.png\" alt=\"\" class=\"wp-image-2365\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Base-Name-and-Location-Variables.png 584w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Base-Name-and-Location-Variables-300x210.png 300w\" sizes=\"(max-width: 584px) 100vw, 584px\" \/><figcaption class=\"wp-element-caption\"> Storage Account Base Name and Location Variables <\/figcaption><\/figure>\n\n\n\n<p>Save once finished and go back to the StroageAccount\nmodule <em>main.tf<\/em> file.<\/p>\n\n\n\n<h1>Random Provider<\/h1>\n\n\n\n<p>A storage account name must be globally\nunique and limited to numbers and lower-case letters.&nbsp; Random characters were added to the end of\nthe storage account name in the previous videos and posts to make it unique. This\nexample requires random characters without manually adding the characters at\neach deployment.<\/p>\n\n\n\n<p>A resource provider called <em>Random<\/em> is used to solve this problem.&nbsp; The Random Provider is used to generate a random string that we\u2019ll append to the end of <em>base_name<\/em> for a unique storage account name.<\/p>\n\n\n\n<p>To use the Random Provider, go back to registry.terraform.io\nad search for <em>Random<\/em> at the top of the page.<\/p>\n\n\n\n<p>Go to Registry.terraform.io and search\nfor \u201crandom\u201d.&nbsp; Random is a HashiCorp\nprovider.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"582\" height=\"271\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Random-Provider.png\" alt=\"\" class=\"wp-image-2366\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Random-Provider.png 582w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Random-Provider-300x140.png 300w\" sizes=\"(max-width: 582px) 100vw, 582px\" \/><figcaption class=\"wp-element-caption\"> Random Provider <\/figcaption><\/figure>\n\n\n\n<p>Select \u201cUse Provider\u201d and copy and paste\nthe provider into the <em>main.tf<\/em> for the storage account module.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"387\" height=\"553\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/User-Provider.png\" alt=\"\" class=\"wp-image-2367\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/User-Provider.png 387w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/User-Provider-210x300.png 210w\" sizes=\"(max-width: 387px) 100vw, 387px\" \/><figcaption class=\"wp-element-caption\"> User Provider <\/figcaption><\/figure>\n\n\n\n<p>Remove the provider block, it\u2019s empty\nand not needed.&nbsp; Once finished, it will\nlook like the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"461\" height=\"271\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Random-Provider.png\" alt=\"\" class=\"wp-image-2368\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Random-Provider.png 461w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Random-Provider-300x176.png 300w\" sizes=\"(max-width: 461px) 100vw, 461px\" \/><figcaption class=\"wp-element-caption\">  Storage Random Provider <\/figcaption><\/figure>\n\n\n\n<p>Next, add the resource <em>random_string<\/em>\nwith the local name <em>random.<\/em><\/p>\n\n\n\n<p>There are three arguments to add:<\/p>\n\n\n\n<ul>\n<li>Length specifics how long the string will be.&nbsp; Set this to six.<\/li>\n\n\n\n<li>Special indicates if random characters are included.&nbsp; Set this to false to exclude special characters from the string.&nbsp;<\/li>\n\n\n\n<li>Upper indicates if upper case characters are included. Set to <em>false<\/em> to exclude upper case characters.<\/li>\n<\/ul>\n\n\n\n<p>Once finished, the random block will\nlook like the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"413\" height=\"156\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Random-String-Block.png\" alt=\"\" class=\"wp-image-2369\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Random-String-Block.png 413w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Random-String-Block-300x113.png 300w\" sizes=\"(max-width: 413px) 100vw, 413px\" \/><figcaption class=\"wp-element-caption\"> Random String Block <\/figcaption><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>Find a complete list of settings for the random string provider here: <a rel=\"noreferrer noopener\" aria-label=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/random\/latest\/docs\/resources\/string (opens in a new tab)\" href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/random\/latest\/docs\/resources\/string\" target=\"_blank\">https:\/\/registry.terraform.io\/providers\/hashicorp\/random\/latest\/docs\/resources\/string<\/a><\/p>\n<\/blockquote>\n\n\n\n<p>That creates the random string used for\nthe storage account name.&nbsp; Next, the\nrandom string is used to create the storage account name.<\/p>\n\n\n\n<p>Go to the azurerm_storage_account resource\nblock to update the name.<\/p>\n\n\n\n<p>Everything is in quotes, just like the  ResourceGroup name.&nbsp; Add the dollar sign, brackets and var.base_name <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \u201c${var.base_name}\u201d<\/pre>\n\n\n\n<p>Immediate after the closing squiggly bracket,\nadd the code to concatenate the random string<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \"${var.base_name}${random_string.random.result}\"<\/pre>\n\n\n\n<p>We are almost there, just one more change.&nbsp; We did not include any input validation for\nthe <em>base_name<\/em> variable, and there are capital letters in our current\nexample.&nbsp; Capital letters are invalid for\na storage account name.&nbsp; We can use an expression\nto convert <em>var.base_name<\/em> to lower case.&nbsp;\nAdd the word \u201dlower\u201d immediately before <em>var.base_name<\/em> and put the\nvariable in parentheses.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name = \"${lower(var.base_name)}${random_string.random.result}\"<\/pre>\n\n\n\n<p>The name of the storage account is now\nthe value of <em>var.base_name<\/em> in lowercase followed by the random string.<\/p>\n\n\n\n<p>Next, update the <em>resource_group_name <\/em>and <em>location<\/em> arguments with the variable settings.&nbsp; The full block of code for the storage account will look like the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"736\" height=\"178\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource-Block-1.png\" alt=\"\" class=\"wp-image-2385\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource-Block-1.png 736w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Resource-Block-1-300x73.png 300w\" sizes=\"(max-width: 736px) 100vw, 736px\" \/><figcaption class=\"wp-element-caption\">  Storage Account Resource Block<\/figcaption><\/figure>\n\n\n\n<p>Save and close all files and go back to\n<em>main.tf<\/em> in the ModuleExample root module.<\/p>\n\n\n\n<p>Open the <em>main.tf<\/em> file and create a module block called <em>StorageAccount.<\/em>&nbsp; Provide the source and base_name as shown below. The settings are similar to the  ResourceGroup module.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"482\" height=\"164\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-Module.png\" alt=\"\" class=\"wp-image-2387\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Module.png 482w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Module-300x102.png 300w\" sizes=\"(max-width: 482px) 100vw, 482px\" \/><figcaption class=\"wp-element-caption\"> Storage Account Module <\/figcaption><\/figure>\n\n\n\n<p>There is a problem with the resource group name.&nbsp; The name was dynamically created based off the <em>base_name<\/em> and the letters \u201cRG\u201d.&nbsp; We could simply add that to the <em>StorageAccount <\/em>block, but that would require manually updating any time it changes.<\/p>\n\n\n\n<p>The better option is to use an output statement in the ResourceGroup module to pass the Resource Group name back to the parent module.<\/p>\n\n\n\n<h1>Output<\/h1>\n\n\n\n<p>Next, we create an output block in the <em>ResocueGroup<\/em> module\nthat returns the resource group name. <\/p>\n\n\n\n<p>Create a file called <em>outputs.tf<\/em> and add a new output block with the local name \u201crg_name_out\u201d and the value \u201cazurerm_resource_group.example.name\u201d as shown below.&nbsp; <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"566\" height=\"192\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Output-Block.png\" alt=\"\" class=\"wp-image-2372\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Output-Block.png 566w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Output-Block-300x102.png 300w\" sizes=\"(max-width: 566px) 100vw, 566px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Output Block <\/figcaption><\/figure>\n\n\n\n<p>Review that the \u201cazurerm_resource_group.example.name\u201d in the  ResourceGroup <em>main.tf <\/em>file.&nbsp; This is the value of the Resource Group name.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"286\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1-1024x286.png\" alt=\"\" class=\"wp-image-2373\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1-1024x286.png 1024w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1-300x84.png 300w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1-768x214.png 768w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Resource-Group-Name-1.png 1083w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"> Resource Group Name <\/figcaption><\/figure>\n\n\n\n<p>Save and close the files in the  ResourceGroup module and go back to <em>main.tf<\/em> in the root module.<\/p>\n\n\n\n<p>As configured, when we apply the deployment, the resource\ngroup module will run first.&nbsp; Once\nfinished, it will return the resource group name in the output.&nbsp; We\u2019ll use that to supply the resource group\nname to the storage account module variable.<\/p>\n\n\n\n<p>Update the <em>resource_group\u00ad_name<\/em> argument with the string \u201cmodule.ResourceGroup.rg_name_out\u201d.&nbsp; With this configuration, the output of the Resource Group name from the ResourceGroup module is input for the StorageAccount module.<\/p>\n\n\n\n<p>Add the location to the StorageAccount module and save the file.&nbsp; Once finished, the  ResourceGroup and StorageAccount modules will look similar to the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"567\" height=\"296\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Finished-Module-Blocks.png\" alt=\"\" class=\"wp-image-2374\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Finished-Module-Blocks.png 567w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Finished-Module-Blocks-300x157.png 300w\" sizes=\"(max-width: 567px) 100vw, 567px\" \/><figcaption class=\"wp-element-caption\"> Finished Module Blocks <\/figcaption><\/figure>\n\n\n\n<h1>Apply the Configuration<\/h1>\n\n\n\n<p>Run a <em>terraform\ninit<\/em> and <em>terraform plan<\/em> next.<\/p>\n\n\n\n<p>Scroll up to the ResourceGroup\naction in the output from <em>terraform plan<\/em>.&nbsp; The name is correct.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"731\" height=\"193\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Terraform-Plan-Resource-Group-Name.png\" alt=\"\" class=\"wp-image-2376\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Terraform-Plan-Resource-Group-Name.png 731w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Terraform-Plan-Resource-Group-Name-300x79.png 300w\" sizes=\"(max-width: 731px) 100vw, 731px\" \/><figcaption class=\"wp-element-caption\"> Terraform Plan Resource Group Name <\/figcaption><\/figure>\n\n\n\n<p>Go to the storage\naccount section and notice the name indicates \u201cKnown after apply\u201d.&nbsp; The name is dependent on random characters\ngenerated when the configuration is applied.&nbsp;\n<\/p>\n\n\n\n<p>Run <em>terraform\napply<\/em> to apply the changes.<\/p>\n\n\n\n<p>Once finished, we can\nsee the name of the storage account in the CLI.&nbsp;\nNotice the name has random characters at the end.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"885\" height=\"251\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-CLI-Output.png\" alt=\"\" class=\"wp-image-2377\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-CLI-Output.png 885w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-CLI-Output-300x85.png 300w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-CLI-Output-768x218.png 768w\" sizes=\"(max-width: 885px) 100vw, 885px\" \/><figcaption class=\"wp-element-caption\"> Storage Account CLI Output <\/figcaption><\/figure>\n\n\n\n<h1>Storage Account Output<\/h1>\n\n\n\n<p>The code is now\nworking, but you may want to use automation to deploy modules.&nbsp; For that, it would be helpful to have the new\nstorage account name as output from the StorageAccount module.<\/p>\n\n\n\n<p>Close all open files\nand go back to the StorageAccount module.&nbsp;\nCreate a new file called <em>output.tf<\/em>.&nbsp; Add an output block for the storage account\nname as shown below.&nbsp; Save the file once\nfinished.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"645\" height=\"160\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Storage-Account-Output.png\" alt=\"\" class=\"wp-image-2378\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Output.png 645w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Storage-Account-Output-300x74.png 300w\" sizes=\"(max-width: 645px) 100vw, 645px\" \/><figcaption class=\"wp-element-caption\"> Storage Account Output <\/figcaption><\/figure>\n\n\n\n<p>One more thing, outputs are passed back to whatever called\nthe module.&nbsp; We called the root module\nwhen we ran <em>terraform apply<\/em> in the previous example, the root module\ncalled the resource group and storage account module.&nbsp; The outputs are exposed to the root module\nthe way it sits now, but not to us.&nbsp; <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"480\" height=\"291\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Outputs-Example.png\" alt=\"\" class=\"wp-image-2379\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Outputs-Example.png 480w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Outputs-Example-300x182.png 300w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><figcaption class=\"wp-element-caption\"> Outputs Example <\/figcaption><\/figure>\n\n\n\n<p>Next, run <em>terraform output<\/em>\nto see what outputs we have.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"735\" height=\"156\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Terraform-No-Output-Found.png\" alt=\"\" class=\"wp-image-2380\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Terraform-No-Output-Found.png 735w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Terraform-No-Output-Found-300x64.png 300w\" sizes=\"(max-width: 735px) 100vw, 735px\" \/><figcaption class=\"wp-element-caption\"> Terraform No Output Found <\/figcaption><\/figure>\n\n\n\n<p>We can fix this by adding outputs\nto the root module.&nbsp; Save and close all open\nfiles and go to the ModuelExample folder.<\/p>\n\n\n\n<p>Add a new <em>outputs.tf<\/em> file.&nbsp; This file echoes the outputs from the two child\nmodules.&nbsp; Update the file with the values\nfrom the module outputs as shown below.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"524\" height=\"234\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/ModuleExample-Output.png\" alt=\"\" class=\"wp-image-2381\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/ModuleExample-Output.png 524w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/ModuleExample-Output-300x134.png 300w\" sizes=\"(max-width: 524px) 100vw, 524px\" \/><figcaption class=\"wp-element-caption\"> Module Example Output <\/figcaption><\/figure>\n\n\n\n<p>Notice the values in\nthe examples above reference the module, then the module name, and then the\noutput name.<\/p>\n\n\n\n<p>Save the file once\nfinished and let\u2019s the updates.<\/p>\n\n\n\n<h1>Destroy and Apply<\/h1>\n\n\n\n<p>Run a <em>terraform destroy<\/em> to remove the existing\ndeployment.&nbsp; Unless, of course, you put\nthis into production.<\/p>\n\n\n\n<p>Once the destroy is finished, run <em>terraform init <\/em>and<em>\nterraform plan<\/em>.<\/p>\n\n\n\n<p>Notice at the bottom of the output from <em>terraform plan<\/em>\nshows two new outputs, <em>RgName <\/em>and <em>StgActName.<\/em>&nbsp; That is the new output form the ModuleExample\nmodule.<\/p>\n\n\n\n<p>Run <em>terraform apply<\/em> next.<\/p>\n\n\n\n<p>Once finished, we can see the new output at the bottom of\nthe screen.&nbsp; Also, run <em>terraform\noutput<\/em> to see the new output values from the ModuleExample module.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"731\" height=\"205\" src=\"https:\/\/www.ciraltos.com\/wp-content\/uploads\/2021\/12\/Module-Example-Output.png\" alt=\"\" class=\"wp-image-2388\" srcset=\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Example-Output.png 731w, https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/12\/Module-Example-Output-300x84.png 300w\" sizes=\"(max-width: 731px) 100vw, 731px\" \/><figcaption class=\"wp-element-caption\"> Module Example Output  <\/figcaption><\/figure>\n\n\n\n<p>The modules are successfully passing data with outputs!<\/p>\n\n\n\n<h1>Summary<\/h1>\n\n\n\n<p>Congratulations on making it to the end of this post! &nbsp;We created examples of calling modules and\npassing data back from modules in this post and video.&nbsp; We also added the random resource and lower\nfunction with the example. Of course, a module with a single resource may not\nbe best practice; but it did make for a good example.&nbsp; <\/p>\n\n\n\n<p>Upcoming content will build on this example with more\ncomplex deployments.&nbsp; Don\u2019t forget to run\n<em>terraform destroy<\/em> to clean up the examples.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modules and outputs are two important concepts for creating quality, reusable Terraform code.&nbsp; This post and accompanying video put those concepts into practice.&nbsp; This is a lengthy subject, so grab a drink of your choice and settle in for the ride.&nbsp; Also, if you are getting started with Terraform, be sure to check out my &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"\" href=\"https:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\"> <span class=\"screen-reader-text\">Modules and Outputs with Terraform and Azure<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":2303,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"default","ast-global-header-display":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":""},"categories":[1159],"tags":[1163,9,992,1164,1169,1174,1181,1182,1188,1172,1160,1165,1170,1186,1175,1184,1187,1171,1162,1185,1179,1178,1177,1183,1168,1176,1007,962,1173],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Modules and Outputs with Terraform and Azure - ciraltos<\/title>\n<meta name=\"description\" content=\"This post reviews using inputs and outputs with Terraform modules.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Modules and Outputs with Terraform and Azure - ciraltos\" \/>\n<meta property=\"og:description\" content=\"This post reviews using inputs and outputs with Terraform modules.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\" \/>\n<meta property=\"og:site_name\" content=\"ciraltos\" \/>\n<meta property=\"article:published_time\" content=\"2021-12-19T20:14:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-23T10:31:42+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/11\/Terraform_VerticalLogo_Color_RGB-2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"176\" \/>\n\t<meta property=\"og:image:height\" content=\"186\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Travis Roberts\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ciraltos\" \/>\n<meta name=\"twitter:site\" content=\"@ciraltos\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Travis Roberts\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#article\",\"isPartOf\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\"},\"author\":{\"name\":\"Travis Roberts\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a\"},\"headline\":\"Modules and Outputs with Terraform and Azure\",\"datePublished\":\"2021-12-19T20:14:31+00:00\",\"dateModified\":\"2023-03-23T10:31:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\"},\"wordCount\":3184,\"commentCount\":2,\"publisher\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a\"},\"keywords\":[\".tf\",\"Azure\",\"Azure CLI\",\"HashiCorp\",\"IaC Terraform\",\"main.tf\",\"Modules\",\"outputs\",\"outputs.tf\",\"registry\",\"Terraform\",\"Terraform Apply\",\"Terraform Destroy\",\"Terraform Examples\",\"Terraform for Azure\",\"terraform modules\",\"terraform outputs\",\"Terraform Plan\",\"terraform registry\",\"Terraform Resource\",\"terraform training\",\"terraform tutorial\",\"terraform var\",\"terraform variables\",\"Terraform Write\",\"Terraform.tfvars\",\"Variables\",\"VSCode\",\"workdlow\"],\"articleSection\":[\"Terraform\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\",\"url\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\",\"name\":\"Modules and Outputs with Terraform and Azure - ciraltos\",\"isPartOf\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#website\"},\"datePublished\":\"2021-12-19T20:14:31+00:00\",\"dateModified\":\"2023-03-23T10:31:42+00:00\",\"description\":\"This post reviews using inputs and outputs with Terraform modules.\",\"breadcrumb\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\/\/www.ciraltos.com\/staging2\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Modules and Outputs with Terraform and Azure\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#website\",\"url\":\"http:\/\/www.ciraltos.com\/staging2\/\",\"name\":\"ciraltos\",\"description\":\"cloud, technology and trends\",\"publisher\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/www.ciraltos.com\/staging2\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a\",\"name\":\"Travis Roberts\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2023\/03\/Logo-1.png\",\"contentUrl\":\"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2023\/03\/Logo-1.png\",\"width\":5657,\"height\":3563,\"caption\":\"Travis Roberts\"},\"logo\":{\"@id\":\"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/image\/\"},\"sameAs\":[\"http:\/\/www.ciraltos.com\",\"https:\/\/twitter.com\/ciraltos\"],\"url\":\"https:\/\/www.ciraltos.com\/staging2\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Modules and Outputs with Terraform and Azure - ciraltos","description":"This post reviews using inputs and outputs with Terraform modules.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/","og_locale":"en_US","og_type":"article","og_title":"Modules and Outputs with Terraform and Azure - ciraltos","og_description":"This post reviews using inputs and outputs with Terraform modules.","og_url":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/","og_site_name":"ciraltos","article_published_time":"2021-12-19T20:14:31+00:00","article_modified_time":"2023-03-23T10:31:42+00:00","og_image":[{"width":176,"height":186,"url":"http:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2021\/11\/Terraform_VerticalLogo_Color_RGB-2.png","type":"image\/png"}],"author":"Travis Roberts","twitter_card":"summary_large_image","twitter_creator":"@ciraltos","twitter_site":"@ciraltos","twitter_misc":{"Written by":"Travis Roberts","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#article","isPartOf":{"@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/"},"author":{"name":"Travis Roberts","@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a"},"headline":"Modules and Outputs with Terraform and Azure","datePublished":"2021-12-19T20:14:31+00:00","dateModified":"2023-03-23T10:31:42+00:00","mainEntityOfPage":{"@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/"},"wordCount":3184,"commentCount":2,"publisher":{"@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a"},"keywords":[".tf","Azure","Azure CLI","HashiCorp","IaC Terraform","main.tf","Modules","outputs","outputs.tf","registry","Terraform","Terraform Apply","Terraform Destroy","Terraform Examples","Terraform for Azure","terraform modules","terraform outputs","Terraform Plan","terraform registry","Terraform Resource","terraform training","terraform tutorial","terraform var","terraform variables","Terraform Write","Terraform.tfvars","Variables","VSCode","workdlow"],"articleSection":["Terraform"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#respond"]}]},{"@type":"WebPage","@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/","url":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/","name":"Modules and Outputs with Terraform and Azure - ciraltos","isPartOf":{"@id":"http:\/\/www.ciraltos.com\/staging2\/#website"},"datePublished":"2021-12-19T20:14:31+00:00","dateModified":"2023-03-23T10:31:42+00:00","description":"This post reviews using inputs and outputs with Terraform modules.","breadcrumb":{"@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/www.ciraltos.com\/staging2\/modules-and-outputs-with-terraform-and-azure\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/www.ciraltos.com\/staging2\/"},{"@type":"ListItem","position":2,"name":"Modules and Outputs with Terraform and Azure"}]},{"@type":"WebSite","@id":"http:\/\/www.ciraltos.com\/staging2\/#website","url":"http:\/\/www.ciraltos.com\/staging2\/","name":"ciraltos","description":"cloud, technology and trends","publisher":{"@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/www.ciraltos.com\/staging2\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/25391996d6cddfecd4d257162b7e373a","name":"Travis Roberts","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/image\/","url":"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2023\/03\/Logo-1.png","contentUrl":"https:\/\/www.ciraltos.com\/staging2\/wp-content\/uploads\/2023\/03\/Logo-1.png","width":5657,"height":3563,"caption":"Travis Roberts"},"logo":{"@id":"http:\/\/www.ciraltos.com\/staging2\/#\/schema\/person\/image\/"},"sameAs":["http:\/\/www.ciraltos.com","https:\/\/twitter.com\/ciraltos"],"url":"https:\/\/www.ciraltos.com\/staging2\/author\/admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/posts\/2352"}],"collection":[{"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/comments?post=2352"}],"version-history":[{"count":9,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/posts\/2352\/revisions"}],"predecessor-version":[{"id":3795,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/posts\/2352\/revisions\/3795"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/media\/2303"}],"wp:attachment":[{"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/media?parent=2352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/categories?post=2352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ciraltos.com\/staging2\/wp-json\/wp\/v2\/tags?post=2352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}