Azure Functions development on macOS [English]

As cloud development continues to evolve, more developers are embracing cross-platform solutions. While Azure Functions traditionally felt more at home in Windows environments, macOS has become a first-class citizen for serverless development. Whether you’re a Mac user diving into Azure or a Windows developer switching platforms, this guide will get you up and running with Azure Functions on macOS.

The beauty of serverless computing lies in its platform agnostic nature. With Azure Functions, you can write code in PowerShell, Python, C#, Java, and JavaScript, and deploy it without worrying about the underlying infrastructure. But what about the development experience on macOS? Let’s explore how to set up a productive Azure Functions development environment on your Mac.

Prerequisites: Setting up your Mac

Before we dive into Azure Functions, we need to ensure our environment is properly configured. The good news is that Microsoft has invested heavily in cross-platform tooling, making the experience quite seamless.

First, let’s install the essential tools:

Azure CLI The Azure CLI is your gateway to managing Azure resources from the command line. Install it using Homebrew:

brew install azure-cli

PowerShell Yes, PowerShell runs natively on macOS! (since 2018 but don’t mind):

brew install --cask powershell

Azure Functions Core Tools This toolkit provides the runtime and templates for creating, debugging, and deploying Azure Functions:

brew tap azure/functions
brew install azure-functions-core-tools@4

Visual Studio Code While not mandatory, VS Code provides an excellent development experience for Azure Functions:

brew install --cask visual-studio-code

After installation, add the Azure Functions extension for VS Code to enhance your development workflow.

Creating your first PowerShell Azure Function on macOS

Now that we have our tools ready, let’s create our first Azure Function. We’ll use PowerShell as our runtime since it’s particularly powerful for automation and Azure management tasks.

First, let’s authenticate with Azure:

# Connect to Azure
Connect-AzAccount

# List available subscriptions
Get-AzSubscription

# Select your target subscription
Select-AzSubscription -SubscriptionId "your-subscription-id"

Create a new function app locally:

# Create a new directory for our function and move into it
mkdir PoShFunction && cd $_

# Initialize a new function app with PowerShell runtime
func init --worker-runtime powershell

This command creates the basic structure for a PowerShell-based function app, including the host.json, local.settings.json, and other configuration files.

Initialize PowerShell Function App

Let’s create our first HTTP-triggered function:

func new --name HttpTriggerDemo --template "HTTP trigger"

This generates a new folder called HttpTriggerDemo with the function code. Let’s examine and modify the generated PowerShell script:

# HttpTriggerDemo/run.ps1
using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request on macOS."

# Interact with query parameters or the request body
$name = $Request.Query.Name
if (-not $name) {
    $name = $Request.Body.Name
}

$body = "Hello, $name! This Azure Function was developed on macOS and is powered by PowerShell."

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})

Testing and debugging locally

One of the great advantages of the Azure Functions Core Tools is the ability to run and test functions locally. This works seamlessly on macOS:

# Start the function runtime locally
func start

You’ll see output similar to this:

Azure Functions Core Tools
Core Tools Version:       4.0.5030 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.21.3.20404

Functions:
        HttpTriggerDemo: [GET,POST] http://localhost:7071/api/HttpTriggerDemo

Test your function using curl or your browser:

curl "http://localhost:7071/api/HttpTriggerDemo?name=MacOS"

Advanced PowerShell scenarios

Let’s create a more practical example - a function that manages Azure resources using PowerShell. This showcases the real power of combining PowerShell with Azure Functions on macOS:

Create a new timer-triggered function:

func new --name ResourceMonitor --template "Timer trigger"

Here’s a more advanced PowerShell function that monitors resource group usage:

# ResourceMonitor/run.ps1
# Input bindings are passed in via param block.
param($Timer)

# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()

# Write an information log with the current time.
Write-Host "PowerShell timer trigger function started at: $currentUTCtime"

try {
    # Connect using Managed Identity (when deployed) or local credentials
    if ($env:MSI_ENDPOINT) {
        Connect-AzAccount -Identity
    } else {
        # For local development, use stored credentials
        Write-Host "Using local Azure credentials for development"
    }

    # Get all resource groups
    $resourceGroups = Get-AzResourceGroup
    
    $report = @()
    
    foreach ($rg in $resourceGroups) {
        # Get resources in each resource group
        $resources = Get-AzResource -ResourceGroupName $rg.ResourceGroupName
        
        $rgInfo = [PSCustomObject]@{
            ResourceGroupName = $rg.ResourceGroupName
            Location = $rg.Location
            ResourceCount = $resources.Count
            CreatedTime = $rg.Tags.CreatedTime
            LastChecked = $currentUTCtime
        }
        
        $report += $rgInfo
    }
    
    # Log the summary
    Write-Host "Resource Group Summary:"
    $report | ForEach-Object {
        Write-Host "  - $($_.ResourceGroupName): $($_.ResourceCount) resources in $($_.Location)"
    }
    
    # In a real scenario, you might want to:
    # - Send this data to Azure Monitor
    # - Store it in a database
    # - Send alerts for specific conditions
    
} catch {
    Write-Error "Error monitoring resources: $($_.Exception.Message)"
    throw
}

Write-Host "PowerShell timer trigger function completed at: $currentUTCtime"

Deployment from macOS

Deploying your Azure Function from macOS is straightforward. First, create the necessary Azure resources using PowerShell:

# Variables for our deployment
$resourceGroupName = "rg-functions-macos-demo"
$functionAppName = "func-macos-demo-$(Get-Random)"
$location = "East US"
$storageAccountName = "stamacosdemfunc$(Get-Random)"

# Create resource group
New-AzResourceGroup -Name $resourceGroupName -Location $location

# Create storage account (required for Azure Functions)
$storageParams = @{
    ResourceGroupName = $resourceGroupName
    Name = $storageAccountName
    Location = $location
    SkuName = "Standard_LRS"
    Kind = "StorageV2"
}
New-AzStorageAccount @storageParams

# Create the function app
$functionParams = @{
    ResourceGroupName = $resourceGroupName
    Name = $functionAppName
    StorageAccountName = $storageAccountName
    Location = $location
    Runtime = "PowerShell"
    RuntimeVersion = "7.2"
    FunctionsVersion = "4"
}
New-AzFunctionApp @functionParams

Deploy your function using the Azure Functions Core Tools:

# Deploy to Azure
func azure functionapp publish $functionAppName

Whether you’re automating infrastructure tasks, building APIs, or creating scheduled jobs, Azure Functions on macOS with PowerShell gives you the flexibility to work in your preferred environment while leveraging the power of Azure’s serverless platform.

Ready to start building? The tools are installed, the examples are tested, and Azure is waiting for your next serverless creation!

Happy scripting!

Comments