Deploy Azure Functions using Powershell and FTP

Deploying an Azure Function to Azure to a large extent resembles deploying an API App. See Link:  Deploy Api App. The only problem is, we can’t create a deployment package for Azure Functions via Visual Studio. Instead, go to the Azure Portal. Open the relevant Function container and click Download App Content.

You will now get a zip file with subfolders per Azure Function. Each Azure Function folder contains a csx file with the Azure Function code and a json file for configuration settings. Also note we can define parameters at the Function Container level. An example is a queue trigger function where the address from the Logic App is taken from the settings. Below you will see the ps1 file and an example psx file.

param (
[parameter(Mandatory = $true)][string] $paramFileName

Import-Module AzureRM.Resources

Write-Host “Login to Azure” –fore gray;

# $PSScriptRoot is null when you run from Powershell ISE
# Run from cmd file
$baseDir = $PSScriptRoot
$pos = $basedir.LastIndexOf(‘\’)
$baseDirParam = $baseDir.Substring(0,$pos)
$dirParam = $baseDirParam + “\AAA-DeployResources\” + $paramFileName
$dirUtils = $baseDirParam + “\AAA-DeployResources\Utils.psm1”
Write-Host “BaseDir: ” $baseDir –fore gray;
Write-Host “Dir ParameterFile: ” $dirParam –fore gray;
Write-Host “Dir UtilsFile: ” $dirUtils –fore gray;

#region Load Parameter file
. $dirParam

#region Import Utils file
Import-Module “$dirUtils”

Write-Host “Functions Container: ” $nameFunctionsContainer –fore gray
$result = UploadToFTP -webAppName $nameFunctionsContainer -rg $resourcegroupFunctions -sourceDir $sourceDirTriggerFunctions

if ($result=’true’)
Write-Host $(Get-Date).ToString(“yyyyMMdd_HHmss”) ” Add Azure Function Container ” $nameFunctionsContainer ” to Azure succeeded” –fore green
Write-Host $(Get-Date).ToString(“yyyyMMdd_HHmss”) ” Add Azure Function Container ” $nameFunctionsContainer ” to Azure failed” –fore red

# Add ApplicationSettings
$appSettingsTriggerFunctions = @{“AzureWebJobsDashboard”=$azureWebJobsDashboard;”AzureWebJobsStorage”=$azureWebJobsStorage;”FUNCTIONS_EXTENSION_VERSION”=$FUNCTIONS_EXTENSION_VERSION; `
“WEBSITE_NODE_DEFAULT_VERSION”=$WEBSITE_NODE_DEFAULT_VERSION_FUNC;”ahakstorage_STORAGE”=$storageConnectionString;”ProcessAGAEventsURI”=$ProcessAGAEventsURI; `
“ProcessAGABeoordelingURI”=$ProcessAGABeoordelingURI;”ProcessAGPURI”=$ProcessAGPURI;”ProcessAGPBeoordelingURI”=$ProcessAGPBeoordelingURI;”ProcessAnnuleringenURI”=$ProcessAnnuleringenURI; `
“ProcessAnnuleringGereedURI”=$ProcessAnnuleringGereedURI;”ProcessBijstellingURI”=$ProcessBijstellingURI;”ProcessOpdrachtenURI”=$ProcessOpdrachtenURI;”ProcessOpdrachtInfoURI”=$ProcessOpdrachtInfoURI; `
Set-AzureRmWebApp -Name $nameFunctionsContainer -AppSettings $appSettingsTriggerFunctions -ResourceGroupName $resourcegroupFunctions

using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text;

private static string logicAppUri = Environment.GetEnvironmentVariable(“ProcessAnnuleringenURI”);

public static void Run(string myQueueItem, TraceWriter log)
log.Info($”C# Queue trigger function processed: {myQueueItem}”);
using (var client = new HttpClient())
var response = client.PostAsync(logicAppUri, new StringContent(myQueueItem, Encoding.UTF8, “application/json”)).Result;

Again we upload the files using FTP. We can use the same FTP script we saw when deploying the API App. There’s one gotcha. If we deploy the Azure Function this way and we go the Integrate tab, we will note that the storage account connection name (in case of a queue trigger) is not selected. We have to select this setting manually.