Skip to content

Commit a0813b9

Browse files
authored
Add a Python Azure Webserver example (pulumi#236)
* Add a Python Azure Webserver example * Add README.md * fix numbering * Fix indentation in readme * Update README now that this works * Fix custom data + use simpler pattern for data source * Format code * Add test * Fix syntax error
1 parent f93239b commit a0813b9

File tree

5 files changed

+233
-0
lines changed

5 files changed

+233
-0
lines changed

azure-py-webserver/Pulumi.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: azure-py-webserver
2+
runtime: python
3+
description: An Azure example using Python to provision a webserver

azure-py-webserver/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new)
2+
3+
# Azure Web Server example in Python
4+
5+
This example deploys an Azure Virtual Machine and starts a HTTP server on it.
6+
7+
## Prerequisites
8+
9+
1. [Install Pulumi](https://pulumi.io/install/)
10+
1. [Configure Pulumi for Azure](https://pulumi.io/quickstart/azure/setup.html)
11+
1. [Configure Pulumi for Python](https://pulumi.io/reference/python.html)
12+
13+
## Deploying and running the program
14+
15+
1. Set up a virtual Python environment and install dependencies
16+
17+
```
18+
$ virtualenv -p python3 venv
19+
$ source venv/bin/activate
20+
$ pip install -r requirements.txt
21+
```
22+
23+
1. Create a new stack:
24+
25+
```
26+
$ pulumi stack init azure-py-webserver
27+
```
28+
29+
1. Set the Azure environment:
30+
31+
```
32+
$ pulumi config set azure:environment public
33+
```
34+
35+
1. Set the required configuration for this example. This example requires you to supply a username and password to
36+
the virtual machine that we are going to create.
37+
38+
```
39+
$ pulumi config set azure-web:username myusername
40+
```
41+
42+
The password is a secret, so we can ask Pulumi to encrypt the configuration:
43+
44+
```
45+
$ pulumi config set --secret azure-web:password Hunter2hunter2
46+
```
47+
48+
1. Run `pulumi up` to preview and deploy the changes:
49+
50+
```
51+
$ pulumi update
52+
Previewing update (azuredev):
53+
54+
Type Name Plan
55+
+ pulumi:pulumi:Stack azure-py-webserver-azuredev create
56+
+ ├─ azure:core:ResourceGroup server create
57+
+ ├─ azure:network:VirtualNetwork server-network create
58+
+ ├─ azure:network:PublicIp server-ip create
59+
+ ├─ azure:network:Subnet server-subnet create
60+
+ ├─ azure:network:NetworkInterface server-nic create
61+
+ └─ azure:compute:VirtualMachine server-vm create
62+
63+
Resources:
64+
+ 7 to create
65+
66+
Do you want to perform this update? yes
67+
Updating (azuredev):
68+
69+
Type Name Status
70+
+ pulumi:pulumi:Stack azure-py-webserver-azuredev created
71+
+ ├─ azure:core:ResourceGroup server created
72+
+ ├─ azure:network:VirtualNetwork server-network created
73+
+ ├─ azure:network:PublicIp server-ip created
74+
+ ├─ azure:network:Subnet server-subnet created
75+
+ ├─ azure:network:NetworkInterface server-nic created
76+
+ └─ azure:compute:VirtualMachine server-vm created
77+
78+
Outputs:
79+
public_ip: "137.117.15.111"
80+
81+
Resources:
82+
+ 7 created
83+
84+
Duration: 2m55s
85+
86+
Permalink: https://app.pulumi.com/swgillespie/azure-py-webserver/azuredev/updates/3
87+
```
88+
89+
1. Get the IP address of the newly-created instance from the stack's outputs:
90+
91+
```
92+
$ pulumi stack output public_ip
93+
137.117.15.111
94+
```
95+
96+
1. Check to see that your server is now running:
97+
98+
```
99+
$ curl http://$(pulumi stack output public_ip)
100+
Hello, World!
101+
```
102+
103+
1. Destroy the stack:
104+
105+
```
106+
▶ pulumi destroy --yes
107+
Previewing destroy (azuredev):
108+
109+
Type Name Plan
110+
- pulumi:pulumi:Stack azure-py-webserver-azuredev delete
111+
- ├─ azure:compute:VirtualMachine server-vm delete
112+
- ├─ azure:network:NetworkInterface server-nic delete
113+
- ├─ azure:network:Subnet server-subnet delete
114+
- ├─ azure:network:PublicIp server-ip delete
115+
- ├─ azure:network:VirtualNetwork server-network delete
116+
- └─ azure:core:ResourceGroup server delete
117+
118+
Resources:
119+
- 7 to delete
120+
121+
Destroying (azuredev):
122+
123+
Type Name Status
124+
- pulumi:pulumi:Stack azure-py-webserver-azuredev deleted
125+
- ├─ azure:compute:VirtualMachine server-vm deleted
126+
- ├─ azure:network:NetworkInterface server-nic deleted
127+
- ├─ azure:network:Subnet server-subnet deleted
128+
- ├─ azure:network:VirtualNetwork server-network deleted
129+
- ├─ azure:network:PublicIp server-ip deleted
130+
- └─ azure:core:ResourceGroup server deleted
131+
132+
Resources:
133+
- 7 deleted
134+
135+
Duration: 3m49s
136+
137+
Permalink: https://app.pulumi.com/swgillespie/azure-py-webserver/azuredev/updates/4
138+
```

azure-py-webserver/__main__.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import pulumi
2+
from pulumi import Output
3+
from pulumi_azure import core, compute, network
4+
5+
config = pulumi.Config("azure-web")
6+
username = config.require("username")
7+
password = config.require("password")
8+
9+
resource_group = core.ResourceGroup("server", location="West US")
10+
net = network.VirtualNetwork(
11+
"server-network",
12+
resource_group_name=resource_group.name,
13+
location=resource_group.location,
14+
address_spaces=["10.0.0.0/16"],
15+
subnets=[{
16+
"name": "default",
17+
"address_prefix": "10.0.1.0/24",
18+
}])
19+
20+
subnet = network.Subnet(
21+
"server-subnet",
22+
resource_group_name=resource_group.name,
23+
virtual_network_name=net.name,
24+
address_prefix="10.0.2.0/24")
25+
public_ip = network.PublicIp(
26+
"server-ip",
27+
resource_group_name=resource_group.name,
28+
location=resource_group.location,
29+
allocation_method="Dynamic")
30+
31+
network_iface = network.NetworkInterface(
32+
"server-nic",
33+
resource_group_name=resource_group.name,
34+
location=resource_group.location,
35+
ip_configurations=[{
36+
"name": "webserveripcfg",
37+
"subnet_id": subnet.id,
38+
"private_ip_address_allocation": "Dynamic",
39+
"public_ip_address_id": public_ip.id,
40+
}])
41+
42+
userdata = """#!/bin/bash
43+
44+
echo "Hello, World!" > index.html
45+
nohup python -m SimpleHTTPServer 80 &"""
46+
47+
vm = compute.VirtualMachine(
48+
"server-vm",
49+
resource_group_name=resource_group.name,
50+
location=resource_group.location,
51+
network_interface_ids=[network_iface.id],
52+
vm_size="Standard_A0",
53+
delete_data_disks_on_termination=True,
54+
delete_os_disk_on_termination=True,
55+
os_profile={
56+
"computer_name": "hostname",
57+
"admin_username": username,
58+
"admin_password": password,
59+
"custom_data": userdata,
60+
},
61+
os_profile_linux_config={
62+
"disable_password_authentication": False,
63+
},
64+
storage_os_disk={
65+
"create_option": "FromImage",
66+
"name": "myosdisk1",
67+
},
68+
storage_image_reference={
69+
"publisher": "canonical",
70+
"offer": "UbuntuServer",
71+
"sku": "16.04-LTS",
72+
"version": "latest",
73+
})
74+
75+
combined_output = Output.all(vm.id, public_ip.name,
76+
public_ip.resource_group_name)
77+
public_ip_addr = combined_output.apply(
78+
lambda lst: network.get_public_ip(name=lst[1], resource_group_name=lst[2]))
79+
pulumi.export("public_ip", public_ip_addr.ip_address)

azure-py-webserver/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pulumi>=0.17.2
2+
pulumi_azure>=0.17.3

misc/test/examples_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,17 @@ func TestExamples(t *testing.T) {
319319
// })
320320
// },
321321
}),
322+
base.With(integration.ProgramTestOptions{
323+
Dir: path.Join(cwd, "..", "..", "azure-py-webserver"),
324+
Config: map[string]string{
325+
"azure:environment": azureEnviron,
326+
"azure-web:username": "myusername",
327+
"azure-web:password": "Hunter2hunter2",
328+
},
329+
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
330+
assertHTTPHelloWorld(t, stack.Outputs["public_ip"])
331+
},
332+
}),
322333
// TODO: This test fails due to a bug in the Terraform Azure provider in which the
323334
// service principal is not available when attempting to create the K8s cluster.
324335
// See the azure-ts-aks-example readme for more detail.

0 commit comments

Comments
 (0)