Skip to content

Commit 753631a

Browse files
author
jim spring
committed
function tutorials, information about settings and keyvault (as well as example)
1 parent 9f46e80 commit 753631a

File tree

13 files changed

+913
-0
lines changed

13 files changed

+913
-0
lines changed

tutorial/functions/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Azure Functions Tutorials
2+
3+
Much of the Active Learning pipeline relies upon Python. One implementation of the
4+
pipeline makes use of Azure Functions with the Python language. This set of documents
5+
and tutorial show how to setup (and script) a Azure Function environment, inject
6+
variables within the environment within which the functions run, how to access
7+
secrets within Azure Keyvault.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Working with Python and Azure Functions
2+
3+
This project has scripts, hints, and tricks for working with Python and Azure
4+
Functions. The project is broken down into multiple areas:
5+
6+
- [Setting up one's environment](initial/README.md)
7+
- [Using Keyvault for Secrets](security/keyvault/README.md)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
## Deploying a Python Azure Function application
2+
3+
Assuming one has gone through the [instructions to setup the environemnt](../setup/initial/README.md)
4+
for developing a Python based Azure Function, the skeleton applicaiton created with an `HttpTrigger`
5+
app can be deployed.
6+
7+
At it's simplest, deploying the function is to uses the Azure Functions CLI tools that were
8+
previously installed. The command is `func azure functionapp publish $AZURE_FUNC_APP_NAME --force`.
9+
The below assumes that one has activated the Python virtual environment.
10+
11+
```bash
12+
export AZURE_FUNC_APP_NAME=jmsazfunapp1
13+
$ func azure functionapp publish $AZURE_FUNC_APP_NAME --force
14+
Getting site publishing info...
15+
pip download -r /home/jims/code/src/github/jmspring/azure_python_functions/scratch/azfuncprj/testprj1/requirements.txt --dest /tmp/azureworkerda2e6auj
16+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 grpcio_tools==1.14.2
17+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 six==1.11.0
18+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 azure_functions==1.0.0a4
19+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 grpcio==1.14.2
20+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 setuptools==40.4.3
21+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 protobuf==3.6.1
22+
pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /tmp/azureworkergtpit9y9 azure_functions_worker==1.0.0a4
23+
24+
Preparing archive...
25+
Uploading content...
26+
Upload completed successfully.
27+
Deployment completed successfully.
28+
Removing 'WEBSITE_CONTENTSHARE' from 'jmsazfunapp1'
29+
Removing 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' from 'jmsazfunapp1'
30+
Syncing triggers...
31+
```
32+
33+
Note the above uses the flag `--force` this is simply because the initial creation of the Azure
34+
Function application set things up such that the Application use Azure Files for publishing
35+
and deployment. Without the `--force`, the result would look something like:
36+
37+
```bash
38+
$ func azure functionapp publish $AZURE_FUNC_APP_NAME
39+
Your app is configured with Azure Files for editing from Azure Portal.
40+
To force publish use --force. This will remove Azure Files from your app.
41+
```
42+
43+
This may be a Preview thing or it may be the default. As things mature, the above directions will
44+
be cleaned up.
45+
46+
Hitting the default web serice, using curl, the result is as follows:
47+
48+
```bash
49+
$ curl https://jmsazfunapp1.azurewebsites.net/api/httpfunc1?name=foo
50+
Hello foo!
51+
```
52+
53+
At this point, you have a Python function deployed to Azure Functions.
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
## Setting up a function environment
2+
3+
In the following document, we explore using the scripts in this folder to walk through
4+
setting up an environment for and deploying a python funciton into Azure Functions.
5+
Python for Azure Functions is in preview at the moment, so, things may change. The
6+
following prerequisites are assumed:
7+
8+
- You have an active Azure account
9+
- The prerequisites for working with Azure Functions have been installed, per [here](https://github.com/Azure/Azure-Functions/wiki/Azure-Functions-on-Linux-Preview)
10+
- Per prerequisites, the scripts below assume one has created a resource group
11+
12+
### Python for Azure Functions in practice
13+
14+
One thing most of the documents around Python for Azure Functions do not call out is
15+
the fact that function development requires a virtual environment to be setup. The
16+
script `setup_environment.sh` does just that. The syntax is:
17+
18+
```bash
19+
$ ./setup_environment.sh <path to virtual environment>
20+
```
21+
22+
For purposes of this write up will use environment variables to illustrate the process,
23+
we will first assume our virtual environment is in `~/python/venv/azfuncprj`, so the
24+
above becomes:
25+
26+
```bash
27+
$ export VIRTUAL_ENV_DIR=~/python/venv/azfuncprj
28+
$ ./setup_environment.sh $VIRTUAL_ENV_DIR
29+
```
30+
31+
Running the above we get:
32+
33+
```bash
34+
$ export VIRTUAL_ENV_DIR=~/python/venv/azfuncprj
35+
$ ./setup/setup_environment.sh $VIRTUAL_ENV_DIR
36+
Running virtualenv with interpreter /usr/bin/python3.6
37+
Using base prefix '/usr'
38+
New python executable in /home/jims/python/venv/azfuncprj/bin/python3.6
39+
Also creating executable in /home/jims/python/venv/azfuncprj/bin/python
40+
Installing setuptools, pip, wheel...done.
41+
To activate the virtualenv run: source python/venv/azfuncprj/bin/activate
42+
```
43+
44+
### Creating the function project
45+
46+
The next step in working with Python for Azure Functions is to create a project and a
47+
function within that project. This is handled by the script `create_function_project.sh`.
48+
For this funciton you will need to know:
49+
50+
- The virtual environment path (created above), `VIRTUAL_ENV_DIR`
51+
- The directory where you want the project to live, this will be defined with the
52+
environment variable `PYFUNC_PROJECT_DIR`
53+
- The project name, defined with the environment variable `PYFUNC_PROJECT_NAME`
54+
- The name of the function within the project, `PYFUNC_FUNCTION_NAME`
55+
- The type of function to create/function template. In this case we will use an
56+
HttpTrigger app, so `PYFUNC_FUNCTION_TYPE=HttpTrigger`
57+
58+
Invoking the `create_function_project.sh` script:
59+
60+
```bash
61+
$ export VIRTUAL_ENV_DIR=~/python/venv/azfuncprj
62+
$ export PYFUNC_PROJECT_DIR=~/python/azfuncprj
63+
$ export PYFUNC_PROJECT_NAME=testprj
64+
$ export PYFUNC_FUNCTION_NAME=testhttpfunc
65+
$ export PYFUNC_FUNCTION_TYPE=HttpTrigger
66+
$ ./create_function_project.sh $VIRTUAL_ENV_DIR $PYFUNC_PROJECT_DIR $PYFUNC_PROJECT_NAME $PYFUNC_FUNCTION_NAME $PYFUNC_FUNCTION_TYPE
67+
Installing wheel package
68+
Installing azure-functions==1.0.0a4 package
69+
Installing azure-functions-worker==1.0.0a4 package
70+
Running pip freeze
71+
Writing .gitignore
72+
Writing host.json
73+
Writing local.settings.json
74+
Writing /home/jims/python/azfuncprj/testprj/.vscode/extensions.json
75+
Select a language: Select a template: HttpTrigger
76+
Function name: [HttpTriggerPython] Writing /home/jims/python/azfuncprj/azfuncprj/testprj/httpfunc1/sample.dat
77+
Writing /home/jims/python/azfuncprj/testprj/httpfunc1/__init__.py
78+
Writing /home/jims/python/azfuncprj/testprj/httpfunc1/function.json
79+
The function "testhttpfunc" was created successfully from the "HttpTrigger" template.
80+
Function httpfunc1 is created within project testprj1
81+
In order to operate with the function:
82+
- Activate the virtual environment
83+
- Change to ~/python/azfuncprj/testprj
84+
```
85+
86+
### Create a Azure Function Application to host your Python function
87+
88+
Per this [document](https://github.com/Azure/azure-functions-python-worker/wiki/Create-your-first-Python-function)
89+
one can run functions locally. If one wants to actually host them in Azure, then one
90+
needs to create an Azure Function application to do so. Outside of the prerequisites mentioned
91+
above, this is the first piece of this setup that actually interacts with Azure itself.
92+
93+
The script `create_function_app.sh` sets this up. It requires that a `resource group` has been
94+
previously created. For purposes of Python support in Azure Functions, the resource group (during
95+
preview) must be created in one of the following regions:
96+
97+
- West US
98+
- East US
99+
- West Europe
100+
- East Asia
101+
102+
The example below will assume the `resource group` will be named `jmsazfunc1rg` and located
103+
in `West US`. The Azure CLI command to do so is:
104+
105+
```bash
106+
export RESOURCE_GROUP_NAME=jmsazfunc1rg
107+
export RESOURCE_GROUP_LOCATION=westus
108+
$ az group create --name $RESOURCE_GROUP_NAME --location $RESOURCE_GROUP_LOCATION
109+
{
110+
"id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/jmsazfunc1rg",
111+
"location": "westus",
112+
"managedBy": null,
113+
"name": "jmsazfunc1rg",
114+
"properties": {
115+
"provisioningState": "Succeeded"
116+
},
117+
"tags": null
118+
}
119+
```
120+
121+
To create the Azure Function application, the following need to be defined:
122+
123+
- Resource Group --> `export RESOURCE_GROUP_NAME=jmsazfunc1rg`
124+
- Resource Group/Function Location --> `export RESOURCE_GROUP_LOCATION=westus`
125+
- Storage Account Name --> `export STORAGE_ACCOUNT_NAME=jmsazfunc1sa`
126+
- Azure Function Applicaiton Name --> `export AZURE_FUNC_APP_NAME=jmsazfunapp1`
127+
128+
The storage account, `jmsazfun1sa`, is needed as that is the locaiton that the Azure Function
129+
state is stored. The name of the applciaiton, for this example is `jmsazfunapp1`. Resource
130+
group name and location were defined previously.
131+
132+
Executing the script:
133+
134+
```bash
135+
$ export RESOURCE_GROUP_NAME=jmsazfunc1rg
136+
$ export RESOURCE_GROUP_LOCATION=westus
137+
$ export STORAGE_ACCOUNT_NAME=jmsazfunc1sa
138+
$ export AZURE_FUNC_APP_NAME=jmsazfunapp1
139+
$ ./create_function_app.sh $RESOURCE_GROUP_NAME $RESOURCE_GROUP_LOCATION $STORAGE_ACCOUNT_NAME $AZURE_FUNC_APP_NAME
140+
{
141+
"id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/jmsazfunc1rg",
142+
"location": "westus",
143+
"managedBy": null,
144+
"name": "jmsazfunc1rg",
145+
"properties": {
146+
"provisioningState": "Succeeded"
147+
},
148+
"tags": null
149+
}
150+
{
151+
"accessTier": null,
152+
"creationTime": "2018-10-08T18:52:49.001675+00:00",
153+
"customDomain": null,
154+
"enableHttpsTrafficOnly": false,
155+
"encryption": {
156+
"keySource": "Microsoft.Storage",
157+
"keyVaultProperties": null,
158+
"services": {
159+
"blob": {
160+
"enabled": true,
161+
"lastEnabledTime": "2018-10-08T18:52:49.118545+00:00"
162+
},
163+
"file": {
164+
"enabled": true,
165+
"lastEnabledTime": "2018-10-08T18:52:49.118545+00:00"
166+
},
167+
"queue": null,
168+
"table": null
169+
}
170+
},
171+
"id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/jmsazfunc1rg/providers/Microsoft.Storage/storageAccounts/jmsazfunc1sa",
172+
"identity": null,
173+
"isHnsEnabled": null,
174+
"kind": "Storage",
175+
"lastGeoFailoverTime": null,
176+
"location": "westus",
177+
"name": "jmsazfunc1sa",
178+
"networkRuleSet": {
179+
"bypass": "AzureServices",
180+
"defaultAction": "Allow",
181+
"ipRules": [],
182+
"virtualNetworkRules": []
183+
},
184+
"primaryEndpoints": {
185+
"blob": "https://jmsazfunc1sa.blob.core.windows.net/",
186+
"dfs": null,
187+
"file": "https://jmsazfunc1sa.file.core.windows.net/",
188+
"queue": "https://jmsazfunc1sa.queue.core.windows.net/",
189+
"table": "https://jmsazfunc1sa.table.core.windows.net/",
190+
"web": null
191+
},
192+
"primaryLocation": "westus",
193+
"provisioningState": "Succeeded",
194+
"resourceGroup": "jmsazfunc1rg",
195+
"secondaryEndpoints": null,
196+
"secondaryLocation": null,
197+
"sku": {
198+
"capabilities": null,
199+
"kind": null,
200+
"locations": null,
201+
"name": "Standard_LRS",
202+
"resourceType": null,
203+
"restrictions": null,
204+
"tier": "Standard"
205+
},
206+
"statusOfPrimary": "available",
207+
"statusOfSecondary": null,
208+
"tags": {},
209+
"type": "Microsoft.Storage/storageAccounts"
210+
}
211+
Your Linux, cosumption plan, function app 'jmsazfunapp1' has been successfully created but is not active until content is published usingAzure Portal or the Functions Core Tools.
212+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
# This script sets up the azure function space that will host the Python
4+
# functions developed.
5+
#
6+
# To set up the function, you need to do the following:
7+
#
8+
# - create a resource group
9+
# - create a storage account
10+
# - create the function app
11+
12+
# Needed:
13+
# - resource group name
14+
# - location
15+
# - storage account name
16+
# - application name
17+
18+
# Check inputs
19+
if [ "$#" -ne "4" ]; then
20+
echo "Usage: create_function_app.sh <resource group name> <resource group location> <storage account name> <application name>"
21+
exit 1
22+
fi
23+
24+
RG_NAME=$1
25+
LOCATION=$2
26+
SA_NAME=$3
27+
APP_NAME=$4
28+
29+
# Create the resource group
30+
az group create --name $RG_NAME --location $LOCATION
31+
if [ "$?" -ne 0 ]; then
32+
echo "Unable to create resource group."
33+
exit 1
34+
fi
35+
36+
# Create a storage account in the resource group for the functions to store
37+
# their state / metadata
38+
az storage account create --name $SA_NAME --location $LOCATION --resource-group $RG_NAME --sku Standard_LRS
39+
if [ "$?" -ne 0 ]; then
40+
echo "Unable to create storage account."
41+
exit 1
42+
fi
43+
44+
# Create the functions app. This is the environment the functions will fu
45+
az functionapp createpreviewapp --resource-group $RG_NAME --consumption-plan-location $LOCATION --name $APP_NAME --storage-account $SA_NAME --runtime python --is-linux

0 commit comments

Comments
 (0)