 You've probably seen how to create Azure resources using the Azure portal, but that's a manual process and it's easily screw-upable when you need to create and repeat the resource creation for multiple projects or when you're moving from dev to production or when you're deploying your customer solution to their Azure subscription from your developer subscription. Wouldn't it be better to script the resource creation and configuration process to ensure that it's the same every single time? What about versioning your resource configuration so it's part of your code? You can with Infrastructure as Code or IAC. IAC is popular in the DevOps world and it fits nicely alongside a complete CI and CD process. It involves creating your resources from machine readable files that can be versioned with your project in your source control solution. In this video I'm going to start with a blank slate and I'm going to show you how to use Bicep, a domain specific language from Microsoft to create Azure resources for an Azure function app. This episode is also available as a blog post on boytonos.io and as a podcast on boytonos.show. Check out the description below the video for links to these other resources. Hi I'm Andrew and if you're new here subscribe to my channel to get notified of future videos for professional developers on Microsoft 365 and Azure topics. Let's start with the question what is Bicep? But first let's talk about ARM. You might be familiar with something called the Azure Resource Manager which is also known as ARM. ARM templates are big JSON documents that you can use to deploy Azure resources and they also have the ability to accept parameters or inputs so that you can create variables for things like resource names, settings, different SKUs, IP addresses, and domain names just to name a few things. But they aren't terribly friendly to work with because they're huge. So Microsoft set out to simplify the challenges with ARM templates and they wanted to create something that had a concise syntax, reliable type safety, and support for code reuse. That's what Bicep is. It's a domain specific language or a DSL that provides a much richer and more productive environment than what we get with ARM. In fact you can compile a Bicep file down to an ARM template in vice versa. Now Bicep has a ton of benefits and Microsoft touts that Bicep has support for all resource types and API versions. It's also got a simple syntax especially when you compare it to those ARM JSON templates. A better authoring experience thanks to a VS code extension that gives us type safety, intelligence, syntax validation, and a bunch of other stuff. The result of a deployment to Azure with Bicep is repeatable giving you confidence in your CINCD process. You don't have to worry about the ordering complexities of resource creation. You simply deploy with one command and Azure takes care of all that stuff for you. And it's also very modular so that you can break it up into different components that we call modules in Bicep. You can even preview what's going to happen to your deployment with the what if operation. You can see what's going to be created, deleted, or updated and any of the properties that are going to be changed as well with that operation. And best of all, Bicep is included with Azure. You don't pay a thing and it's fully supported by Microsoft support. Okay now that's your Bicep overview fire hose sales pitch. So brass tacks. Let's see it. Let's look at a common scenario. Let's say that you want to create an Azure Function app. Now this is a simple process using the Azure portal. The wizard that you're going to go through in creating it is collecting enough information on creating the resource. Let's see that. What I'm going to do is come over here to my Azure portal and go to portal.azure.com and I'm going to go ahead and sign in. So here I'm in my Azure subscription and I'm going to go ahead and I'm going to go ahead and create a new resource or say I want to create a new resource. So I'm going to start by creating a new resource group and we'll just call this our playground 01. And I'm going to put this in my east US and just say review and create it. So our resource group is now created. Let's go see what it looks like to create our Azure function app and see what the process looks like. So I'm going to go say create and I'm going to search for a function app and I'll say create. Now from here it's going to ask me a bunch of questions. So where do I want to put this? I'm going to put it in the existing resource group that we just created playground one. Let's give it a name. I'll just call this my playground function app. It doesn't like that. So how about 01? There we go 01. I'm going to be publishing things as code. Let's see the runtime stack. We're going to use node. This doesn't really matter at this time. The version LTS is good. We're going to deploy this to east US. I like Linux and we'll just say it's a premium plan just for kicks. It's going to ask me what kind of a premium plan I want to use here. So it's given me an option for creating my hosting plan of where my Azure function app is going to run. So it's creating one called ASP playground 01 with four characters after it and it's chosen the elastic premium one EP1 skew in size. It's asking about zone redundancy. I don't really care about that right now. Hosting, it needs a storage account. That's interesting. So that one's called playground 01 BE44. And let's go to networking. I'm not going to deal with any of the networking stuff right now for monitoring. Yeah, I'm going to go ahead and use Azure application insights because that's going to hook up to my function app to let me see how the function app is performing both from the resource side, but then I can also use that inside of my functions as well. And I'll just go ahead and I'll just say create. So it'll go to a review and then I say create. And I'm going to let this go ahead and create our resources. All right. So what did that process create? Well, it created a storage account, an app service plan or a hosting plan where everything is going to run and it created our function app as well. It also created an instance of application insights that we're going to use to monitor the function app and it connected to the function app to the app insights instance. And we can see that if we come over here to our function app and we look at the configuration for our production deployment slot and what you're going to see here are a bunch of app settings and you can see some of the app settings for application insights. We also have an app setting for the storage account that was created, the web storage, the web jobs storage, some details about the function as well like what's the extension version we're using in the runtime and then also some website content settings as well that have been set. Not only this, maybe you also want to create some additional deployment slots for your function app. That's something you definitely could do. Well, let's see how we can do all of this with bicep. Now, in another video, this one up here that I'm also going to link to in the description below the video, I'm going to show you how I'm using this bicep file that we're about to create in a GitHub workflow for a complete CI and CD process. This video that you're watching right now, we're just going to focus on the bicep part. So first, let's make sure that my environment is all set up. Now, there's nothing I need to do with Azure, but I do need to make sure that I've got some stuff that I've done to my laptop to be able to use bicep and create the bicep templates and test them out. Now, to create a deployment with your bicep file, I'm going to use the Azure CLI and I guess you could use PowerShell, but I'm a CLI person, so I'm just going to use the CLI. Now, I already have the Azure CLI installed on my laptop. So I'm going to drop a link to it in the description below just in case that you need it and you haven't installed it. Now, bicep is provided as an extension to the CLI. So first, let's see if it's installed. I'm going to use the terminal that's in VS Code because we're going to use VS Code to create our bicep file. So we're just going to use the terminal because it'll be easier to see both of them at the same time. So I'm going to do this by saying az bicep version and what that's going to do is that's going to use the Azure CLI to see if bicep is already installed and here you can see it's not installed. So it tells me how to install it by just saying az bicep install. Now let's make sure it's installed by saying az bicep version and it should come back and give us some information about the extension that's installed. Okay, cool. So that's good. We can even ask it what things can we do with this by doing the help command. Okay, so bicep is now installed inside of the Azure CLI. Now, I also need to make sure that I'm logged into Azure with the CLI and I set the CLI to the Azure subscription where I want to create all these resources. So to set the subscription, I'm going to run az account list to get a list of all the subscriptions for my account that I have access to and then I'm going to set which one I want to use using the az account set and then use the subscription argument and then to confirm that I have the subscription set on the CLI that I want to use, I can just see az account show and that confirms that I'm actually using or I've set to use the subscription that I want to use here. Now let's make sure that Visual Studio Code has the bicep extension installed and I'm going to include a link to this in the description below to make sure that you can find it easily. My machine definitely does because I can just say bicep and I can see that the extension is already installed and so with that my laptop is good to go. Now the first thing that I'm going to do is I need to create a resource group where I want to put everything. So I can do that using the Azure CLI as well. Now I'm going to store the name of my resource group in a variable called resource group and I'm going to use that to create the resource using the Azure CLI by typing in az group create pass in the name of the resource group, the location where I want the resource group to be defaulted to and then I'm just going to set a tag on it as well and now to confirm that resource group was created I'll just come back over here to the Azure portal. I can do a refresh for my subscription and here we can see we have Playground 2 set up. Okay with everything set up let's get started creating our bicep file. So when you do this you want to think about your dependency tree like as a mental map like I'm creating a function app but that needs a hosting plan so I should create that first and then my function app is going to need a storage account to store logs and some other things so I probably need to create that as well before I create the function app. You get the picture. Let's start by creating the basics of our bicep file. Now I'm going to start with what I want for my inputs known to be as parameters to be and these are going to enable my bicep file to be reusable across different projects. What I'm going to do first is I'm going to create a parameter called location and it's going to default to the location of the resource group that we're currently in where we're defining this. You're going to see in a little bit when I run my bicep file I'm going to tell it what resource group to create the deployment in so when it runs the bicep file is going to be able to get the location of the current resource group so all resources that are created in it they're going to go in east u.s. where my resource group is. I'm then going to create a resource name prefix parameter that I can pass in or I should pass in and what I'm doing with this is I want every single resource that I create in my azure function to have the same prefix on their name I'm going to standardize the suffix to be whatever I want inside of my bicep file. Here you can see I'm also setting the description of it so that when I use this bicep file I can get intelligence if another bicep file is going to call it. The next thing is I'm going to define the deployment ID I'm giving it a default value of a bunch of zeros but in the other video where I'm going to talk about using github actions for deployment you'll see why I like to go through and set the deployment ID as well and then finally I'm going to define the name of the staging slot that I want to create for my function app and in my case I'm going to default that to staging so now let's create that storage account that we're going to need now to create the resource I'm going to use the keyword resource and give it a name I'm just going to call this my az storage account that's an internal variable for my bicep file that I can use in other places I'm going to use the resource called microsoft.storage slash storage accounts and then I specify what API I want to use now when I create this I'm going to pass in a bunch of properties and I do that using a similar syntax to what we have in json where I'm setting an object with a bunch of properties I'm going to set the name to be whatever the prefix is with storage on the end I'm going to set the location equal to the location of our resource group which we defined in our parameter at the top I'm going to set the kind of our resource to storage v2 and then I'm going to set the skew to be standard locally redundant storage so I'm not going to do any kind of like globally redundant stuff in this demo here when we create the function app one of its app settings needs the connection string for the storage account so what I'm going to do is I'm going to create a variable and I'm going to use the first keys bicep function to get the primary and the secondary keys from the storage account the primary key is the first one in the array that's returned so I'm going to stuff that into this variable notice that as I'm typing some of these things in I'm getting some intelligence and that's the benefit of using something like bicep over using arm templates because we're getting this intelligence and part of it's being provided to me as well through the vs code extension for bicep you'll also notice that I'm getting these little squigglies or little warnings here and it's saying that hey you've defined this variable but you're never using it so you might have picked up on that as I'm typing certain things like this environment name prefix when I use this to create the string interpolation to basically concatenate two strings together I was that I was showing up as not being used up online five but now that I'm using it it's actually working next let's create the app insights instance to do this I'm going to create a new resource named az app insights and I'm going to use the resource called microsoft.insights slash components and then pick the API I want to use the API version I'm going to set the name of the app insights instance to wherever my prefix is dash AI I'm going to set the location to east us using the same location property the kind is set to web and then I'm going to set some other properties on this like the application type the public network access for ingestion and for query I'm setting all these different values these are all all these different options are defined not only on the resource itself but it's also defined in the bicep documentation the type for all the different types that are available you can use any of the stuff that you have with arm that in bicep files for those different property values remember bicep is kind of just a dsl on top of arm templates now similar to creating that storage account I'm going to need the app insights instrumentation key for the function app when I create it so I'm going to stuff that in a variable as well right now all right now for the main event now let's create the function app but first I need to create a azure hosting plan where it's going to be stored to do that I'm going to create a resource we're going to stuff it in a variable called az hosting plan and I'm going to use the resource microsoft.web slash server farms I'm going to set the name the location and the kind to use the similar values I've already used so far the kind you notice I'm going to set that to Linux for the skew I'm going to use an s1 skew and for the properties I'm going to set it to be reserved oh there's something I want to show you so before we move on so check this out the vs code bicep extension can show you a visualization of all the resources that you're creating cool right what's cool about this is I can even click to one on one of these resources and it'll take me straight to the actual resource that I've created so you can see I'm jumping around here so that might not be too exciting but watch this remember our function app that's going to have to have a dependency on the hosting plan let's create the function app now so to do that we're going to create a new resource called az function app and then I'm going to I'm going to use the resource called our named microsoft.web slash sites I'm going to set the name I'm going to set the kind it's going to be a function app the location and the identity for this one we're going to use a system assigned identity so we could use like managed identity you'll see in the other video that I'm going to talk about later or that I'll show you I use this and with my full CINCD process with a github workflow you'll see where that's coming into play now for the properties as I set these properties watch the visualization over there on the right hand side as I finish all these properties up and how I'm I'm linking the server farm id to the hosting plan that we just created his id now function apps just like web apps in azure can have deployment slots that are depending on the hosting plan that you selected I love using these and in my other video that is going to that I'm going to show you how I use github workflows to do full CINCD of an azure function that's going to use this bicep file I'm going to show you how I use them with my azure functions for completely automated ci and cd process that includes swapping the two deployment slots when I want that to happen but I need the slots first so I've already got one slot by default because when we create the function app it automatically created that but I need a staging slot so let's go about creating that now now to create a staging slot I'm going to use the same resource keyword and call it the az function slot staging and then the name of the resource I'm going to use is the microsoft web slash sites slash slots I'm then going to set the name the location the identity and the properties to be very similar to the ones we have for the function app but you'll notice the name looks a little bit different because it's going to be the name of the function app that we created previously and then I'm going to add on after a slash the name of the staging slot that we passed in as one of our input parameters but wait a minute did we forget something a function app needs some application settings that are defined when it's created right we saw that and when I created it using the portal that's how app insights is going to be wired up along with a few other things like the supported functions runtime and a whole bunch of other stuff well I didn't forget anything instead I created the resources like this very intentionally here's what's going on I want the slots in my function app to have mostly all the same app settings across both of the different slots except for one property I want that to be slot slot specific and that means I don't want it to change when I swap the different slots I want it to stay with that slot even though the code base is going to change so in the azure portal I usually do this by checking a box on the slot property but when I provisioned it with the resource manager you first have to tell the function app that one setting is slot specific and then you have to go set all the app settings on each slot independently so here's how we're going to do this first I'm going to tell a function app that it has one specific setting that slot that slot specific and I'm going to do this with a microsoft dot web slash sites slash config resource and I'm going to set its name to slot config names then I'm going to list the all the app settings that I want to be slot specific to be the app settings names property and lastly I need to set the app settings on both slots but I'm going to do this with a special capability we have in bicep called a module let's create a new bicep file that we're going to use to set our app settings on the slots and I need a few input parameters like the app insights instrumentation key the storage accounts details the function name and the staging slot name so let me go ahead and add these now I'm also going to create a parameter with the default value that I want for that slot specific app setting now because both of the slots app settings mostly mirror each other except for that one property I'm going to create a common variable called the base slot app setting that contains all the settings that are shared by both slots and I'm going to use string interpolation to not just create these name value pairs but also concatenate a few strings for the different values of these different settings so they're all in the name value pair setup now let's set the production slot settings now I'm going to do that by creating a new variable with just the value for the production slot and I'm then going to set the value using the same microsoft.web slash site slash config resource and I'm going to set the name of the function app slash app settings all right that's how it's going to set those app settings and the value of the properties that I'm going to set well I'm going to use this the bicep union function to merge the base settings and the production settings together and they're going to repeat the process for the staging slot but instead I'm going to use the resource microsoft.web slash sites slash slots slash config and I'm going to use the name of the staging slot to specify these different settings now to call this module let's jump back to my main bicep file and I'm going to use the module keyword to call my module and I'm going to give it a specific name unique to the deployment and then you're going to see why I'm going to do that in a few minutes when we actually do the deployment to set the input parameters I'll just set those using the params property on the object that I'm creating notice that you saw on the visualization it created the app service module that I was creating or the the the module that I created and then once I referenced the file it actually looked inside that module and it showed me the resources that were being created which were the two functions slot settings also notice that I'm using the variables that I created previously to pass them in as parameters to get things like the app insights instrumentation key and the storage account access key and notice that this module as I'm giving it these different references it's picking up dependencies on some of the other objects and resources that I've already created in this bicep file now the last step is to update the output settings this isn't really necessary but you're going to see why I do this in the other video where I use this bicep file in my cincd process for my github workflow now let's look at that visualization I'm gonna go full screen notice how we can see our nested module in our main bicep visualization this is really cool we can use this module on its own too if we wanted in a totally different bicep file or we could just use it straight from the azure cli let's see if this works I'm going to go back to the console and I'm going to use the azure cli to create a brand new deployment I'm going to do that by typing in az deployment group create I'm going to give the deployment a name I'll call it my deploy one I'm going to tell it what resource group where I want to create this deployment so in this case here I'm going to use the same variable I used earlier I'm going to then specify the bicep file that we're going to use and then I'm also going to pass in a couple parameters remember that we had a few input parameters on our bicep file like the deployment name ID we're going to call that my deploy 1.1 or 1-1 and then I'm also going to set the resource name prefix and I'm going to use the prefix name Zara and I can see we got an error here so let's take a look at this and we see there's a reference to a staging slot line 99 so this is a little confusing because unfortunately what we're seeing here is the error is coming from the JSON file that was generated so I have to kind of use this to figure out where the problem is and I can see that because it's talking about a function staging slot that is probably going to be when I'm creating the staging slot and sure enough I can see the problem because I'm passing in a resource here when it really wanted to pass in the name now it took a second to get started but that's a good sign because it likely means that my bicep file is valid unlike the couple little typos that you saw me have earlier so what I'm going to do is I'm going to jump back over to the Azure portal I'm going to go into the resource group that we create our playground to and I'm going to go over here to our deployments and see what deployments we have and we can see there's the deployment is starting to run right here now let's see everything that got created so if I go look at my deployment we see one was called my deploy and we can see all the stuff that it did these are all the things that it created or our work that it ended up doing here we see storage listed twice that doesn't mean it was created twice it just meant that it was created there maybe was an update to it somewhere along the way we can also see that it actually ran another deployment inside it we can see that this one's listed as a deployment and see where it's called my deploy one dash one grant app service this is the deployment that we use to create our our module so when our main dot bicep called our other module that was setting the app settings those are seen as two different deployments and that's why I like to use that deployment ID I give it a name because I use that as kind of the prefix so when I look at all of the deployments for this for this resource group I can tell that that this deployment was tied to this one and what's also cool about this is that when I look at the deployment I can also look at what the template looked like so here's the JSON template that was created from our bicep file we can also look at the variables that were defined and the parameters that were all passed in but I can also look give it a little bit easier to see I can look at the inputs for this deployment so there's the location for our resource group there's the resource name prefix there's the deployment name ID and the function app staging slot and I can see the outputs that were returned back to me so that's why I said I don't you don't really need to do the outputs but it's kind of nice so we can go back and see like hey what did you create an app insights instance what's that instrumentation key if I come back over here to the resource now and if I go to the overview here I can see all of my resources are all created we've got our azure function app we got a staging slot there's our hosting plan and there's app insights if I come to my azure function app and I look at the deployment slots I can see that we have two slots that are created if I look at the production slots configuration which is what we're on right now and I show all the values you can see there's our instrumentation key there's our storage account connection string and all those are the values that we set notice here that the app configuration level is set to be a deployment slot setting and the value is set to production if I jump over to my staging slot and I look at the staging slot and pick his configuration here you'll see after showing the values he's got all the same values except for that one that set up as a as just a slot specific setting so this is really cool we can see all these values that were set and sure enough we could even see look at that one deployment that we created that can for our app settings or for the settings we set for each one of the slots and we can see all the inputs that were passed into it so like the staging slot name was named this the function app name was named this etc so it's really cool we can see all that stuff that's all defined biceps pretty cool as I now have a file that defines the function app and all this dependencies and one thing that I love about this infrastructure is code stuff is that not only do I have a file that I can use to recreate and make changes to my app but my changes can be versioned and documented with my project and that's going to act as like documentation for whatever my project needs so what do you think let me know by dropping a comment below and let me know if you want to see more videos about bicep or azure functions or doing azure functions ci and cd stuff if you like this video please give me a thumbs up and consider subscribing by smashing that big red subscribe button below that way you're going to see when I publish more videos on similar topics for professional developers specifically around microsoft 365 and microsoft azure including topics on bicep and azure functions hey and don't forget to check out that other video where I show you how to use this bicep file in a complete ci and cd process and that uses this file to not only create the resources in a github workflow but only if all of my tests pass once the azure resources are provisioned the workflow then deploys my app into the resources that it created thanks and I'll see you next time