iwr -useb get.scoop.sh | iex
Then
scoop install nodejs-lts
scoop install azure-cli
scoop install azure-functions-core-tools
scoop install openssl
scoop install git
scoop install gow
Install HomeBrew
brew update && brew install azure-cli
brew tap azure/functions
brew install azure-functions-core-tools@3
az login
az account list-locations -o table
az account list --query "[?name=='Microsoft Partner Network'].tenantId" -o tsv
az account set --subscription "Microsoft Partner Network"
- Storage account name must be [a-z][0-9]{3..24}
- az functionapp --name the must be globally unique
- func azure functionapp publish must be in the directory in which the code exists (LocalFunctionProj in this example)
az login
az account set --subscription "Microsoft Partner Network"
az storage account list -o table
az group create --name mtiexample000rg --location westeurope
az storage account create --name mtiexample000sa --resource-group mtiexample000rg --location westeurope --kind StorageV2 --sku Standard_LRS
az storage container create --auth-mode login --account-name mtiexample000sa --name mtiexample000sc
az functionapp plan create --name mtiexample000sp --resource-group mtiexample000rg --location westeurope --sku B1
az functionapp create --runtime node --runtime-version 10 --functions-version 2 --resource-group mtiexample000rg --storage-account mtiexample000sa --name mtiexample000sp --name mti-example --plan mtiexample000sp
func init mti --javascript
cd mti
func new --name mti-example --template "HTTP trigger"
The func new command also creates sub-directory mti-example
- index.json (This is the implementation of the function)
- function.json (this contains the binding of the function to services and triggers)
Inside the mti-example directory execute
func start
This will confirm that your code is correctly configure
curl -l http://localhost:7071/api/mti-example?name=test
This should return as before but also commit the output to a message queue
Having demonstrated this working you can Ctrl-C the window with the func Start executing and then you can publish the function to Azure
the --force on the publish appears to be required.. It appears to be an issue with runtime environment versioning
func azure functionapp publish mti-example --force --javascript
This will produce output like
Getting site publishing info...
Creating archive for current directory...
Uploading 1.31 KB [###############################################################################]
Upload completed successfully.
Deployment completed successfully.
Syncing triggers...
Functions in mti-example:
mti-example - [httpTrigger]
Invoke url: https://mti-example.azurewebsites.net/api/mti-example?
code=Aj0/VfBBRLteG6VkL8nCaMkzRK8mrBUVjxsoBTdwdqCV34m9bm7nEw==
Remember that the code= parameter is the key to access the function so its unique to deployment
curl -l "https://mti-example.azurewebsites.net/api/mti-example?\
code=Aj0/VfBBRLteG6VkL8nCaMkzRK8mrBUVjxsoBTdwdqCV34m9bm7nEw==&name=fred"
Produces
Hello, fred. This HTTP triggered function executed successfully.
and
curl -l "https://mti-example.azurewebsites.net/api/mti-example? \
code=Aj0/VfBBRLteG6VkL8nCaMkzRK8mrBUVjxsoBTdwdqCV34m9bm7nEw=="
Produces
This HTTP triggered function executed successfully.
Pass a name in the query string or in the request body for a personalized response.
It is also possible to directly post JSON files
curl -X POST -H "Content-Type: application/json" \
-d "{\"name\": \"edmund\"}" \
http://localhost:7071/api/mti-example
Remeber that the quotes matter.
az functionapp list -o table
az functionapp show --resource-group mtiexample000rg --name mti-example -o table
func azure functionapp list-functions mti-example --show-keys
func azure functionapp logstream mti-example --browser
func azure functionapp fetch-app-settings mti-example
in the mti-example\function.json file change it to look like this
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "outputBlob",
"direction": "out",
"type": "blob",
"path": "mtiexample000sc/{rand-guid}",
"connection": "AzureWebJobsStorage"
}
]
}
- outputBlob is the JavaScript Function into which data is written
- mtiexample000sc is the azure Storage Blob Container into which the data is stored. {rand-guid} is a guid to create the filename
- AzureWebJobsStorage is the connection string
in the mti-example\index.js file change it to look like this
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const name = (req.query.name || (req.body && req.body.name));
const responseMessage = name
? "Hello, " + name + ". This HTTP triggered function executed successfully."
: "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";
context.bindings.outputBlob = req.body
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}
- the req.body gets placed into context.bindings.outputBlob
func azure functionapp publish mti-example
A new URL will be given to use the service in Azure.
func azure functionapp list-functions mti-example --show-keys
Gives us the URL to access the function
az storage container list --account-name mtiexample000sa -o table
Gives us a list of the Storage Containers
We can test the function with
curl -X POST -H "Content-Type: application/json" -d "{\"name\": \"edmund\"}" https://mti-example.azurewebsites.net/api/mti-example
az storage blob list --account-name mtiexample000sa --container-name mtiexample000sc --auth-mode login -o table
Provides a list of the blobs in the container
az storage blob download --account-name mtiexample000sa --container-name mtiexample000sc --auth-mode login -n 53c89099-589d-4626-99c2-4d24961110c2 -f t.out
downloads a blob and places it in a file t.out
az group list -o table
az group delete --resource-group mtiexample000rg
Stuff learnt along the way
This is not in any sensible order
- Resource group is used to agregate resources
- Storage Account provisions a particularly availability of Storage
- CosmosDB Account is the principal which looks after the CosmosDB service
- SQLDB is created by the CosmosDB Account, in a particularly ResourceGroup
- SQL Container is use to partition the SQLDB accross multiple instances of the CosmosDB service (for scale). The partition key must be reflected as a column in the database
az cosmosdb create --resource-group mtiexample000rg --name "mtiexample000cdba" --enable-free-tier
az cosmosdb sql database create -a mtiexample000cdba -g mtiexample000rg -n mtiexample000db
az cosmosdb sql container create -a mtiexample000cdba -g mtiexample000rg -d mtiexample000db \
--name mtiexample000dbc -p "/name"
You can confirm the connection strings
az cosmosdb keys list -n mtiexample000cdba -g mtiexample000rg
az cosmosdb keys list -n mtiexample000cdba -g mtiexample000rg --type connection-strings
You can confirm the database
az cosmosdb sql database show -a mtiexample000cdba -g mtiexample000rg -n mtiexample000db
az cosmosdb sql container show -a mtiexample000cdba -g mtiexample000rg -d mtiexample000db -n mtiexample000dbc
Examine the local.settings.json file key AzureWebJobsStorage contains the storage account connection string. Put this into an environmental variable as you'll use this lots
set AZURE_STORAGE_CONNECTION_STRING= \
"DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=mtiexample000sa;\
AccountKey=XH34KYJIQJINA5wFWN1AyAqhkM9jVy5IkS33CbKYv29p9XUNYvQVek52OTwNQWLGBVWvnR+FmYgnTn1l0LwIEg=="
az storage queue list
Should work and show you have no queues currently created for that storage connection string.
az storage queue create --name outqueue
az storage message get --queue-name outqueue -o tsv --query [].{Message:content}
returns the parameter base64 encoded
az storage message get --queue-name outqueue -o tsv --query [].{Message:content} | openssl base64 -d