The Context
In this demo, I will deploy a simple C# (full .Net framework) Azure functions. I will create the Azure Function App and storage using an Azure Resource Manager (ARM template) and deploy with a method named Zip push or ZipDeploy. All the code, script, a template is available on my Github.
The Azure Functions Code
The Azure Function doesn't have to be special, and it can be any language supported by Azure Functions. Simply to show you everything, here the code of my function.
namespace AzFunctionZipDeploy
{
public static class Function1
{
[FunctionName("GetTopRunner")]
public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
string top = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "top", true) == 0)
.Value;
if (top == null)
{
dynamic data = await req.Content.ReadAsAsync< object>();
top = data?.top;
}
return top == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a number to get your top x runner on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, new { message = $"Hello, here is your Top {top} runners", runners = A.ListOf(int.Parse(top)) });
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}
It's a really simple function that will return a list of
Person
generated on the fly. The list will contain as many person as the number passed in parameter. I'm using the very useful GenFu library, from my buddies: ASP.NET Monsters.The only thing we need to do is to create our compress file (Zip or Rar) that contains everything our project required.
In this case, it's the project file (AzFunction-ZipDeploy.csproj), the function's code (Function1.cs) the host (host.json) and local settings of our function (local.settings.json).
The ARM template
For this demo, we need one Azure Function App. I will use a template that is part of the Azure Quickstart Templates. A quick look to the
azuredeploy.parameters.json
file and we see that the only parameter we really need to set is the name of our application.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"value": "zipdeploydemo"
}
}
}
To be able to ZipDeploy, we need to add one Application Setting to let the Kudu interface we need its help to compile our code. To do that let's open the
azuredeploy.json
and go to the appSettings
section. We need to add a new variable named: SCM_DO_BUILD_DURING_DEPLOYMENT
and set it to true
. After adding the setting it should look like this (see the last one... that's our new one):
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('functionAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~1"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "6.5.0"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": true
}
]
The Deployment Script
Now that all the pieces are ready it's time to put it together one script. In fact, only the two last commands are required; everything else is just stuff to make it easier to re-use it. Check out my previous post 5 Simple Steps to Get a Clean ARM Template, to learn more about the best practices related to ARM template. So let's see that script, it's pretty simple.
# script to Create an Azure Gramophone-PoC Solution
resourceGroupName=$1
resourceGroupLocation=$2
templateFilePath="./arm/azuredeploy.json"
parameterFilePath="./arm/azuredeploy.parameters.json"
dateToken=`date '+%Y%m%d%H%M'`
deploymentName="FrankDemo"$dateToken
# az login
# You can select a specific subscription if you do not want to use the default
# az account set -s SUBSCRIPTION_ID
if !( $(az group exists -g $resourceGroupName) ) then
echo "---> Creating the Resourcegroup: " $resourceGroupName
az group create -g $resourceGroupName -l $resourceGroupLocation
else
echo "---> Resourcegroup:" $resourceGroupName "already exists."
fi
az group deployment create --name $deploymentName --resource-group $resourceGroupName --template-file $templateFilePath --parameters $parameterFilePath --verbose
echo "---> Deploying Function Code"
az functionapp deployment source config-zip -g $resourceGroupName -n zipdeploydemo --src "./zip/AzFunction-ZipDeploy.zip"
echo "---> done <--- code="">--->
The only "new" thing is the last command
functionapp deployment source config-zip
. That where we specify to the Azure Function App to look to --src
to get our source. Because I'm running it locally, the path is pointing to a local folder. However, you could execute this command also in the CloudShell, and that would become a URI... to an Azure Blob Storage by example.Deploy and Test
If you didn't notice yet, I did my script in bash and Azure CLI. That because I want my script to be compatible with all platforms. Of course, you could have done it in PowerShell or anything else that would call the REST API.
To deploy, just execute the script passing the ResourceGroup name, and its location.
./Deploy-AZ-Gramophone.sh cloud5mins eastus
To get to Function URL, go to the Azure portal (portal.azure.com) and click on the Function App that we just deploy. Click on the function
GetTopRunner
in this case, and click on the </> Getfunction URL button.Use that URL in postman and pass another parameter
top
to see we the deployment ws successful.In Video Please
If you prefer, I also have a video version of this post.
~Enjoy!