Modules and Outputs with Terraform and Azure

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we get started with modules and outputs in terraform and azure [Music] hello everyone i'm travis and this is seraldos i'm not going to lie to you this is going to be a long one but modules and outputs are one of those core concepts that's indispensable for creating quality reusable terraform code but don't worry i'm going to step through it piece by piece i have time stamps and chapters below if you want to jump ahead or go back before we get started please like subscribe share with a friend and let me know what you think in the comments below also check out my course on azure virtual desktop and hybrid identities with azure id at udb.com the link is below and check out the join button if you're so inclined let's get started with what a module is a module is a piece of reusable code modules contain a collection of multiple resources that create some form of infrastructure every programming language has some version of a module in powershell they're called functions when the code is called we pass in inputs and if all goes as planned we get the results as outputs reusability is key for modules if you create a block of code that deploys something useful it's great to be able to reuse or share that code let's talk about what a module isn't a module isn't a single instance of a resource it may be tempting to turn everything into a module create a module for a v-net a storage account an app service for example each of those are single resources and not the makings for a module a module is a collection of resources i'm going to paraphrase terraform documentation because they sum it up nicely a module is not a thin wrapper around a single resource if that's what you're deploying just use the resource block no sense in complicating things with a module the name is a good indication if something should be a module if the module name is simply azure sql that may not be a good use case for a module but if the module name is azure app services with sql backend that may be a better candidate for a module because it's a composite of resources a module is contained in directories we've already created modules the root module we created in previous videos was a module all projects start with a root module like we created before we can call child modules from within the root module the child module is the container for other resources the root module can call child modules and those can have child modules as well but it's best to keep the module structure as flat as possible to keep things readable a module will have input variables these are variables sent from the calling or root module they have resources this is what is deployed when the module is called and outputs let's pause for a second and talk about outputs when we call a child module it runs in its own environment the output from the module is not passed back to the parent module by default that's a problem if we need that data from the child module to finish a subsequent step we can tell the child module to return data to the root module with outputs we can then use the data elsewhere in the code let's go a little further with the structure of a module i'm going with a standard module structure from the terraform documentation different environments may have slightly different variations on this but should be close we'll start with the root module this is the main entry point for the module this is the only requirement when creating a module basically we have to have a directory with some code in it to be a functional module it should have a readme file either called readme or readme.md the md file uses markdown a module can have child modules if that helps organize the code a module with a readme file is intended to be reused a module without a readme file is intended only to be a dependency to the parent module a license should be included especially if that module will be published publicly there'll be a set of files the main.tf and variables.tf we went over those in a previous video also an output.tf file that defines the outputs description should be included with variables and outputs this will seriously help the next person that has to reuse the code and that next person may be you you can also supply examples in a separate example directory the directory and file structure for a simple module will look like this but it can be as complex as this with each child module and example having their own set of files we're going to create a couple simple modules next that go against some of the rules i just outlined but rules are meant to be broken right these are simple one resource modules the purpose of this demo is to show how to pass inputs and outputs between modules it's easier to demonstrate this with a less complex environment we're going to create a root module and two child modules the first child module will create a resource group and output the resource group name we'll pass that to a second module to create a storage account the second module will pass back a randomly generated storage account name we have a couple other items we'll cover along the way we'll use an expression to concatenate some values create a random string and use a function to convert a string to lowercase letters let's hop into vs code to get started here we are in vs code i have a new root module or folder on the local disk called module example create the similar folder structure if you're following along by the way i'll make this code available just check the link below under that we have two new folders one called resource group and the other one storage account these are for well the resource group and storage account module this is just an example of calling modules and returning output in real life it may not make sense to create modules for a single resource like a resource group or storage account i tried a larger deployment but thought this makes for a better example at least for now first let's create a main tf at the root module right under the module example directory let's add our provider we can get that from the terraform registry at registry.terraform.io here we are let's go to azure use the provider and we'll copy this let's go back to vs code and we'll paste that in remember to update the provider to features we'll just leave the features empty once you've got that done save and close we'll come back to this shortly next let's create the resource group module we'll start by going into the resource group folder that's empty so we'll create a main.tf along with the variables.tf let's go to the main.tf and in maine tf under resource group let's add the resource group resource we'll come back to the terraform registry go to documentation and search for resource group and there it is we'll copy that and paste it into the main.tf in our resource group module a resource group requires a minimum of two settings a name and location we could simply pass in those values for both but let's do this a little different we're also going to create a storage account let's use the same base name for both so we can create two resources based off of the same base name variable let's go to variables and we're going to create two variables a base name and a location this one we'll call base name that's going to be a string and for the description let's add a description next we'll add the location now we have that base name and the location so let's save that and let's go back to the main.tf in our resource group module and i still have that open over here let's update the location with a variable next we have the base name for the resource group name i want to take the base name and add an rg at the end to create the resource group name that's going to require us to create a new string based on the variable and the letters rg to do this we'll create an expression we start by placing the expression in quotes and then we're going to add the base name variable so to do that we want to pass in that value into a string we need to start with a dollar sign and then surround that variable in squiggly brackets so that will use the value of var.base name and then at the end we just want to add an rg so we'll go 1 over and rg so now the name is whatever we pass in as the base name followed by rg let's save and close these files we're going to test this shortly but first open up main tf under module example we'll have multiple main.tf files in different directories make sure you're working in the correct one from here we'll call the module with a module block followed by the name and quotes so we'll go to the end add a space we'll enter module to start the module block and then we give it a name resource group go to the next line then type source this indicates the location of the module we'll give it a path to the module the resource group folder for this example notice the location is in quotes it starts with a dot that's the present directory then a slash this is a linux style directory listing and then the folder or the module name we have to pass in the base name and the location let's add the base name that matches the variable the modules expecting let's set the base name to terraform example01 and then add the location west u.s for this example let's save the file and we'll test to see if this works open up the terminal and we'll do a terraform init that looks good next let's run terraform plan and notice we're running this from the module example directory the output shows the new resource group will be created with the name terraform example01rg so our expression worked that's good let's create a storage account module next close the main.tf file and go to the storage account module create the main.tf and the variables.tf file for the storage account module we're going to create a storage account let's go into the terraform registry and find the storage account azure rm storage account we'll copy the resource block we'll go back to vs code into the main.tf that's under the storage account module and let's paste in the storage account resource and for this example let's get rid of tags there are three items we need to supply the base name used for the storage account name and the location the location can be the same as the resource group but it doesn't have to be and the third is the resource group name let's go to variables.tf and add those variables let's start with the variable for the storage account base name next we'll add the resource group name and last the location those are the three variables we need let's save this and go back to the resource group module main.tf here's the problem with storage account names they must be globally unique in the last couple videos i added some random characters at the end to make sure the name is unique i want to add random characters but i don't want to have to add the characters each deployment we're going to use a special kind of resource called random this will generate a random string that will apply to the end of the base name for a unique storage account name first let's add the provider for this module we'll go back to the terraform registry we're in the azure rm provider we need to find the random provider let's type in random there it is hashicorp random we'll go to use provider we'll copy this let's go back to vs code and at the top of the storage account main.tf and let's paste in the provider remove the provider block it's empty and not needed now that we have the provider let's add a resource called random string with the name random so this is a resource block we'll start with resource the resource is random underscore string and the local name we'll just call it random we need to add some arguments the length will set that to six digits there's another argument called special this indicates if we want to use special characters or not we're creating a name for a storage account so we want to make sure this is set to false we'll set that to false after that we'll use the argument upper and we'll set that to false remember we can't use special characters or uppercase letters for a storage account name this will create a string that's six characters long with no special characters and no uppercase letters now that we have the base and the new random string let's format the storage account name everything has to be in quotes just like we did with a resource group we'll add a dollar sign opening and closing squiggly brackets and pass in var.base name again that tells terraform to use the value of that variable so right after the closing squiggly bracket we're going to add another dollar sign in brackets and this time we'll add that random string so we'll go random underscore string that's the resource type dot random dot result so that will concatenate those two values what we entered in as the base name and the random string one more thing and this is because the storage account name has to be in lower case we didn't create any formatting or input rules for the base name if someone enters uppercase letters into that base name the deployment will fail because that's not a valid storage account name there's a simple fix we'll convert the base name variable to lowercase with the lower function we do that by adding the word lower right before var and then surround the variable in parentheses that forces the var.base name to lowercase next we have to change the resource group name and the resource group location to variables we'll set the resource group name to var dot resource group name there it is and we'll do the same with location var dot location save and close the files and let's go back to the main.tf in the root module let's create a new module block for the storage account so we'll start with module and we'll call it storage account we'll set the source and that's under the storage account directory we'll set the base name to match the resource group module and the resource group name we're going to run into a problem with the resource group name that was dynamically built in the resource group module now we know the name is the base name with the rg appended to the end we could simply add that but if that code in the resource group module was changed we'd have to update the reference to the resource group on the storage account module that would be cumbersome we want this to be as change free as possible this is a problem that outputs will help with let's save the file and we'll talk about outputs next let's close this and go back into the resource group module we want that module to return something when it gets done running we'll do that by starting with an outputs.tf file outputs simply return a value to the calling module we'll create a new output block and you guessed it it starts with output give it a name for this example i'll use rg underscore name underscore out then we give it a value this is the value that will be returned and that value is going to be the value of azure rm underscore resource underscore group dot resource group dot example and name we can hop over to main tf to see that value so it's resource azure rm underscore resource underscore group dot example dot name this will return the value of the resource group name and assign it to the rg underscore name underscore out output save and close the file and let's go back to the main.tf and the root module now when we apply this the resource group module will be the first to run once it's finished you'll return the resource group name and the output we'll use that name to supply the resource group name to the storage account module we'll do that by specifying module dot resource group dot rg underscore name underscore out okay and one last thing before we move on we have to add a location and we'll manually add west u.s so in this step we're simply calling the output from the resource group module and applying it to the input of the storage account module this is how we can pass the output from one module and use it as input for the next so let's save this file open up the command prompt and let's run terraform in it that looks good let's run terraform plan all right let's take a look at the resource group that's using the correct location and the rg at the end of the name just like before let's look at the storage account the location looks good but look at the name it indicates known after reply what does that mean well we told it to base the name off random characters so we won't have a name until it's actually applied and those random characters are generated so let's apply it now you may notice it's created the random string this will take a couple minutes to finish i'll pause here and come back once it's done that finished we can see the name of the storage account in the cli or by going into the resource group in the portal and there's our storage account with those random characters at the end that all looks good but at some point we may want to use automation and something like a storage account name could be used as an input variable for another module especially because that storage account name is getting created on the fly let's go back to vs code we can close the terminal as well as the main.tf and go back to the storage account we're going to give the storage account its own outputs.tf file we'll create a new output block with the name stg underscore act underscore name underscore out we'll give it a value and that value is resource dot azure rm underscore storage underscore account dot example dot name we'll save that we can close and if we go back to main we can verify that value we entered in the output block resource dot azure rm underscore storage underscore account dot example dot name let's close the main tf and one more thing outputs are passed back to whatever called the module for what we're doing with this example we're calling the root module from the command line the root module calls the resource group and storage account module the outputs are exposed to the root module the way it sits now but not to us let's open up the command prompt and run terraform output to see what outputs are available to us there we go if i spell it right it shows there's no outputs nothing shows because we didn't pass the outputs from the root module back to us we had outputs from the resource group module and we'll have them from the storage account module the next time we run it because we just created the outputs.tf so let's fix this from the root module the module example directory create a new outputs.tf file we're going to return the value of the resource group name and the storage account name create a new output block and give it the name sdg act name we'll add the value the value is module dot storage account dot storage account name out next is the resource group name so another output block we'll call it rg name the value equals the module dot resource group dot rg name out save the file and before we run this again let's destroy the previous deployment that's providing you haven't rolled this into production yet of course i'll pause here and come back once it's done okay that finished once done let's run terraform init and terraform plan that's looking good notice we have a couple new things on the bottom the output for rg name and storage account name let's run apply i'll pause here and come back once it's finished now that finished we can see the rg name and storage account name output also if we run terraform output it returns the two values as well this is an example of calling modules and passing data back from the modules as output we also added the random resource and lower function with the example a module with a single resource may not be the best practice matter of fact in production it may be better to create a single module with both the resource group and the storage account but this makes for a good example we'll build on this example with more complex deployments in the future that's it that's the basic framework we'll use for creating modules in azure this may not have been the best use case for modules but it's a simple example we'll use for creating reusable modules in the future please don't forget to like and subscribe and thanks for watching
Info
Channel: Travis Roberts
Views: 23,994
Rating: undefined out of 5
Keywords: Modules, outputs, outputs.tf, terraform outputs, terraform modules, Terraform.tfvars, variables, terraform variables, terraform var, Azure, Azure CLI, IaC Terraform, Terraform Registry, VSCode, Terraform for Azure, registry, .tf, HashiCorp, workdlow, Terraform Resource, .terraform, Terraform Write, Terraform Plan, Terraform Apply, Terraform Destroy, main.tf, terraform tutorial, terraform training, Terraform Examples
Id: 0YLPfSLbp9Y
Channel Id: undefined
Length: 28min 2sec (1682 seconds)
Published: Sun Dec 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.