Using Pulumi on AWS
In this post I shall how to use the examples provided by Pulumi to setup a static website using AWS S3.
Pre requisities
- These steps assume you have already cloned https://github.com/pulumi/examples.git 2. Python version >=3 3. AWS account
Setup user in IAM
- Create a user in AWS which has access to create S3 resources
- Export the credentials.csv
- You will need the AWS_ACCESS_KEY_ID
- You will need the AWS_SECRET_ACCESS_KEY
- Note down the AWS region you want to deploy into
Deployment configuration
- Export the following environment variables
export AWS_ACCESS_KEY_ID=<your access key id>
export AWS_SECRET_ACCESS_KEY=<your secret access key>
Initialize the stack
Make sure you are in the top level directory where you cloned the examples git repository
cd aws-py-s3-folder
pulumi stack init s3-website
pulumi config set aws:region <aws_region>
Note
It is important to note that if you run ‘pulumi stack init s3-website’ inside a directory without a project file i.e. the** Pulumi.yaml file**.
You will get the following error message.
error: no Pulumi project found in the current working directory
Pulumi core files
- Pulumi.yaml » main project file
- main.py » entry point file
- www » directory holding the static content which will be served in the S3 bucket
- requirements.txt » a list of required Python modules
Once you have initialized the Pulumi stack you will also find an extra file called ‘Pulumi.S3-website.yaml’ which contains the AWS region you configured Pulumi to use.
You will notice the requirements.txt file containing the required Python modules.
pulumi>=2.0.0,<3.0.0
pulumi-aws>=2.0.0,<3.0.0
main.py
No HCL here except only Python for defining the deployment. As below you’ll notice the modules from pulumi are imported.
Definition of the S3 read policy, along with what files will be served.
The export of stack properties are defined at the bottom, these can later be inspected.
import json
import mimetypes
import os
from pulumi import export, FileAsset
from pulumi_aws import s3
web_bucket = s3.Bucket('s3-website-bucket', website={
"index_document": "index.html"
})
content_dir = "www"
for file in os.listdir(content_dir):
filepath = os.path.join(content_dir, file)
mime_type, _ = mimetypes.guess_type(filepath)
obj = s3.BucketObject(file,
bucket=web_bucket.id,
source=FileAsset(filepath),
content_type=mime_type)
def public_read_policy_for_bucket(bucket_name):
return json.dumps({
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
f"arn:aws:s3:::{bucket_name}/*",
]
}]
})
bucket_name = web_bucket.id
bucket_policy = s3.BucketPolicy("bucket-policy",
bucket=bucket_name,
policy=bucket_name.apply(public_read_policy_for_bucket))
# Export the name of the bucket
export('bucket_name', web_bucket.id)
export('website_url', web_bucket.website_endpoint)
Deployment
Python virtual env
This virtual environment is required to install dependency packages necessary for the deployment.
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Deploy
pulumi up
Previewing update (s3-website):
Type Name Plan
+ pulumi:pulumi:Stack aws-py-s3-folder-s3-website create
+ ├─ aws:s3:Bucket s3-website-bucket create
+ ├─ aws:s3:BucketPolicy bucket-policy create
+ ├─ aws:s3:BucketObject index.html create
+ ├─ aws:s3:BucketObject favicon.png create
+ └─ aws:s3:BucketObject python.png create
Resources:
+ 6 to create
Do you want to perform this update? [Use arrows to move, enter to select, type to filter]
yes
> no
details
Do you want to perform this update? [Use arrows to move, enter to select, type to filter]
> yes
no
details
Do you want to perform this update? yes
Updating (s3-website):
Type Name Status
+ pulumi:pulumi:Stack aws-py-s3-folder-s3-website created
+ ├─ aws:s3:Bucket s3-website-bucket created
+ ├─ aws:s3:BucketObject index.html created
+ ├─ aws:s3:BucketObject python.png created
+ ├─ aws:s3:BucketObject favicon.png created
+ └─ aws:s3:BucketPolicy bucket-policy created
Outputs:
bucket_name: "s3-website-bucket-#####"
website_url: "s3-website-bucket-#####".s3-website-#####".amazonaws.com"
Resources:
+ 6 created
Duration: 12s
Permalink: https://app.pulumi.com/####/aws-py-s3-folder/S3-website/updates/1
Inspect stack output
pulumi stack output
Current stack outputs (2):
OUTPUT VALUE
bucket_name s3-website-bucket-####
website_url s3-website-bucket-####.amazonaws.com
Open the website_url in your browser, and you will see the static contents served in S3.
Cleanup
pulumi destroy -y
Previewing destroy (s3-website):
Type Name Plan
- pulumi:pulumi:Stack aws-py-s3-folder-s3-website delete
- ├─ aws:s3:BucketPolicy bucket-policy delete
- ├─ aws:s3:BucketObject python.png delete
- ├─ aws:s3:BucketObject favicon.png delete
- ├─ aws:s3:BucketObject index.html delete
- └─ aws:s3:Bucket s3-website-bucket delete
Outputs:
- bucket_name: "s3-website-bucket-#####""
- website_url: "s3-website-bucket-#####".s3-website-#####".amazonaws.com"
Resources:
- 6 to delete
Destroying (s3-website):
Type Name Status
- pulumi:pulumi:Stack aws-py-s3-folder-s3-website deleted
- ├─ aws:s3:BucketPolicy bucket-policy deleted
- ├─ aws:s3:BucketObject index.html deleted
- ├─ aws:s3:BucketObject python.png deleted
- ├─ aws:s3:BucketObject favicon.png deleted
- └─ aws:s3:Bucket s3-website-bucket deleted
Outputs:
- bucket_name: "s3-website-bucket-#####"
- website_url: "s3-website-bucket-#####".s3-website-#####".amazonaws.com"
Resources:
- 6 deleted
Duration: 8s
Delete the stack
pulumi stack rm s3-website -y
Stack 's3-website' has been removed!
Also remove the IAM user you created for this demo.
Timing
Overall time: <1min to setup a basic S3 bucket and serve static content in AWS.