Announcing my Scratch Terraform provider
Brendan Thompson • 29 October 2021 • 4 min read
Since the advent of the for
expression, and for_each
meta-argument in 2018 as part of
Terraform 0.12 Preview I have created many weird and wonderful loops. Terraform 0.12
was released to GA in May 2019, which meant the adoption of these features increased heavily and
saw the demise of count
meta-argument.
Creating simple loops is easy, but the complexity lies when you have complex, multi-layered input/config
data that you need to loop through. For a fair chunk of this, you can develop those loops using locals
blocks. However, they do not give you a real feel for how it will reach within a resource
for_each
. Until now, I would often create a separate project in a scratch
directory, mock
out some of the code I was developing, and run my for_each
's on something basic like a
random_string
. The use of random_string
was fine, but it did not output any
information about the maps being used in the for_each
, making it more like guessing about
attributes on an object.
All of this lead me to develop the new provider we are talking about today
terraform-provider-scratch
. This provider is in its earliest stage of development,
and it has already proven to be pretty useful.
Currently the provider supports the following resources:
scratch_bool
scratch_list
scratch_map
scratch_number
scratch_string
These provide some basic scenarios for developing loops. You can read more about these types on the docs page.
The next feature to add to this provider is the ability to test dynamic
blocks, which also
consumes a for_each
meta-argument and can be pretty confusing sometimes on which properties you
have available, and what the result of their output is.
The following is an elementary and quick example of using the provider with some local variables.
First, we will declare our provider and ensure that it is pulling from the correct place.
terraform {
required_providers {
scratch = {
source = "registry.terraform.io/brendanthompson/scratch"
}
}
}
provider "scratch" {}
Now we set up the locals
that we will use as our config. (Be warned, it's pretty complex!)
locals {
animals = {
cat = {
sound = "meow"
colours = ["ginger", "black", "white"]
average_age = 15
}
dog = {
sound = "woof"
colours = ["brown", "blonde", "white"]
average_age = 13
}
}
}
Now we have our config; we can consume it using the providers scratch_string
resource.
resource "scratch_string" "animal_sound" {
for_each = local.animals
description = format("Animal: %s", each.key)
in = each.value.sound
}
As can be seen, this is very basic; all we are passing in is the sound and a description that is
the key. The description
attribute is entirely optional but helpful in providing more context.
The output of the above as a terraform apply
is:
# scratch_string.animal_sound["cat"] will be created
+ resource "scratch_string" "animal_sound" {
+ description = "Animal: cat"
+ id = (known after apply)
+ in = "meow"
}
# scratch_string.animal_sound["dog"] will be created
+ resource "scratch_string" "animal_sound" {
+ description = "Animal: dog"
+ id = (known after apply)
+ in = "woof"
}
darwin_arm64
runners on GitHub Actions so I am having to build that provider version locally. I will look into ways of giving support for this long-term. This is currently being tracked in Support for darwin_arm64
architectureI currently have a few people mucking around with the provider and giving me some feedback, once all of that has come back through, and any required changes made, I am going to do a more in-depth post on how to use it and when.
Hopefully, you're interested in testing this out and providing some feedback through GitHub Issues or Discussions!