Skip to content

Commit ae58676

Browse files
tusharshahrsrshade
andauthored
Added azure native function app in python (#1002)
Added azure native function app in python ``` Type Name Status + pulumi:pulumi:Stack azure-py-functions-dev created + ├─ azure-native:resources:ResourceGroup resourcegroup_functions_py created + ├─ azure-native:web:AppServicePlan consumption-plan created + ├─ azure-native:storage:StorageAccount storageaccount created + └─ azure-native:web:WebApp functionapp created Outputs: consumptionplan : "consumption-plan2e4262cf" endpoint : "https://functionappd8d431c1.azurewebsites.net/api/HelloWithPython" function_app : "functionappd8d431c1" primarystoragekey : "[secret]" resourcegroup : "resourcegroup_functions_pyb8aff58c" storageaccount : "storageaccount6a453652" storageaccountkeys : "[secret]" storageconnectionstring: "[secret]" ``` curl "$(pulumi stack output endpoint)" Hello from Python in Pulumi! You have stood up a serverless function in Azure! --------- Co-authored-by: Richard Shade <richard@pulumi.com>
1 parent beeac20 commit ae58676

File tree

14 files changed

+534
-0
lines changed

14 files changed

+534
-0
lines changed

azure-py-functions/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+
venv/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.pythonPath": "venv/bin/python"
3+
}

azure-py-functions/Pulumi.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: azure-py-functions
2+
runtime:
3+
name: python
4+
options:
5+
virtualenv: venv
6+
description: A minimal Azure Native Function in Python with Pulumi program

azure-py-functions/README.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Deploying Serverless Applications with Azure Functions
2+
3+
You will deploy a Azure Function Apps with HTTP-triggered serverless functions in python
4+
5+
## Running the App
6+
7+
1. Login to Azure CLI (you will be prompted to do this during deployment if you forget this step):
8+
9+
```
10+
$ az login
11+
```
12+
13+
1. Create a new stack:
14+
15+
```
16+
$ pulumi stack init dev
17+
```
18+
19+
20+
1. Create a virtual environment and install python dependencies
21+
22+
### Windows
23+
Run the following command to create a virtual environment
24+
```bash
25+
python -m venv venv
26+
```
27+
28+
Activate the environment:
29+
```bash
30+
venv\Scripts\activate
31+
```
32+
33+
Install dependencies:
34+
```bash
35+
pip3 install -r requirements.txt
36+
```
37+
### Mac and Linux
38+
Run the following command to create a virtual environment
39+
```bash
40+
python3 -m venv venv
41+
```
42+
43+
Activate the environment:
44+
```bash
45+
source venv/bin/activate
46+
```
47+
48+
Install dependencies:
49+
```bash
50+
pip3 install -r requirements.txt
51+
```
52+
53+
At this point, dependencies will be installed into your virtual environment. **If you close your terminal at any time**, you may need to re-activate the environment:
54+
```bash
55+
source venv/bin/activate
56+
```
57+
58+
1. Configure the location to deploy the resources to. The Azure region to deploy to is pre-set to **WestUS** - but you can modify the region you would like to deploy to.
59+
60+
```bash
61+
pulumi config set azure-native:location eastus2
62+
```
63+
64+
[pulumi config set](https://www.pulumi.com/docs/reference/cli/pulumi_config_set/) allows us to pass in [configuration values](https://www.pulumi.com/docs/intro/concepts/config/#setting-and-getting-configuration-values) from the command line.
65+
Feel free to choose any Azure region that supports the services used in these labs ([see this infographic](https://azure.microsoft.com/en-us/global-infrastructure/regions/) for current list of available regions). A list of some of the regions:
66+
67+
```
68+
centralus,eastasia,southeastasia,eastus,eastus2,westus,westus2,northcentralus,southcentralus,
69+
westcentralus,northeurope,westeurope,japaneast,japanwest,brazilsouth,australiasoutheast,australiaeast,
70+
westindia,southindia,centralindia,canadacentral,canadaeast,uksouth,ukwest,koreacentral,koreasouth,
71+
francecentral,southafricanorth,uaenorth,australiacentral,switzerlandnorth,germanywestcentral,
72+
norwayeast,jioindiawest,australiacentral2
73+
```
74+
75+
The command updates and persists the value to the local `Pulumi.dev.yaml` file. You can view or edit this file at any time to effect the configuration of the current stack.
76+
77+
1. Azure Python Function Zip file
78+
The applications settings configure the app to run on Python3 deploy the specified zip file to the Function App. The app will download the specified file, extract the code from it, discover the functions, and run them. We’ve prepared this [zip](https://github.com/tusharshahrs/demo/blob/main/content/lab/pulumi/azure-native/python/app/HelloWithPython.zip) file for you to get started faster, you can find its code [here](https://github.com/tusharshahrs/demo/tree/main/content/lab/pulumi/azure-native/python/app). The code contains a single HTTP-triggered Azure Function.
79+
80+
1. Run `pulumi up` to preview and select `yes` to deploy changes:
81+
82+
```
83+
$ pulumi up
84+
Previewing update (dev)
85+
86+
View Live: https://app.pulumi.com/myuser/azure-py-functions/dev/previews/f3ea-2esdff2-123d-e79d
87+
88+
Type Name Plan
89+
+ pulumi:pulumi:Stack azure-py-functions-dev create
90+
+ ├─ azure-native:resources:ResourceGroup resourcegroup_functions_py create
91+
+ ├─ azure-native:web:AppServicePlan consumption-plan create
92+
+ ├─ azure-native:storage:StorageAccount storageaccount create
93+
+ └─ azure-native:web:WebApp functionapp create
94+
95+
Resources:
96+
+ 5 to create
97+
98+
Do you want to perform this update? [Use arrows to move, enter to select, type to filter]
99+
> yes
100+
no
101+
details
102+
103+
Updating (dev)
104+
105+
View Live: https://app.pulumi.com/myuser/azure-py-functions/dev/updates/1
106+
107+
Type Name Status
108+
+ pulumi:pulumi:Stack azure-py-functions-dev created
109+
+ ├─ azure-native:resources:ResourceGroup resourcegroup_functions_py created
110+
+ ├─ azure-native:web:AppServicePlan consumption-plan created
111+
+ ├─ azure-native:storage:StorageAccount storageaccount created
112+
+ └─ azure-native:web:WebApp functionapp created
113+
114+
Outputs:
115+
consumptionplan : "consumption-plan7b9df5ed"
116+
endpoint : "https://functionappfe054af4.azurewebsites.net/api/HelloWithPython"
117+
function_app : "functionappfe054af4"
118+
primarystoragekey : "[secret]"
119+
resourcegroup : "resourcegroup_functions_py4eba2bf2"
120+
storageaccount : "storageaccounta6b2e431"
121+
storageaccountkeys : "[secret]"
122+
storageconnectionstring: "[secret]"
123+
124+
Resources:
125+
+ 5 created
126+
127+
Duration: 50s
128+
```
129+
130+
1. Check the deployed function endpoints via [pulumi stack output](https://www.pulumi.com/docs/reference/cli/pulumi_stack_output/)
131+
132+
```
133+
$ pulumi stack output endpoint
134+
https://functionappfe054af4.azurewebsites.net/api/HelloWithPython
135+
136+
1. You can now open the resulting endpoint in the browser or curl it:
137+
```
138+
$ curl "$(pulumi stack output endpoint)"
139+
Hello from Python in Pulumi! You have stood up a serverless function in Azure!
140+
```
141+
142+
## Cleanup and destroy everything
143+
144+
1. Destroy the stack via: `pulumi destroy` .Select `yes`
145+
```
146+
Previewing destroy (dev)
147+
148+
Type Name Plan
149+
- pulumi:pulumi:Stack azure-py-functions-dev delete
150+
- ├─ azure-native:web:WebApp functionapp delete
151+
..
152+
..
153+
154+
Outputs:
155+
- endpoint : "https://functionappfe054af4.azurewebsites.net/api/HelloWithPython"
156+
..
157+
..
158+
159+
Resources:
160+
- 5 to delete
161+
162+
Do you want to perform this destroy? [Use arrows to move, enter to select, type to filter]
163+
yes
164+
> no
165+
details
166+
..
167+
..
168+
Resources:
169+
- 5 deleted
170+
171+
Duration: 1m1s
172+
```
173+
174+
1. Remove the stack
175+
176+
```
177+
pulumi stack rm
178+
This will permanently remove the 'dev' stack!
179+
Please confirm that this is what you'd like to do by typing ("dev"):
180+
```
181+
182+
Type in the name of your stack: **dev**

azure-py-functions/__main__.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import pulumi
2+
from pulumi_azure_native import resources
3+
from pulumi_azure_native import storage
4+
from pulumi_azure_native import web
5+
from pulumi import Output
6+
7+
# Create an Azure Resource Group
8+
resource_group = resources.ResourceGroup('resourcegroup_functions_py')
9+
10+
# Create a Storage Account
11+
account = storage.StorageAccount(
12+
'storageaccount',
13+
resource_group_name=resource_group.name,
14+
sku=storage.SkuArgs(
15+
name=storage.SkuName.STANDARD_LRS,
16+
),
17+
kind=storage.Kind.STORAGE_V2,
18+
)
19+
20+
# Create a consumption plan
21+
# Consumption plan must be linux for python: https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale#operating-systemruntime
22+
plan = web.AppServicePlan(
23+
"consumption-plan",
24+
resource_group_name=resource_group.name,
25+
location=resource_group.location,
26+
kind="functionapp",
27+
reserved=True, # This is an Azure Requirement for PYTHON. The function can only run on Linux.
28+
sku=web.SkuDescriptionArgs(name="Y1", tier="Dynamic", size="Y1", family="Y", capacity=0),
29+
)
30+
31+
# Export the Azure Resource Group
32+
pulumi.export('resourcegroup', resource_group.name)
33+
34+
# Export the Storage Account
35+
pulumi.export('storageaccount', account.name)
36+
37+
# Export the Consumption Plan
38+
pulumi.export('consumptionplan', plan.name)
39+
40+
# List of storage account keys
41+
storageAccountKeys = pulumi.Output.all(resource_group.name, account.name).apply(
42+
lambda args: storage.list_storage_account_keys(
43+
resource_group_name=args[0], account_name=args[1]
44+
)
45+
)
46+
# Primary storage account key
47+
primaryStorageKey = storageAccountKeys.apply(lambda accountKeys: accountKeys.keys[0].value)
48+
# Build a storage connection string out of it:
49+
storageConnectionString = Output.concat(
50+
"DefaultEndpointsProtocol=https;AccountName=", account.name, ";AccountKey=", primaryStorageKey
51+
)
52+
53+
54+
# Export the storageacountkey as a secret
55+
pulumi.export("storageaccountkeys", pulumi.Output.secret(storageAccountKeys))
56+
# Export the primarystoragekey as a secret
57+
pulumi.export('primarystoragekey', pulumi.Output.secret(primaryStorageKey))
58+
# Export the storageconnectionstring as a secret
59+
pulumi.export('storageconnectionstring', pulumi.Output.secret(storageConnectionString))
60+
61+
# Create the functionapp
62+
app = web.WebApp(
63+
"functionapp",
64+
resource_group_name=resource_group.name,
65+
location=resource_group.location,
66+
kind="functionapp",
67+
reserved=True,
68+
server_farm_id=plan.id,
69+
site_config=web.SiteConfigArgs(
70+
app_settings=[
71+
web.NameValuePairArgs(name="runtime", value="python"),
72+
web.NameValuePairArgs(name="FUNCTIONS_WORKER_RUNTIME", value="python"),
73+
web.NameValuePairArgs(name="FUNCTIONS_EXTENSION_VERSION", value="~3"),
74+
web.NameValuePairArgs(name="AzureWebJobsStorage", value=storageConnectionString),
75+
web.NameValuePairArgs(
76+
name="WEBSITE_RUN_FROM_PACKAGE",
77+
value="https://github.com/pulumi/examples/raw/master/azure-py-functions/app/HelloWithPython.zip",
78+
),
79+
],
80+
),
81+
)
82+
83+
# Export the function
84+
pulumi.export('function_app', app.name)
85+
86+
# Full endpoint of your Function App
87+
function_endpoint = app.default_host_name.apply(
88+
lambda default_host_name: f"https://{default_host_name}/api/HelloWithPython"
89+
)
90+
pulumi.export('endpoint', function_endpoint)
2.09 KB
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import logging
2+
3+
import azure.functions as func
4+
5+
6+
def main(req: func.HttpRequest) -> func.HttpResponse:
7+
logging.info('Python HTTP trigger function processed a request.')
8+
return func.HttpResponse(
9+
f"Hello from Python in Pulumi! You have stood up a serverless function in Azure!"
10+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"scriptFile": "__init__.py",
3+
"bindings": [
4+
{
5+
"authLevel": "anonymous",
6+
"type": "httpTrigger",
7+
"direction": "in",
8+
"name": "req",
9+
"methods": [
10+
"get",
11+
"post"
12+
]
13+
},
14+
{
15+
"type": "http",
16+
"direction": "out",
17+
"name": "$return"
18+
}
19+
]
20+
}

0 commit comments

Comments
 (0)