Terraform Cloud Project Bootcamp with Andrew Brown — 1.6.0 Terrafrom Data Content Version

Gwen Leigh
4 min readOct 7, 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 6 0 Terraform Data Content Version

Issue #33 Goals

  • ✅ 1) Only change files when we set a content version.

Workflow

Troubleshooting

Previously in unit 1.5.0, we invalidated the CloudFront cache using /* which clears all the data that’s cached in the edge locations and this is an expensive call. CloudFront copies the cache version to all the edge location servers around the world.

In this unit, we will set up the content version so we can refresh the cache with the most up-to-date data according to version updates.

1. Add a variable content_verison

Add the content_version to the variables.tf file. Pay attention to the file and directory level:

  • ./modules/terrahouse_aws/varaibles.tf
variable "content_version" {
description = "The content version. Is a positive integer starting at 1."
type = number

validation {
condition = var.content_version > 0 && floor(var.content_version) == var.content_version
error_message = "The content_version must be a positive integer starting at 1."
}
}
  • variables.tf (at root)
variable "content_version" {
type = number
}

2. Disable etag using lifecycle

lifecycle is a useful meta-argument that we can use to control the behaviour of resources. There are 4 arguments — create_before_destroy, prevent_destroy, ignore_changes, and replace_triggered_by. In this step, we apply ignore_changes on etag to stop Terraform from updating the stack upon changes to files tagged with etag.

⚠️Before implementing the lifecycle on etag, make sure that your etag works correctly and detects file changes. I updated my index.html file to observe its behaviour and it did apply the change set.

Add the following snippets to the resource storage definition in the module. We are disabling the etag and placing a trigger that will help terraform pick up changes in the variable content_version.

  • ./modules/terrahouse_aws/resource-storage.tf
resource "aws_s3_object" "index_html" {
bucket = aws_s3_bucket.website_bucket.bucket
key = "index.html"
source = var.index_html_filepath
content_type = "text/html"

etag = filemd5("${path.root}/public/index.html")
+ lifecycle {
+ replace_triggered_by = [terraform_data.content_version.output]
+ ignore_changes = [etag]
+ }
}

...

+ resource "terraform_data" "content_version" {
+ input = var.content_version
+ }

Then terraform apply so that the disabling etag and the trigger on content_version update take effect. Then, try updating the index.html file then terraform plan to test if etag is correctly NOT triggered.

3. Trigger updates on content_version update

Andrew tries updating the content_version value in terraform.tfvars. Then terraform apply. However, nothing changes.

# terraform.tfvars
content_version = 2

Andrew figures out that the problem was the incorrect way we were referencing the variable content_version in the module in main.tf at root. The version value was hard-coded. Modify it to refer to the actual variable.

module "terrahouse_aws" {
source = "./modules/terrahouse_aws"
user_uuid = var.user_uuid
bucket_name = var.bucket_name
index_html_filepath = var.index_html_filepath
error_html_filepath = var.error_html_filepath
- content_version = 1
+ content_version = var.content_version
}

Then do this:

  • Change the content_version value in variables.tfvars
  • tf apply — auto-approve

Terraform correctly detected the update in the content_version value and applied the change set accordingly.

New <div> section in my index.html for CloudFront distribuiton 😊

Troubleshooting

  • “content_version” is required, but no definition was found.

In the main.tf at root, add content_version in the terrahouse_aws module.

# ./main.tf
module "terrahouse_aws" {
source = "./modules/terrahouse_aws"
user_uuid = var.user_uuid
bucket_name = var.bucket_name
index_html_filepath = var.index_html_filepath
error_html_filepath = var.error_html_filepath
+ content_version = var.content_version
}

--

--

Gwen Leigh

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