United Kingdom: +44 (0)208 088 8978

Pulumi.FSharp.Extensions

Matt discusses the Pulumi.FSharp.Extensions libraries, which provide some more F#-friendly ways of working with Pulumi.

In this post, we're going to take a look at the Pulumi.FSharp.Extensions libraries maintained by Stefano d'Antonio and contributors. I'll start with some background information, then show some code and its results.

Infrastructure as Code

Infrastructure as Code (IaC) is about managing IT infrastructure through version-controlled configuration files and code. By managing it this way, teams can benefit from software practices like code review, and automation enabling easy consistency between test and production environments.

If you want more background, check out IBM's post on IaC.

Pulumi

Pulumi is a popular open-source infrastructure as code tool. It has SDKs for many different programming languages, and enables targeting many different environments, such as Microsoft Azure, Amazon Web Services and Google Cloud Platform.

Aside: Pulumi vs. Farmer

If you're a regular reader of our blog, you're probably aware that we use and maintain Farmer, a key component of SAFE Stack. You might be wondering what the differences are. Luckily for me, Mikhail Shilkov wrote an excellent post a few years ago comparing them. Even better, Mikhail works at Pulumi, so you know his information's good!

I'll let you check out that post if you want to explore the differences in more depth, but the main things I want to highlight are:

  • Pulumi targets many languages and environments; Farmer focuses on F# and Azure.
  • Farmer helps you declare what you want and lets Azure Resource Manager take care of deployment; Pulumi focuses more on orchestration, giving you more control but making you work more for it.

As shown in the Pulumi .NET SDK docs, once you've installed Pulumi and .NET, you can run pulumi new azure-fsharp to create a starter project. It includes code that creates resources via object constructor:

let storageAccount =
    StorageAccount("sa",
        StorageAccountArgs
            (ResourceGroupName = resourceGroup.Name,
             Sku = input (SkuArgs(Name = SkuName.Standard_LRS)),
             Kind = Kind.StorageV2))

Pulumi.FSharp.Extensions

Now that we know a little bit about IaC and Pulumi, we can talk about Pulumi.FSharp.Extensions. As the GitHub repo's description makes clear, the project is about providing computation expressions to reduce boilerplate when working with Pulumi from F#.

To use it, you first need to add the appropriate package (Pulumi.FSharp.AzureNative in this case). Once you've added it and opened the required namespaces, you can declare your resources using computation expressions, which feels a bit more natural that object constructors in F# code:

open Pulumi.FSharp.AzureNative.Storage
open Pulumi.FSharp.AzureNative.Storage.Inputs

...

let storage = storageAccount {
    resourceGroup rg.Name
    location rg.Location
    name "samattpulumi"
    sku { name "Standard_LRS" }
    kind Kind.StorageV2
}

And, after running pulumi up here's what you get in Azure:

Resource group overview in Azure Portal showing the declared storage account

One thing that I found pretty weird about Pulumi is that I didn't build up a collection of resources to deploy that were passed to some deploy function. It just seems to keep track of that itself, as if by magic, in the background. Presumably Pulumi's object constructors have a side effect of registering them in some place that Pulumi keeps track of, to diff against the existing state when deploying. It's interesting, but not to my tastes; I prefer to be more explicit.

Wrap up

As we've seen, Pulumi and Pulumi.FSharp.Extensions make it easy to declare infrastructure in F# code and deploy it. Farmer's great, but if you need to go beyond what it can offer (for example because you're targeting a non-Azure cloud provider), consider giving them a try. A quick note before you do though: the project is licensed under GPL-2.0. Make sure that the license terms are acceptable for your use case.

Thanks Stefano and contributors for providing us with a more F#-friendly way of interacting with Pulumi!