Deploying Azure Functions Using Pulumi & .NET
Tags: azure, pulumi, serverless, infrastructureascode
Published: 2020-07-31 13:05:34


In this article you'll learn how to deploy your source code to Azure Functions using just a few lines of C# powered by [Pulumi](https://www.pulumi.com/).

We'll start by creating a regular new Azure Function project, which you can either do from Visual Studio 2019 or using the [func](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#v2) command line tool. The Visual Studio template will already create an HTTP-triggered function as an example, using the `func` cli will require you to call `func new` after creating the project using `func init`.

Implementing, testing and building the Azure Function project is absolutely not affected by using Pulumi for creating Azure resources & deploying your application — this article will focus on the part that comes after you ran `dotnet publish` on your function project.
> Friends don't let friends right-click publish

While Visual Studio offers the option to publish an Azure Function project directly to an existing or newly created Azure Function resource, without requiring you to head to the Azure Portal to create the resources manually, you'll be left with no means to automate the creation of all the required resources and deploy your application. In this article, we'll use Pulumi to implement an automated infrastructure-as-code style approach for resource creation and application deployment.

In addition to your Azure Function project, you'll need a second project for your infrastructure code. This can be a regular .NET Core command line project — you'll just have to add a reference to the [Pulumi.Azure](https://www.nuget.org/packages/Pulumi.Azure) nuget package. But we're getting ahead of ourselves — lets start with some installation requirements.

### What you need to have installed on your system

Since we will be using Pulumi for creating Azure resources and deploying our application, you'll need the Pulumi CLI installed. The [documentation](https://www.pulumi.com/docs/get-started/install/) shows a range of installation options for various operating systems. You can verify if the installation was successful by running `pulumi version`.

Also, you'll need to install the [.NET Core SDK](https://dotnet.microsoft.com/download).

Lastly, installing the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) is required - Pulumi uses it under the hood. After installation, you'll need to run `az login` in order to create the resources in the right target subscription. There are [other ways](https://www.pulumi.com/docs/intro/cloud-providers/azure/setup/) to configure the target subscription for pulumi programs, but this is the one we'll stick with for this article.

With that, you should be ready to go.

### Creating the blank Azure resources using Pulumi

Now, let's continue where we left of — with a completely empty .NET Core command line project, in which you just added a dependency to the Pulumi.Azure nuget:

![Empty .NET Core CLI project with dependency to the Pulumi.Azure nuget](https://dev-to-uploads.s3.amazonaws.com/i/o5dwd5s2okfa52at5o27.png)

The only thing you'll need to add in addition is a `Pulumi.yaml` file next to your `Program.cs`:

{% gist https://gist.github.com/ChristianEder/becf388b3e56c21a63a9cc456137174c %}

Now let's add a stack — stacks are Pulumi's notion of a deployed environment. A stack defines all the required resources, and can be instantiated multiple times in order to create a range of environments. The [documentation](https://www.pulumi.com/docs/intro/concepts/stack/) puts this as
> Every Pulumi program is deployed to a stack. A stack is an isolated, independently configurable instance of a Pulumi program. Stacks are commonly used to denote different phases of development (such as development, staging and production) or feature branches (such as feature-x-dev, jane-feature-x-dev).

Using the .NET SDK, a stack is nothing else than a class creating all the required resources in its constructor. Deploying the stack when running your pulumi program is a one-liner in the `Program.cs file`:

{% gist https://gist.github.com/ChristianEder/961298074cdb55a480d7b23b543edd25 %}

This pulumi program can be run by calling `pulumi up` within the pulumi projects directory and will create the resources defined in the stack:

* A resource group, and within that...

* A consumption based app service plan

* A storage account

* A function app configured to use both the plan and the storage account

Running `pulumi up` will — at least on your first run — ask you for a name for the stack to create. Just choose something that makes sense to you — I chose "dev". The stack name will be reflected in the names of the created resources.

### Deploying your application

Now that you've got a brand new Azure Function App created (it should show up in your [Azure Portal](https://portal.azure.com/)), let's run `dotnet publish` on the function app project (not the pulumi program) and deploy the files created as a build output to the Function App. We'll do this by creating a .zip file as a new blob in our storage account, and then configure the function app to run from that .zip file:

{% gist https://gist.github.com/ChristianEder/8361bc9deb698b3ab4120ef3d6764870 %}

`GetSignedBlobUrl` in the snippet above is a helper function you can find [here](https://gist.github.com/ChristianEder/42f57e27d8b6ab75d299722764704d57).

And that's it — your next call to `pulumi up` will bundle the output of your earlier call to `dotnet publish` into a .zip file, upload it into a new blob, and configure the Function App to use the contents of this blob.

Christian Eder is a Lead Software Architect working for [Zühlke Engineering](https://www.zuehlke.com/) and has a strong background in all things cloud, with a focus on IoT projects. He helps his customers in finding the right solutions, defining suitable architectures and efficient implementation.