Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Add the first Next Level IaC blog post
Browse files Browse the repository at this point in the history
  • Loading branch information
cnunciato committed Apr 26, 2024
1 parent b122414 commit d682df4
Show file tree
Hide file tree
Showing 20 changed files with 815 additions and 0 deletions.

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions themes/default/layouts/shortcodes/langname
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- /* Used to display a language-specific runtime name based on the chosen language. */ -}}
<pulumi-chooser type="language" options="javascript,typescript,python,go,csharp,java,yaml,fsharp,visualbasic" option-style="none" class="inline">
<pulumi-choosable type="language" value="javascript">JavaScript</pulumi-choosable>
<pulumi-choosable type="language" value="typescript">TypeScript</pulumi-choosable>
<pulumi-choosable type="language" value="python">Python</pulumi-choosable>
<pulumi-choosable type="language" value="go">Go</pulumi-choosable>
<pulumi-choosable type="language" value="csharp">C#</pulumi-choosable>
<pulumi-choosable type="language" value="java">Java</pulumi-choosable>
<pulumi-choosable type="language" value="yaml">Pulumi YAML</pulumi-choosable>
<pulumi-choosable type="language" value="fsharp">F#</pulumi-choosable>
<pulumi-choosable type="language" value="visualbasic">VB</pulumi-choosable>
</pulumi-chooser>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module aws-iam-role-instanceprofile-go

go 1.21

toolchain go1.21.0

require (
github.com/pulumi/pulumi-aws/sdk/v6 v6.24.0
github.com/pulumi/pulumi/sdk/v3 v3.108.1
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module aws-iam-role-policyattachment-managedpolicy-go

go 1.21

toolchain go1.21.0

require (
github.com/pulumi/pulumi-aws/sdk/v6 v6.24.0
github.com/pulumi/pulumi/sdk/v3 v3.108.1
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module aws-iam-user-group-grouppolicy-go

go 1.21

toolchain go1.21.0

require (
github.com/pulumi/pulumi-aws/sdk/v6 v6.24.0
github.com/pulumi/pulumi/sdk/v3 v3.108.1
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module aws-iam-user-userpolicy-go

go 1.21

toolchain go1.21.0

require (
github.com/pulumi/pulumi-aws/sdk/v6 v6.24.0
github.com/pulumi/pulumi/sdk/v3 v3.108.1
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: aws-static-website-with-runtime-logic-python
description: An example that demonstrates a few interesting things you can do at runtime with Pulumi.
runtime:
name: python
options:
virtualenv: venv
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import pulumi
import pulumi_aws as aws
import asyncio
import boto3
import json
import os
import requests
import subprocess
import time

# Build the website.
result = subprocess.run(["hugo"], stdout=subprocess.PIPE, cwd="./www")

# Provision a storage bucket for the website.
bucket = aws.s3.Bucket(
"bucket", website=aws.s3.BucketWebsiteArgs(index_document="index.html")
)

# Apply some ownership controls and public-access privileges.
ownership_controls = aws.s3.BucketOwnershipControls(
"ownership-controls",
bucket=bucket.bucket,
rule=aws.s3.BucketOwnershipControlsRuleArgs(
object_ownership="ObjectWriter",
),
)

public_access_block = aws.s3.BucketPublicAccessBlock(
"public-access-block",
bucket=bucket.bucket,
block_public_acls=False,
)

# Copy the website home page into the bucket
homepage = aws.s3.BucketObject(
"index.html",
bucket=bucket.id,
content=open("./www/public/index.html", "r").read(),
content_type="text/html",
acl="public-read",
opts=pulumi.ResourceOptions(depends_on=[ownership_controls, public_access_block]),
)

# Fetch some redirects from a hypothetical CMS.
response = requests.get(f"{os.environ['CMS_ENDPOINT']}/redirects.json")
redirects = json.loads(response.text)

# Create an S3 website redirect for each one.
for i, redirect in enumerate(redirects):
aws.s3.BucketObject(f"redirect-{i}",
bucket=bucket.id,
key=redirect["from"],
website_redirect=redirect["to"],
acl="public-read",
opts=pulumi.ResourceOptions(depends_on=[ownership_controls, public_access_block]),
)

# Create a CloudFront distribution for the website.
cdn = aws.cloudfront.Distribution(
"cdn",
enabled=True,
default_root_object="index.html",
origins=[
aws.cloudfront.DistributionOriginArgs(
origin_id=bucket.arn,
domain_name=bucket.website_endpoint,
custom_origin_config=aws.cloudfront.DistributionOriginCustomOriginConfigArgs(
origin_protocol_policy="http-only",
http_port=80,
https_port=443,
origin_ssl_protocols=["TLSv1.2"],
),
)
],
default_cache_behavior=aws.cloudfront.DistributionDefaultCacheBehaviorArgs(
target_origin_id=bucket.arn,
viewer_protocol_policy="redirect-to-https",
allowed_methods=["GET", "HEAD", "OPTIONS"],
cached_methods=["GET", "HEAD", "OPTIONS"],
forwarded_values=aws.cloudfront.DistributionDefaultCacheBehaviorForwardedValuesArgs(
query_string=True,
cookies=aws.cloudfront.DistributionDefaultCacheBehaviorForwardedValuesCookiesArgs(
forward="all",
),
),
),
restrictions=aws.cloudfront.DistributionRestrictionsArgs(
geo_restriction=aws.cloudfront.DistributionRestrictionsGeoRestrictionArgs(
restriction_type="none",
),
),
viewer_certificate=aws.cloudfront.DistributionViewerCertificateArgs(
cloudfront_default_certificate=True,
),
)

def create_invalidation(id):

# Don't bother invalidating unless it's an actual deployment.
if pulumi.runtime.is_dry_run():
print("This is a Pulumi preview, so skipping cache invalidation.")
return

client = boto3.client("cloudfront")
result = client.create_invalidation(
DistributionId=id,
InvalidationBatch={
"CallerReference": f"invalidation-{str(time.time)}",
"Paths": {
"Quantity": 1,
"Items": [ "/*" ],
},
},
)

print(f"Cache invalidation of distribution {id}: {result['Invalidation']['Status']}.")

# Register a function to be be invoked before the program exits.
async def invalidate(id):
await asyncio.to_thread(create_invalidation, id)

cdn.id.apply(lambda id: invalidate(id))

# Export the URL of the CDN.
pulumi.export("cdnURL", pulumi.Output.format("https://{0}", cdn.domain_name))
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pulumi>=3.0.0,<4.0.0
pulumi_aws>=6.0.0,<7.0.0
requests>=2.0.0,<3.0.0
boto3>=1.0.0,<2.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
baseURL = 'http://example.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
Hi, world!
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: aws-static-website-with-runtime-logic-typescript
description: An example that demonstrates a few interesting things you can do at runtime with Pulumi.
runtime: nodejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as cloudfront from "@aws-sdk/client-cloudfront";
import * as childProcess from "child_process";
import * as fs from "fs";

const config = new pulumi.Config("aws");
const region = config.require("region");

// Build the website.
const proc = childProcess.execSync("hugo", { stdio: "inherit", cwd: "./www" });

// Provision a storage bucket for the website.
const bucket = new aws.s3.Bucket("bucket", {
website: {
indexDocument: "index.html"
},
});

// Apply some ownership controls and public-access privileges.
const ownershipControls = new aws.s3.BucketOwnershipControls("ownership-controls", {
bucket: bucket.id,
rule: {
objectOwnership: "ObjectWriter",
},
});

const publicAccess = new aws.s3.BucketPublicAccessBlock("public-access-block", {
bucket: bucket.id,
blockPublicAcls: false,
});

// Copy the website home page into the bucket.
const homepage = new aws.s3.BucketObject("index.html", {
bucket: bucket.id,
content: fs.readFileSync("./www/public/index.html", "utf-8"),
contentType: "text/html",
acl: "public-read",
}, { dependsOn: [ownershipControls, publicAccess]});

// Fetch some redirects from a hypothetical CMS.
const redirects = fetch(`${process.env.CMS_ENDPOINT}/redirects.json`)
.then(response => response.json())
.then(items => items.forEach((redirect: any, i: number) => {

// Create an S3 website redirect for each one.
new aws.s3.BucketObject(`redirect-${i}`, {
bucket: bucket.id,
key: redirect.from,
websiteRedirect: redirect.to,
acl: "public-read",
}, { dependsOn: [ownershipControls, publicAccess]});
}),
);

// Create a CloudFront distribution for the website.
const cdn = new aws.cloudfront.Distribution("cdn", {
enabled: true,
defaultRootObject: "index.html",
origins: [{
originId: bucket.arn,
domainName: bucket.websiteEndpoint,
customOriginConfig: {
originProtocolPolicy: "http-only",
httpPort: 80,
httpsPort: 443,
originSslProtocols: ["TLSv1.2"],
},
}],
defaultCacheBehavior: {
targetOriginId: bucket.arn,
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: [ "GET", "HEAD", "OPTIONS" ],
cachedMethods: [ "GET", "HEAD", "OPTIONS" ],
forwardedValues: {
queryString: true,
cookies: {
forward: "all",
},
},
},
restrictions: {
geoRestriction: {
restrictionType: "none",
},
},
viewerCertificate: {
cloudfrontDefaultCertificate: true,
},
});

// Register a function to be be invoked before the program exits.
process.on("beforeExit", () => {

// Only invalidate after a deployment.
if (pulumi.runtime.isDryRun()) {
console.log("This is a Pulumi preview, so skipping cache invalidation.");
return;
}

cdn.id.apply(id => {
const client = new cloudfront.CloudFrontClient({ region });
const command = new cloudfront.CreateInvalidationCommand({
DistributionId: id,
InvalidationBatch: {
CallerReference: `invalidation-${Date.now()}`,
Paths: {
Quantity: 1,
Items: [ "/*" ],
},
},
});

client.send(command)
.then(result => {
console.log(`Invalidation status for ${id}: ${result.Invalidation?.Status}.`);
process.exit(0);
})
.catch(error => {
console.error(error);
process.exit(1);
});
});
});

// Export the URL of the CDN.
export const cdnURL = pulumi.interpolate`https://${cdn.domainName}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "aws-static-website-with-runtime-logic-typescript",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18"
},
"dependencies": {
"@aws-sdk/client-cloudfront": "^3.563.0",
"@pulumi/aws": "^6.0.0",
"@pulumi/awsx": "^2.0.2",
"@pulumi/pulumi": "^3.113.0",
"typescript": "^5.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": ["index.ts"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
baseURL = 'http://example.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'
Loading

0 comments on commit d682df4

Please sign in to comment.