Create and Deploy Azure Functions with Serverless
Tags: serverless, webdev, tutorial, node
Published: 2019-09-24 23:04:19

> This article is part of [#ServerlessSeptember](https://dev.to/azure/serverless-september-content-collection-2fhb). You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles are published every day — that's right, every day — from community members and cloud advocates in the month of September. 

> Find out more about how Microsoft Azure enables your Serverless functions at [https://docs.microsoft.com/azure/azure-functions/](https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=servsept_devto-blog-cxa).

# Overview

Previously, the most common way to create Azure Functions is through the [portal](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function) or using [azure-cli](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function-azure-cli).  

When using either of these tools to create and deploy Azure Functions, you have to first manually deploy the dependent resources

* Resource group
* Storage account
* App service plan

You also have to write your own bindings and put them in a specific location for functions to work <sup>[1](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node#folder-structure)</sup>.  For example, if you have a `hello` http-trigger function, you will need a `hello/function.json` file with the following content

```json
# hello/function.json

{
  "disabled": false,
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "authLevel": "anonymous"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ],
  "entryPoint": "sayHello",
  "scriptFile": "../src/handlers/hello.js"
}
```

Fortunately, there's a much simpler way to do this. The [serverless-azure-functions plugin](https://github.com/serverless/serverless-azure-functions/blob/master/CHANGELOG.md) allows you to quickly create and deploy function without all the overhead work.

> Currently, the plugin only supports node, support for other languages are coming.

---

## Pre-requisites

### Node.js

Serverless is a Node.js CLI tool so you'll need to [install Node.js](https://nodejs.org/en/download/package-manager/) on your machine.

### Serverless

Make sure [Serverless](https://github.com/serverless/serverless) is installed and you're on at least `1.53`


   ```bash
   npm i -g serverless
   ```

```bash
➜ sls -v
Framework Core: 1.53.0
Plugin: 3.1.0
SDK: 2.1.1
Components Core: 1.0.0
Components CLI: 1.2.3
```

   Once installed, the Serverless CLI can be call with `serverless` or 
   the shorthand `sls` command.


```bash
$ sls -h


Commands
* You can run commands with "serverless" or the shortcut "sls"
* Pass "--verbose" to this command to get in-depth plugin info
* Pass "--no-color" to disable CLI colors
* Pass "--help" after any <command> for contextual help
```

---

## Create function

### Command

Using the `create` command we can specify one of the available [templates](https://serverless.com/framework/docs/providers/azure/cli-reference/create#available-templates). For this example we use `azure-nodejs` with the `--template` or shorthand `-t` flag.

The `--path` or shorthand `-p` is the location to be created with the template service files.


```bash
sls create --template azure-nodejs --path $(whoami)-sample-app
```

### Output

The command above created a new directory, in my case `myho-sample-app`, with the following contents.

```text
├── src
|   ├── handlers
|       ├── goodbye.js
|       ├── hello.js
|   ├── .gitignore
|   ├── host.json
|   ├── package.json
|   ├── README.md
|   ├── serverless.yml
```

### Note

Azure plugin uses a combination of:

- prefix, if provided
- service name
- region
- stage

to generate resource names on deployment. Since resource name have to be unique in Azure, adding `$(whoami)` will append your username to
the service name, thus creating a unique name.

---

## Install Azure Plugin

The previous step created a new directory `<YOUR-USER-NAME>-sample-app` where all the function related code are stored. `cd` into that directory

Run

```bash
npm install
```

--- 

## Testing locally

> You can skip this section if you do not want to test your functions locally before deploy.

The sample app created from template contains 2 functions: hello and goodbye.  You can test them locally before deploying to Azure.

You'll need to use 2 terminal windows for the following.

### Terminal 1

```bash
sls offline
```

While this process is running, you'll notice that some new files have been added.  These files are necessary for Azure function to operate but will be clean up when the process exit. 

### Terminal 2

```bash
sls invoke local -f hello -d '{"name": "Azure"}'
```

In your terminal window you should see the following response

```bash
$ Serverless: URL for invocation: http://localhost:7071/api/hello?name%3DAzure
$ Serverless: Invoking function hello with GET request
$ Serverless: "Hello Azure"
```

---

## Deploy to Azure

Once you're happy with your code, the next step is to deploy to Azure. 

### Azure subscription

If you don't have an Azure account, get started by [signing up for a free account](https://azure.microsoft.com/en-us/free/), which includes $200 of free credit

### Set up credentials

Before you can deploy, you'll have to set up a `service principal`. 

#### Azure-cli

Make sure you have [azure-cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) installed

#### Log in

```bash
az login
az account list # list all subscriptions
az account set --subscription <SUBSCRIPTION_ID> # choose the one you want
```

#### Generate service principals

Download this [script](https://raw.githubusercontent.com/serverless/serverless-azure-functions/master/scripts/generate-service-principal.sh), run it, and follow the printed instruction.

The script will generate, extract, and write the required credentials to a file that you can then export as environment variables.  

```bash
# Download the file and name it `sp.sh`
curl https://raw.githubusercontent.com/serverless/serverless-azure-functions/master/scripts/generate-service-principal.sh -o sp.sh

# skip this if you're on windows
chmod +x sp.sh

# run the script
./sp.sh
```

### Deploy

Deploying to Azure is as simple as running the following command

```bash
# if you want more logging info, uncomment the next line
# export SLS_DEBUG=*

sls deploy
```

#### Behind the scene

1. The plugin created an arm template that is used to deploy all the dependent resources
   * Resource group
   * App service plan
   * Storage account

1. Once the infrastructure is up and running, the zipped source code is deployed to the function app

```bash
➜ sls deploy
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: hello event: httpTrigger
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: goodbye event: httpTrigger
Serverless: Packaging service...

...

Serverless: -> Deploying ARM template...

...

Serverless: -> ARM deployment complete
Serverless: Deploying serverless functions...
Serverless: Deploying zip file to function app: sls-wus-dev-myho-sample-app
Serverless: -> Deploying service package @ /Users/myho/dev/work/github.com/mydiemho/azure-utils/myho-sample-app/.serverless/myho-sample-app.zip

...

Serverless: Deployed serverless functions:
Serverless: -> goodbye: [GET] sls-wus-dev-myho-sample-app.azurewebsites.net/api/goodbye
Serverless: -> hello: [GET] sls-wus-dev-myho-sample-app.azurewebsites.net/api/hello
```

### Test deployed functions

You can test the deployed functions by going directly to the url, or using the `invoke` command.

```bash
sls invoke -f hello -d '{"name": "Azure"}'
```

---

## Wrap up

Congratulation! You have created and deployed your first Azure function with Serverless.  

---

## Next step

There are a lot more you can do with Serverless than just Http-trigger functions. 

### [API Management](https://docs.microsoft.com/en-us/azure/api-management/)

You can add APIM to your functions by configure the `apim` section in `serverless.yml`.  The generated file already included this, just uncommented the section (line 33-59) and redeploy to give it a try.

1. APIM Configuration

```yaml
# serverless.yml

apim:
  apis:
    - name: v1
      subscriptionRequired: false # if true must provide an api key
      displayName: v1
      description: V1 sample app APIs
      protocols:
        - https
      path: v1
      tags:
        - tag1
        - tag2
      authorization: none
  cors:
    allowCredentials: false
    allowedOrigins:
      - "*"
    allowedMethods:
      - GET
      - POST
      - PUT
      - DELETE
      - PATCH
    allowedHeaders:
      - "*"
    exposeHeaders:
      - "*"
```

1 . Deploy Output


```bash
➜ sls deploy

...

Serverless: Starting APIM service deployment
Serverless: -> Deploying API keys
Serverless: -> Deploying API: v1
Serverless: -> Deploying API Backend: myho-sample-app-backend => https://sls-wus-dev-myho-sample-app.azurewebsites.net/api
Serverless: -> Deploying CORS policy: v1
Serverless: -> Deploying API Operations: sls-wus-dev-797b03-apim
Serverless: --> GET-hello: [GET] https://sls-wus-dev-797b03-apim.azure-api.net/v1/hello
Serverless: --> GET-goodbye: [GET] https://sls-wus-dev-797b03-apim.azure-api.net/v1/goodbye
Serverless: Finished APIM service deployment
```

> You will not be able to use the `invoke` command to test the APIM set up

### Additional Triggers

In addition to http-trigger functions, the following triggers are also supported

1. Storage Blob
1. Storage Queue
1. Timer
1. Service Bus Queue
1. Service Bus Topic
1. EventHubs

For more information, see the [official doc](https://serverless.com/framework/docs/providers/azure/events/)

---

## More hands-on training

If you get this far and want to learn more about serverless on Azure, Microsoft is hosting a free workshop in NYC before [ServerlessConf](https://serverlessconf.io/) on Monday, Oct 7, 2019.  Registration is @ http://aka.ms/nycworkshop

There may or may not be 🍦🍦🍦🍦🍦