Follow me on Twitter, happy to take your suggestions on topics or improvements /Chris
There are many ways to create Serverless functions with Azure Functions. We can use the Portal, VS Code but also the terminal and a Cli tool called
func
. We will focus on the latter in this article, so be prepared to go full terminal :)
In this article we will cover:
- WHY, why do we want to use the CLI to manage our functions when we have a UI?
- WHAT, what will this CLI tool allow me to do?
- Demo, of course, we want to take our CLI tool for a spin and see how it works right, right?
Resources
Sign up for a free Azure account
To create Serverless Azure Functions you will need a free Azure account.Net Serverless series
A collection of articles I wrote on .Net + Serverless and some other thingsServerless series,
authoring in Portal as well as VS CodeCore Tools Development
We've only scratched the surface on all the possible options you can use with thefunc
CLI.Install Azure CLI
Azure CLI is very competent and pretty much everything you can do in the Portal is possible to do from the terminal
Why a CLI
There are many reasons to why you would want to use a CLI.
Scripting, One of the more important reasons is probably scripting for usage in a CI/CD process.
Speed, Speed could be another factor, few things beat the speed of running a command in the terminal
IDE/Editor agnostic, We all have a favorite terminal we like to use. Sometimes what we want to do is possible to do through a UI in our editor of choice and sometimes it's not
What
Before we begin let's start by installing our CLI. This looks a bit different depending on your OS of choice.
Installing
What we need is something called azure-functions-core-tools
. Below is the instructions for respective OS:
Mac
brew tap azure/functions
brew install azure-functions-core-tools
Windows
npm i -g azure-functions-core-tools --unsafe-perm true
Linux
wget -q https://packages.microsoft.com/config/ubuntu/19.04/packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb
Everything installed? Good :)
Overview of func
Ok so we got this CLI tool installed called func
. Run func --help
in the terminal and let's try to gain an understanding of what it can do for us:
Ok, we got quite the long answer back so let's look at it page by page. Above it's listing what it can do for us generally like working with:
- Azure, allows us to manage resources
- Durable, this is a stateful Serverless offering that we won't look at now but in a later article
- Extensions, this is about supporting different kinds of bindings, to support binding to e.g a Database we need to have an extension installed for that
- Function, this is about support actions around functions like creating and running them
- Host, how to run our functions locally
- Kubernetes, heard of Kubernetes? No? It's what you can use to orchestrate containers. Still confused? It's ok, I got a 5 part series on Kubernetes here
- Settings, we want to be able to manage settings, it could be connection strings to a database or some other keys we might need to run the app
- Templates, when you scaffold a function you need to start by selecting how to trigger it, e.g what causes the function to be invoked in the first place. That could be a change to a Database or someone hitting a HTTP endpoint and so on.
Let's check out the other page we got from running func --help
We got four distinct actions:
-
start, by calling
func start
we will build and run the code -
new, by calling
func new
we trigger a function creation process in which we are asked to for the template we want to use -
init, by calling
func init
we trigger a process that allows us to create a Function App project, all functions needs to live inside of such a project - logs, calling this command means we will be abl to get logs from a running function so we can analyze what's going on
Demo
So what do we want to achieve with our demo? Well, we want to:
- Scaffold a project, this where we need to start. We will go through how to scaffold for different programming platforms
- Scaffold a function, of course, we want to scaffold functions. This has a great wizard that kicks off.
- Run the app, once we scaffolded everything, let's ensure we can run our app, like we are used to from VS Code
- Deploy to Azure, using Azure CLI we will create the needed resources and end up deploying our Function app + functions to the Cloud
Scaffold a project
You can start a project with just func init NameOfProject
but this will give you the default worker runtime, which is dotnet
. So for that reason I recommend being explicit like so:
With the above command we func init MyNodeApp --worker-runtime dotnet
it will create a .Net based project in the directory MyDotnetApp
, e.g the name of our creates a directory with the same name.
Other possible values for --worker-runtime
are dotnet, node, python, powershell
.
Scaffold a function
Now that we have decided a --worker-runtime
and any functions we scaffold under our app will follow suit and be created in the same runtime.
To create a function we kick off a wizard by typing func new
, like so:
As you can see above we are asked for a template, thereafter a name for our function. This creates the expected Get.cs
file. What happens here depends on runtime chosen. For JavaScript, you would get a directory Get
with a index.js
and function.json
.
So what does my Get.cs
look like?
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace MyDotnetApp
{
public static class Get
{
[FunctionName("Get")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
}
}
That looks like what we are used to. Worth noting is that authorization is AuthorizationLevel.Function
, so if we want that to be either Anonymous
or Admin
we can always change it afterward.
So is this the only way to scaffold a function? No, we can skip this wizard and use flags like so:
func new --template HttpTrigger --name Post
In a scripted scenario, you are more likely to use the latter version of creating a function.
Run the app
Ok, so we got a function app and a function, let's see if we can run it. We start up our app with func start
, this implicitly runs restore
, that fetches needed packages and also build our app. We end up with the familiar:
and the functions work quite well:
Deploy to Azure
What about deployment? Right-click, like the browser?
Not quite, but still relatively simple.
What you need to do is:
-
Create a function app in your subscription, this step consists of 4 steps. It might sound like much but think that you are scripting this, then it's not so much. If you are actively authoring a function you are more likely to use VS Code where the
Create
+Publish
step is literally just right-click - Publish, this is a simple command that deploys your app
Create a function App using CLI
We need to create the following things
- Resource group, this is a logical grouping of your resources, think of this as a directory in the Cloud
- Storage account, as soon as you need to place files somewhere in Azure they need to be tied to a storage account
- Service plan, An App Service Plan consists of the underlying virtual machines that will host the Azure App Services. It has several tiers, from Free to Premium. The App Service Plan defines the region of the physical server where your app will be hosted on and the amount of storage, RAM, and CPU the physical servers will have
- Create the actual function app, based on having created the above artifacts we are now ready to create the actual Serverless app
Before we start, ensure you are logged into Azure via the Azure CLI. Type az login
, if you are unsure.
Let's start by setting up two variables:
storageName=mystorageaccount$RANDOM
functionAppName=myappsvcpfunc$RANDOM
the call to $RANDOM
will ensure we get a unique name.
Create a resource group
az group create \
--name myResourceGroup \
--location westeurope
Create an azure storage account
az storage account create \
--name $storageName \
--location westeurope \
--resource-group myResourceGroup \
--sku Standard_LRS
Create an App Service plan
az appservice plan create \
--name myappserviceplan \
--resource-group myResourceGroup \
--location westeurope
Create a Function App
az functionapp create \
--name $functionAppName \
--storage-account $storageName \
--plan myappserviceplan \
--resource-group myResourceGroup
Publish
func azure functionapp publish $functionAppName
After you've run the last command it ends up listing all the URLs for each of the functions in your app. Clicking one of the URL links should spin up a browser and lough and behold, it works :)
Summary
Ok, so we took a trip down to CLI country, no UI as far as the eye could see. The terminal option might not feel as smooth as VS Code or IDEs in general but it's mostly meant for scripting so that's what you need to keep in mind. Next time you need to set up a CI/CD pipeline and need to script the creation of an app and even deploy, remember func
and func --help
even.
Top comments (0)