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:

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"
    }

I 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!

Brendan Thompson

Principal Cloud Engineer

Azenix

Discuss on Twitter