Terraform Cloud Project Bootcamp with Andrew Brown — 1.8.0 Assets Upload for Each

Gwen Leigh
4 min readOct 8, 2023

--

This article is part of my Terraform journey with Terraform Bootcamp by Andrew Brown and Andrew Bayko with Chris Williams and Shala.

My wild career adventure into Cloud Computing continues with Andrews, and I highly, highly recommend you to come join us if you are interested. Check out Andrews’ free youtube learning contents. You can also buy some paid courses here to support their good cause.

Agenda

Video here: 1 8 0 Assets Upload For Each

Issue #37 Goals

  • ✅ 1) Use for each to upload assets.
  • ✅ 2) Explore different data structures in terraform.
  • ✅ 3) terraform console

Workflow

  • ✅ 1) Run http-server and check your website.
  • ✅ 2) for_each: update resource-storage.tf & index.html

1. Run http-server and check your website.

http server launched on a turtle lol

Install http-server which is a convenient http server that makes your local development and testing so easy. You can run the command in the before: section on terminal. If you are using gitpod, you can update your gitpod.yml so your environment installs and spins it up every time you launch a new Gitpod environment:

# gitpod.yml
- name: http-server
before: |
npm install --global http-server
http-server

Once thehttp-server is running, go check your website (http://128.0.1:8080).

2. Update index.html & resource-storage.tf

We want to make terraform update our infrastructure every time there are differences in the objects stored in the designated bucket.

resource-storage.tf

Add the resource upload_assets to the storage definition file in the terrahouse_aws module.

  • resource-storage.tf
resource "aws_s3_object" "upload_assets" {
for_each = fileset("${path.root}/public/assets", "*.{jpg.png.gif}")
bucket = aws_s3_bucket.website_bucket.bucket
key = "assets/${each.key}"
source = var.index_html_filepath
content_type = "text/html"
etag = filemd5(var.index_html_filepath)
lifecycle {
replace_triggered_by = [ terraform_data.content_version.output ]
ignore_changes = [ etag ]
}
}
  • You can test if the file path works correctly by testing it on terraform console. Open the console by running terraform console. Then run fileset(“${path.root}/public/assets”, “*.{jpg.png.gif}”). Make sure you are running this at root, otherwise it won’t be able to locate your files and return the result.

for_each

for_each accepts a map or a set of strings and creates an instance for each item in that map or set. In our code above, for_each will iterate through the set of strings using fileset, and create each file in the aws_s3_bucket.website_bucket.bucket as destination. Each object created in the bucket will have its own etag. As constained by the lifecycle, however, the replacement will only be triggered by changes in content_version.

Some useful notes from Andrew’s instructional material

index.html

As we have configured Terraform to take note of changes in the target path (var.assets_path) and upload files accordingly, I added some <images> in the index file and the corresponding image files at the local path.

+   <h1 class="fonts-head1">Do one thing
+ <br>that scares you every day.
+ </h1>
+ <p>Eleanor Roosevelt</p>
+ <img src="./assets/eleanor-roosevelt.jpg" />

Then run the following commands to test the function.

  • terraform plan
  • terraform apply
I uploaded a new picture and it detects the change.

Terraform picks up the changes and correctly uploads newly added image files to the remote S3 bucket.

This is the image I added in the above snippet.
Hi Akinlolu Gbemisola John (G-oracle) 👋 Thanks a lot for your kind message. Your words found itself an entry on my favourite quotes list :D

Resources

Bootcamp

Terraform

--

--

Gwen Leigh

Cloud Engineer to be. Actively building my profile, network and experience in the cloud space. .