How YOU can create and manage Serverless functions using a CLI 
Tags: tutorial, dotnet, serverless, webdev
Published: 2019-10-07 20:13:46

---
title: How YOU can create and manage Serverless functions using a CLI 
published: true
description: This shows how to scaffold, manage and Deploy Serverless functions from the Terminal. If you are looking to script for a CI/CD scenario for example, this is the way to go
tags: tutorial, dotnet, serverless, webdev 
cover_image: https://thepracticaldev.s3.amazonaws.com/i/anv6kwepc7xhdvrcqjjs.jpg
---

Follow me on [Twitter](https://twitter.com/chris_noring), 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](https://azure.microsoft.com/en-us/free/?wt.mc_id=devto-blog-chnoring)
To create Serverless Azure Functions you will need a free Azure account

- [.Net Serverless series](https://dev.to/azure/net-core-series-serverless-graphql-nuget-testing-entity-framework-and-more-5dgk)
A collection of articles I wrote on .Net + Serverless and some other things 

- [Serverless series, ](https://dev.to/azure/serverless-how-you-can-learn-serverless-authoring-functions-in-portal-vs-code-write-apis-and-more-1cno)
authoring in Portal as well as VS Code

- [Core Tools Development](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#start)
We've only scratched the surface on all the possible options you can use with the `func` CLI.

- [Create a function app using Azure CLI](https://docs.microsoft.com/azure/azure-functions/scripts/functions-cli-create-app-service-plan?wt.mc_id=devto-blog-chnoring)

- [Install Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest?wt.mc_id=devto-blog-chnoring)
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:

![](https://thepracticaldev.s3.amazonaws.com/i/x30b4h0luzpfvk2mivfp.png)

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](TODO) 
- **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`

![](https://thepracticaldev.s3.amazonaws.com/i/7t7tpzqdq7lqw2625fam.png)

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:

![](https://thepracticaldev.s3.amazonaws.com/i/9e7m6jlhaq0unk083zny.png)

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:

![](https://thepracticaldev.s3.amazonaws.com/i/3ki8tabdv79jh563hbc2.png)

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?

```csharp

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:

![](https://thepracticaldev.s3.amazonaws.com/i/f5inkicxwfg5o9git232.png)

and the functions work quite well:

![](https://thepracticaldev.s3.amazonaws.com/i/9qjyyip7h75xafvrvqlu.png)

### 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 :)

![](https://thepracticaldev.s3.amazonaws.com/i/k4r30srn5wwi7kmu0r8s.png)

## 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.