forked from pulumi/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e3dd441
commit 00221d0
Showing
19 changed files
with
547 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
name: container-quickstart | ||
description: NGINX container example | ||
runtime: nodejs | ||
template: | ||
config: | ||
aws:region: | ||
description: The AWS region to deploy into | ||
default: us-west-2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new) | ||
|
||
# Easy container example | ||
|
||
Companion to the tutorial [Provision containers on AWS](https://pulumi.io/quickstart/aws-containers.html). | ||
|
||
## Prerequisites | ||
|
||
To run this example, make sure [Docker](https://docs.docker.com/engine/installation/) is installed and running. | ||
|
||
## Running the App | ||
|
||
Note: some values in this example will be different from run to run. These values are indicated | ||
with `***`. | ||
|
||
1. Create a new stack: | ||
|
||
``` | ||
$ pulumi stack init containers-dev | ||
``` | ||
|
||
1. Configure Pulumi to use an AWS region that supports Fargate. This is currently only available in `us-east-1`, `us-east-2`, `us-west-2`, and `eu-west-1`: | ||
|
||
``` | ||
$ pulumi config set aws:region us-west-2 | ||
``` | ||
|
||
1. Restore NPM modules via `npm install` or `yarn install`. | ||
|
||
1. Preview and deploy the app via `pulumi up`. The preview will take a few minutes, as it builds a Docker container. A total of 19 resources are created. | ||
|
||
``` | ||
$ pulumi up | ||
``` | ||
|
||
1. View the endpoint URL, and run curl: | ||
|
||
```bash | ||
$ pulumi stack output | ||
Current stack outputs (1) | ||
OUTPUT VALUE | ||
hostname http:https://***.elb.us-west-2.amazonaws.com | ||
|
||
$ curl $(pulumi stack output hostname) | ||
<html> | ||
<head><meta charset="UTF-8"> | ||
<title>Hello, Pulumi!</title></head> | ||
<body> | ||
<p>Hello, S3!</p> | ||
<p>Made with ❤️ with <a href="https://pulumi.com">Pulumi</a></p> | ||
</body></html> | ||
``` | ||
|
||
1. To view the runtime logs from the container, use the `pulumi logs` command. To get a log stream, use `pulumi logs --follow`. | ||
|
||
``` | ||
$ pulumi logs --follow | ||
Collecting logs for stack container-quickstart-dev since 2018-05-22T14:25:46.000-07:00. | ||
2018-05-22T15:33:22.057-07:00[ pulumi-nginx] 172.31.13.248 - - [22/May/2018:22:33:22 +0000] "GET / HTTP/1.1" 200 189 "-" "curl/7.54.0" "-" | ||
``` | ||
|
||
## Clean up | ||
|
||
To clean up resources, run `pulumi destroy` and answer the confirmation question at the prompt. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
FROM nginx | ||
COPY content /usr/share/nginx/html |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<html> | ||
<head><meta charset="UTF-8"> | ||
<title>Hello, Pulumi!</title></head> | ||
<body> | ||
<p>Hello, containers!</p> | ||
<p>Made with ❤️ with <a href="https://pulumi.com">Pulumi</a></p> | ||
</body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import * as awsx from "@pulumi/aws-infra"; | ||
|
||
// Create an elastic network listener to listen for requests and route them to the container. | ||
// See https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html | ||
// for more details. | ||
let listener = new awsx.elasticloadbalancingv2.NetworkListener("nginx", { port: 80 }); | ||
|
||
// Define the service to run. We pass in the listener to hook up the network load balancer | ||
// to the containers the service will launch. | ||
let service = new awsx.ecs.FargateService("nginx", { | ||
desiredCount: 2, | ||
taskDefinitionArgs: { | ||
containers: { | ||
nginx: { | ||
image: awsx.ecs.Image.fromPath("./app"), | ||
memory: 512, | ||
portMappings: [listener], | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
// export just the hostname property of the container frontend | ||
export const hostname = listener.endpoint().apply(e => `http:https://${e.hostname}`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "container-quickstart", | ||
"main": "index.js", | ||
"dependencies": { | ||
"@pulumi/pulumi": "dev", | ||
"@pulumi/aws": "dev", | ||
"@pulumi/aws-infra": "=0.16.3-dev.1546999531" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
name: voting-app | ||
runtime: nodejs | ||
description: Voting app that uses containers | ||
template: | ||
config: | ||
aws:region: | ||
description: The AWS region to deploy into | ||
default: us-west-2 | ||
redisPassword: | ||
description: The Redis password | ||
secret: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new) | ||
|
||
# Voting app with two containers | ||
|
||
A simple voting app that uses Redis for a data store and a Python Flask app for the frontend. The example has been ported from https://github.com/Azure-Samples/azure-voting-app-redis. | ||
|
||
The example shows how easy it is to deploy containers into production and to connect them to one another. Since the example defines a custom container, Pulumi does the following: | ||
- Builds the Docker image | ||
- Provisions AWS Container Registry (ECR) instance | ||
- Pushes the image to the ECR instance | ||
- Creates a new ECS task definition, pointing to the ECR image definition | ||
|
||
## Prerequisites | ||
|
||
To use this example, make sure [Docker](https://docs.docker.com/engine/installation/) is installed and running. | ||
|
||
## Deploying and running the program | ||
|
||
### Configure the deployment | ||
|
||
Note: some values in this example will be different from run to run. These values are indicated | ||
with `***`. | ||
|
||
1. Login via `pulumi login`. | ||
|
||
1. Create a new stack: | ||
|
||
``` | ||
$ pulumi stack init voting-app-testing | ||
``` | ||
|
||
1. Set AWS as the provider: | ||
|
||
``` | ||
$ pulumi config set cloud:provider aws | ||
``` | ||
|
||
1. Configure Pulumi to use an AWS region that supports Fargate, which is currently only available in `us-east-1`, `us-east-2`, `us-west-2`, and `eu-west-1`: | ||
|
||
``` | ||
$ pulumi config set aws:region us-west-2 | ||
``` | ||
|
||
1. Set a value for the Redis password. The value can be an encrypted secret, specified with the `--secret` flag. If this flag is not provided, the value will be saved as plaintext in `Pulumi.testing.yaml` (since `testing` is the current stack name). | ||
|
||
``` | ||
$ pulumi config set --secret redisPassword S3cr37Password | ||
``` | ||
|
||
### Install dependencies | ||
|
||
1. Restore NPM modules via `npm install` or `yarn install`. | ||
|
||
### Preview and deploy | ||
|
||
1. Ensure the Docker daemon is running on your machine, then preview and deploy the program with `pulumi up`. The program deploys 24 resources and takes about 10 minutes to complete. | ||
|
||
1. View the stack output properties via `pulumi stack output`. The stack output property `frontendUrl` is the URL and port of the deployed app: | ||
|
||
```bash | ||
$ pulumi stack output frontendURL | ||
***.elb.us-west-2.amazonaws.com | ||
``` | ||
|
||
1. In a browser, navigate to the URL for `frontendURL`. You should see the voting app webpage. | ||
|
||
![Voting app screenshot](./voting-app-webpage.png) | ||
|
||
### Delete resources | ||
|
||
When you're done, run `pulumi destroy` to delete the program's resources: | ||
|
||
``` | ||
$ pulumi destroy | ||
This will permanently destroy all resources in the 'testing' stack! | ||
Please confirm that this is what you'd like to do by typing ("testing"): testing | ||
``` | ||
|
||
## About the code | ||
|
||
At the start of the program, the following lines retrieve the value for the Redis password by reading a [configuration value](https://pulumi.io/reference/config.html). This is the same value that was set above with the command `pulumi config set redisPassword <value>`: | ||
|
||
```typescript | ||
let config = new pulumi.Config(); | ||
let redisPassword = config.require("redisPassword"); | ||
``` | ||
|
||
In the program, the value can be used like any other variable. | ||
|
||
### Resources | ||
|
||
The program provisions two top-level resources with the following commands: | ||
|
||
```typescript | ||
let redisCache = new awsx.ecs.FargateService("voting-app-cache", ... ) | ||
let frontend = new awsx.ecs.FargateService("voting-app-frontend", ... ) | ||
``` | ||
|
||
The definition of `redisCache` uses the `image` property of `FargateService.taskDefinitionArgs` to point to an existing Docker image. In this case, this is the image `redis` at tag `alpine` on Docker Hub. The `redisPassword` variable is passed to the startup command for this image. | ||
|
||
The definition of `frontend` is more interesting, as it uses `image` property of `FargateService.taskDefinitionArgs` to point to a folder with a Dockerfile, which in this case is a Python Flask app. Pulumi automatically invokes `docker build` for you and pushes the container to ECR. | ||
|
||
So that the `frontend` container can connect to `redisCache`, the environment variables `REDIS`, `REDIS_PORT` are defined. Using the `redisListenre.endpoint` property, it's easy to declare the connection between the two containers. | ||
|
||
The Flask app uses these environment variables to connect to the Redis cache container. See the following in [`frontend/app/main.py`](frontend/app/main.py): | ||
|
||
```python | ||
redis_server = os.environ['REDIS'] | ||
redis_port = os.environ['REDIS_PORT'] | ||
redis_password = os.environ['REDIS_PWD'] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FROM tiangolo/uwsgi-nginx-flask:python3.6 | ||
RUN pip install redis | ||
COPY /app /app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# UI Configurations | ||
TITLE = 'Pulumi Voting App' | ||
VOTE1VALUE = 'Tabs' | ||
VOTE2VALUE = 'Spaces' | ||
SHOWHOST = 'false' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copied from https://github.com/Azure-Samples/azure-voting-app-redis | ||
|
||
from flask import Flask, request, render_template | ||
import os | ||
import random | ||
import redis | ||
import socket | ||
import sys | ||
|
||
app = Flask(__name__) | ||
|
||
# Load configurations | ||
app.config.from_pyfile('config_file.cfg') | ||
button1 = app.config['VOTE1VALUE'] | ||
button2 = app.config['VOTE2VALUE'] | ||
title = app.config['TITLE'] | ||
|
||
# Redis configurations | ||
redis_server = os.environ['REDIS'] | ||
redis_port = os.environ['REDIS_PORT'] | ||
redis_password = os.environ['REDIS_PWD'] | ||
|
||
# Redis Connection | ||
try: | ||
r = redis.StrictRedis(host=redis_server, port=redis_port, password=redis_password) | ||
r.ping() | ||
except redis.ConnectionError: | ||
exit('Failed to connect to Redis, terminating.') | ||
|
||
# Init Redis | ||
if not r.get(button1): r.set(button1,0) | ||
if not r.get(button2): r.set(button2,0) | ||
|
||
@app.route('/', methods=['GET', 'POST']) | ||
def index(): | ||
|
||
if request.method == 'GET': | ||
|
||
# Get current values | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
|
||
# Return index with values | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
elif request.method == 'POST': | ||
|
||
if request.form['vote'] == 'reset': | ||
|
||
# Empty table and return results | ||
r.set(button1,0) | ||
r.set(button2,0) | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
else: | ||
|
||
# Insert vote result into DB | ||
vote = request.form['vote'] | ||
r.incr(vote,1) | ||
|
||
# Get current values | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
|
||
# Return results | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
if __name__ == "__main__": | ||
app.run() |
Oops, something went wrong.