Right now, the bucket’s contents are hard-coded. Next, you’ll make the location of the contents configurable, and add support for populating the bucket with an entire directory’s worth of contents.
Instead of hard-coding the "site"
directory, we will use configuration to make it easy to change the location without editing the program.
Create a file config.ts
and add this to it:
import { Config } from "@pulumi/pulumi";
const config = new Config();
export const siteDir = config.require("siteDir");
Add this line to your index.ts
file’s import statements:
import { siteDir } from "./config";
And replace the hard-coded "site"
parameter with this imported siteDir
variable:
const myObject = new aws.s3.BucketObject("index.html", {
acl: "public-read",
bucket: myBucket,
contentType: "text/html",
source: path.join(siteDir, "index.html"),
});
The index.ts
file should now have the following contents:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as path from "path";
import { siteDir } from "./config";
const myBucket = new aws.s3.Bucket("my-bucket", {
website: {
indexDocument: "index.html",
},
});
const myObject = new aws.s3.BucketObject("index.html", {
acl: "public-read",
bucket: myBucket,
contentType: "text/html",
source: path.join(siteDir, "index.html"),
});
export const bucketName = myBucket.bucket;
export const bucketEndpoint = pulumi.interpolate`http://${myBucket.websiteEndpoint}`;
To make matters interesting, rename the site
directory to www
:
mv site www
Now, deploy your changes. To do so, first configure your stack. If you don’t, you’ll get an error:
pulumi up
This results in an error like the following:
error: Missing required configuration variable 'iac-workshop:siteDir'
please set a value using the command `pulumi config set iac-workshop:siteDir <value>`
Configure the iac-workshop:siteDir
variable very much like the aws:region
variable:
pulumi config set iac-workshop:siteDir www
On the next pulumi up
, Pulumi detects that the path has changed and will perform a simple update:
Updating (dev):
Type Name Status Info
pulumi:pulumi:Stack iac-workshop-dev
~ └─ aws:s3:BucketObject index.html updated [diff: ~source]
Outputs:
bucketEndpoint: "http://my-bucket-aca82a7.s3-website-us-west-1.amazonaws.com"
bucketName : "my-bucket-aca82a7"
Resources:
~ 1 updated
2 unchanged
Duration: 3s
Permalink: https://app.pulumi.com/joeduffy/iac-workshop/dev/updates/5
Instead of hard-coding the set of files, you will now change the program to read the entire contents of the www
directory. The mime
NPM package dynamically detects content types and node-dir
recursively scans directories. Install these packages:
npm install mime @types/mime node-dir @types/node-dir
Add import statements for the new packages:
import * as mime from "mime";
import * as nodedir from "node-dir";
The
@types/...
packages are not imported. They are only there to ensure compile-time TypeScript checking.
Now replace the object allocation with this code:
const files = nodedir.files(siteDir, { sync: true });
for (const file of files) {
const name = file.substring(siteDir.length+1);
const myObject = new aws.s3.BucketObject(name, {
acl: "public-read",
bucket: myBucket,
contentType: mime.getType(file) || undefined,
source: file,
});
}
Add a new file, about.html
, to the www
directory:
<html>
<p>Infrastructure as code using real languages is powerful.</p>
</html>
The index.ts
file should now have the following contents:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as path from "path";
import { siteDir } from "./config";
import * as mime from "mime";
import * as nodedir from "node-dir";
const myBucket = new aws.s3.Bucket("my-bucket", {
website: {
indexDocument: "index.html",
},
});
const files = nodedir.files(siteDir, { sync: true });
for (const file of files) {
const name = file.substring(siteDir.length+1);
const myObject = new aws.s3.BucketObject(name, {
acl: "public-read",
bucket: myBucket,
contentType: mime.getType(file) || undefined,
source: file,
});
}
export const bucketName = myBucket.bucket;
export const bucketEndpoint = pulumi.interpolate`http://${myBucket.websiteEndpoint}`;
Perform a deployment:
pulumi up
You will see a single new object created for the www/about.html
file:
Updating (dev):
Type Name Status
pulumi:pulumi:Stack iac-workshop-dev
+ └─ aws:s3:BucketObject about.html created
...
Now fetch it:
curl $(pulumi stack output bucketEndpoint)/about.html
And you will see the contents added above.