How to build Azure Functions with PowerShell
If you want to build an Azure Functions app with PowerShell, don't start in Azure.
That may sound counterintuitive, but in this video, Anthony Howell, PowerShell consultant and DevOps engineer at Equip, illustrates why it's easier to start the process inside Virtual Studio Code instead.
First, make sure you install the Azure Functions extension. Once there, expand the subscription tab on the left and add the new function. Then, press the lightning icon to create a new project. It will prompt you to choose a folder and language and, in this case, you chose PowerShell for the function project.
Next, choose the trigger, which is an event that will launch the function. There are numerous trigger options in Azure, including timer, queue and Event Grid, but for this example Howell uses an HTTP trigger that kicks off in the presence of a HTTP request. Users can choose multiple triggers at one time, but be sure to be descriptive with naming.
Once you set the triggers, select an authentication before you add it to your current workspace. Users can now see all of the files created within the file explorer and it opens the "run.ps1" file. Each folder represents a function and you'll see "function.json" files that include the function's settings. The "run.ps1" file displays all the parameters for the function. This is where you will notice "$name = $Request.Query.Name."
If you want to return the information, send specific commands to do so, such as a "Push-OutputBinding" cmdlet that will send the information to the user who triggered the HTTP request. With VS Code, you can hit F5 to start a local version of the function.
Next, scroll to the bottom of the page to see the link to the function's API. If the user wishes to launch another PowerShell session, grab that URL, complete "Invoke-RestMethod" and use the "Get" method. All user requests are logged by Azure Functions so they can be tracked by the organization.
The next steps go deeper into updating commands, testing the triggers and debugging the code -- all while the function runs locally. To get a full grasp of the entire step-by-step process, watch the video on how to build Azure Functions with PowerShell, or read the transcript below.
All right. To get started with a PowerShell function in Azure, you notice that I'm not in Azure, it's actually easiest to build it inside of VS Code. So in VS Code, make sure you've got the Azure functions extension installed. And if I open that, you can see that it will show me all of my subscriptions I have access to. So I'm going to expand out the one that I want to add the function to, and it may take a minute to load. And you can see that I've got two other functions in there already, but we're going to create a new one.
So to do that, press this like little lightning icon, and it's going to tell us we have a project open. So, let's create a new project. And I'm going to select a folder that I've already got created here, and use that. And here we can select the language. So, in this case, creating a PowerShell function. And for the trigger, this is what kicks off the function. An HTTP trigger will kick off when it receives some kind of HTTP request. And the other really easy one is the timer trigger, they've got a lot of Azure ones. We're going to use the HTTP trigger since it is real easy to demo, and leave the default name of HTTP trigger. And keep in mind, with your function you can have multiple triggers, so it will behoove you to name it something that's more descriptive than just what type of trigger it is. And here we can select if wewant to be able to use authentication or just anybody can use it. I'm going to select "Anonymous," so we don't have to worry about authentication. And then I'm going to choose to add to the current workspace that we're already in. There you go. And once that happens, you notice that we've got all these files created in the file explorer on the left, and it opens up the "run.ps1" file.
So this folder structure on the left, each folder is a function. And underneath that function, it's got the "function.json" file, if we take a look at that. These are all the settings for your function. So you can see it's got the authLevel, the type, the direction, the methods and the name. And so, the name, that is the name of the request that comes in. And of course that "run.ps1" file that we just took a look at, we're not going to worry about the "sample.dat" file. And so, inside of this "run.ps1" file, and this is what's really important. You notice here at the top we've got the parameter. So the first parameter is "Request." So that's the actual request that is sent to our function. And so if we scroll down to where you can see that "$name = $Request.Query.Name." And if that's not true then it will be in the body, and I'll show you how to actually send this information.
So if we wanted to simply return that information, you can see here in the demo it's got an example already, saying that, if there is a name in the body, that what it's going to do is. So, it's sending body equals name, and then scroll down. In choosing the "Push-OutputBinding" cmdlet to actually send information back to the original sender of that HTTP request. And so what's really cool with VS Code is that if we just hit F5, you can see that it's actually going to start a local version of that function. And this is pretty typical, the first time you write it, it will break into the debugger. So we just hit F5 again to continue. OK.
So, here down at the bottom, it actually give us a link to our function's API. So go ahead and copy this. If we launch another PowerShell session here, we can do an "Invoke-RestMethod" and give it that URL, and just use the "Get" method on it. And we can see that if we scroll down on this output here, you can see that it actually logs the request that we just sent it. If we look at this output here we can see, "Please pass a name on the query string or in the request body." And remember, if we take a look at the "run.ps1" and that if there is a name in the body, that it will respond with "Hello $name," otherwise it will ask for a name. So, let's actually send it a name.
And you notice that I'm actually sending the body as "Json." And interestingly enough, so let's check the body variable. And we can see that it is "Json." So, actually, you know what? Since we are sending it "Json" we actually need to tell it that we're sending a "Json" so that's what the "ContentType" option does. So, there we can see we get a response that says, "Hello Anthony." Cool. So, once we want to stop the function from running we just hit the stop there in VS Code. And now what we can do is, if we want to change this -- so, for instance, if we want to say, if name equals Anthony, for example, and put the status above the name as well. And something else we can do, it's really useful and a function for PowerShell, is we can actually debug it while it's running here locally. So, let's try that.
And so to debug it, instead of putting breakpoints like you normally would, you actually use the "Wait-Debugger" cmdlet. So, if I put that in there and then run this function again, using F5 to actually have it launch the function in the background. And if we scroll up, you notice it's using the same URI from before. And if we send it the same exact response from before, in our other PowerShell window, if we flip back over here, you notice that we've got that executing in the log there. Sometimes the debugger does break inside of the module here. That's expected, it's actually listed in the documentation, so we just have to hit F5 again to continue on to the actual breakpoint. And if we do that, there you notice that we've got the break right next to the "Wait-Debugger."
So now, if we switch to our PowerShell integrated console, and notice that we've got that debugger. So we can actually look at the name variable, for instance. We can see that it's Anthony. And on the left, of course, we can also get a graphical representation of that as well. So if you wanted to make sure that the name was setting properly, or, you know, just normal debug stuff, this is how you would do that. So I'm going to go and hit F5 again, there we go. So it's saying that command completed. So we'll switch back over to the task here. So, now what we should see is we got a response out of the Azure function. Sweet. OK. Cool.
So, assuming that's exactly what we want in our function, we can go ahead and stop the function. Oh, and since it creates a local repository, we can actually commit it in. And we can push that to a GitHub repo, an Azure DevOps repo, whatever you need to, assuming you want to save your code. And if we switch back over to the Azure functions, we should be able to select our subscription again, and then deploy our function app to Azure. And here, again, we're going to select the subscription and we're going to create a new function app. And here's where we're going to give it a name. Oh, can't use underscores apparently, so we'll take that out. And you notice down here in the bottom right-hand corner, it's creating a storage account as well as a function. So the function has to actually store a small amount of data in Azure, and this can take a couple of minutes to complete. And then you can see in the bottom right-hand corner, "Creating new function app, 'TechSnipsDemos'." Perfect. Cool.
And now, notice that we can add a URI for our function that it gives us down here. And so, if we let it finish actually deploying the function we wrote to the function app it just created. We'll give it another minute while it finishes loading. There we go. So now, go and close that output. So, now if we expand our function app, we can see, in our functions we've got our one HTTP trigger. And to get the URL for that function, we can just right click and copy that function URL. And now if we go back to PowerShell, I'm going to take that local host out of there and then paste in the URL that we just got from the function itself. And there you can see, it's what? "techsnipsdemos.azurewebistes.net/api/HttpTrigger." And if we run this -- the first time it runs it does what's called a cold start, which means it actually has to start up and initialize. That's OK, it's going to take a little longer than usual. And actually, we're going to be waiting a long time for this. So, I'm going to go ahead and ctrl+c out of this.
This is something I've done several times before. But you've got to make sure you don't leave the Wait-Debugger in your script, otherwise, your cloud version of your function app will be waiting for the debugger indefinitely. So, I'm going to go and save that, I commit that. And then go back to my Azure functions here, and I'm going to deploy this back up to the same function as before. Yes, overwrite it, that's fine. So hopefully, that's the result of seeing me run into that. You can also run into that same problem, where you forget and leave the Wait-Debugger in your script.
All right. There we go. We have that "Deployment to 'TechSnipsDemos' is completed." So if we switch back over to our PowerShell console, we can go ahead and run that same exact command again, but this time the cold start will take a little bit of time, but it should actually return some data within a reasonable amount of time. There we go. So this time we did actually get the response from Azure. And if we did want to change the body to be a different name. So, for instance, and then we run again.
You notice, the second time it goes much faster. That's because it's doing a warm start. So the application is already running, initializing, just waiting for a response. And since we sent it in a different name, it's just telling us, "Hello," and then the name we sent it. So that's how you can get started building PowerShell functions inside of an Azure function app. Thanks for watching.