04 December 2024 ~ 4 min read
Refactoring monsternames-api to use modern terraform

Benjamin Clark
Part 4 of 4 in Infrastructure as Code (IaC)
Introduction

Over the course of several blog posts, I mentioned how:
-
I created a RESTAPI many moons ago based on pseudo-random generation of monster names
-
That led to me managing GitHub with GitHub and Terraform to get control of the repos I’d need
That last blog post was over a year ago now, and I’ve been doing things differently since then. For starters, my approach to Terraform has matured enough for me to coin the term “Terraform with data-structures and algorithms”… which I swiftly implemented in my professional career for multiple corporate organisations, and then gave a talk about to a room full of other professionals on the 14th November this year.
(Said talk is recorded, if you’re intrigued, and available on youtube)
Which got me thinking, there must be a better way to do this refactor than I originally intended.
The goal
To take onboard my ideas around Terraform with Data Structures and Algorithms and apply them to the refactor of monsternames-api. Namely:
-
Have a single repository responsible for all Infrastructure and Application code
-
Ensure parity of service
-
Reduce cost!
The actual step
They say that code is self-documenting. In this case, I believe the paradigm I’ve used for Terraform holds this to be true so there’s not much to say here other than… here’s the code: https://github.com/sudoblark/sudoblark.monsternames.api.
I’ve used my ideas around data-structure driven Terraform to make the Infrastructure super simple to understand, for example here’s the directory layout in respect to Terraform:

Pretty simple, we know our fundamental building blocks for this are:
-
Some S3 files that are uploaded into a bucket (additional_s3_files)
-
An API Gateway configuring a RESTAPI
-
One or more IAM Roles
-
One or more lambdas
-
One or more s3 buckets
This holds even more true if we inspect one of the locals.tf
entrypoints for our modules, for example here is the locals.tf
for additional_s3_files
:
locals.tf
/*
Data structure
---------------
A list of dictionaries, where each dictionary has the following attributes:
REQUIRED
---------
- name: : Friendly name used through Terraform for instantiation and cross-referencing of resources,
only relates to resource naming within the module.
- source_folder : Which folder where the {source_file} lives.
- source_file : The path under {source_folder} corresponding to the file to upload.
- destination_key : Key in S3 bucket to upload to.
- destination_bucket : The S3 bucket to upload the {source_file} to.
OPTIONAL
---------
- template_input : A dictionary of variable input for the template file needed for instantiation (leave blank if no template required)
*/
locals {
raw_s3_files = [
{
name : "config",
source_folder : "application/swagger_ui/",
source_file : "index.html",
destination_bucket : local.known_buckets.assets.name,
destination_key : "swagger_ui/index.html",
},
]
}
Well that’s incredible simple. The rest of the Terraform should follow suite… if you understand the locals.tf
files - which have a well-documented interface and are simply just data structures - you understand the Infrastructure.
Regarding the application code, this is a little more complex but not overly so. In fact, the README.md
file in the repository explains it in great depth… so just read that!
The result
Deploying this stack via GitHub actions was fully successful: https://github.com/sudoblark/sudoblark.monsternames.api/actions/runs/12159130971.
And the frontend at https://monsternames.sudoblark.com/ is live:

A simple GET or POST works as expected. Lovely stuff, and hugely more simple than the absolute mess I first produced back in 2021.
It also quite neatly demonstrates my principles for data-structure driven Terraform in a more concrete manner… hopefully being a useful example I can use at further conferences!
The usage of cloud-native architecture - removing the expensive MySQL database I had previously - also means running the thing will be about 1/20th of the cost of before… simpler, and cheaper? Win-win!
Conclusion
So that’s it. A fairly short blog post, as the new paradigm I’ve developed hopefully means you can just read the code as-is and it all makes sense!
Also a huge weight off my shoulders… I’ve been meaning to refactor this for ages, and getting to do so with the new ways of working I’ve developed is just the cherry on top.
Part 4 of 4 in Infrastructure as Code (IaC)