Experimenting with Terraform in YAML

Why even try this

Terraform is one of the go-to tools for infrastructure as code.
However, once you start managing multiple environments (dev/prod, etc.), dealing with environment-specific differences becomes surprisingly tricky. Many people…


This content originally appeared on DEV Community and was authored by totegamma

Why even try this

Terraform is one of the go-to tools for infrastructure as code.

However, once you start managing multiple environments (dev/prod, etc.), dealing with environment-specific differences becomes surprisingly tricky. Many people have looked into Terragrunt as a solution to this problem.

Also, while Terraform’s dedicated language HCL (HashiCorp Configuration Language) is fairly approachable, using constructs like count or for fluently requires some practice. And at the end of the day, it’s almost entirely a Terraform-specific DSL — not something that can be easily reused elsewhere.

That’s why, in this article, I want to try something different: defining a Terraform project using YAML and its expression evaluator yisp.

With YAML + yisp, you can freely define and compose modules in more flexible ways, and the same knowledge can be applied to other YAML-based domains like Kubernetes manifests.

Whether this is practical or not is still questionable — but it might open up new ways to handle environment-specific variations.

Terraform JSON Syntax Refresher

Terraform usually expects .tf files written in HCL, but you can also provide configuration in JSON format.

For example, the following HCL file:

terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "2.4.0"
    }
  }
}

provider "local" {}

resource "local_file" "hello1" {
  content  = "1st Hello, World!"
  filename = "hello1.txt"
}

resource "local_file" "hello2" {
  content  = "2nd Hello, World!"
  filename = "hello2.txt"
}

Can be rewritten as JSON:

{
  "provider": {
    "local": {}
  },
  "resource": {
    "local_file": {
      "hello1": {
        "content": "1st Hello, World!",
        "filename": "hello1.txt"
      },
      "hello2": {
        "content": "2nd Hello, World!",
        "filename": "hello2.txt"
      }
    }
  },
  "terraform": {
    "required_providers": {
      "local": {
        "source": "hashicorp/local",
        "version": "2.4.0"
      }
    }
  }
}

Save this as <filename>.tf.json, and Terraform will happily accept it with the usual terraform apply.

What is yisp?

yisp is a small tool that lets you embed and evaluate expressions inside YAML.

For instance, this YAML:

# index.yaml
mynumber: !yisp
  - add
  - 5
  - 3

Evaluates to:

# result
mynumber: 8

by simply running yisp build ..

yisp also supports importing multiple YAML files, merging objects, or even outputting JSON instead of YAML.

In this experiment, we’ll use yisp to make Terraform JSON easier to author in YAML, and to manage environment-specific differences through imports and patching.

First Steps

Here’s a simple Terraform definition written in YAML:

# tf.yaml
terraform:
  required_providers:
    local:
      source: hashicorp/local
      version: "2.4.0"

---
provider:
  local: {}

---
resource:
  local_file:
    hello1:
      content: "1st Hello, World!"
      filename: "hello1.txt"

---
resource:
  local_file:
    hello2:
      content: "2nd Hello, World!"
      filename: "hello2.txt"

Then, in index.yaml, merge them into one object:

# index.yaml
!yisp
- lists.reduce
- - include
  - tf.yaml
- maps.merge

Running yisp build . will output the same JSON structure as shown earlier.

Using a Makefile

Terraform commands don’t accept configuration via stdin — they require an actual file. To streamline the workflow, let’s use a Makefile that automatically generates the JSON before running Terraform:

rendered.tf.json:
    yisp build . -o json > rendered.tf.json

init: rendered.tf.json
    terraform init

plan: rendered.tf.json
    terraform plan

apply: rendered.tf.json
    terraform apply

Now you can simply run make plan or make apply, and YAML will be converted to JSON on demand.

Modularizing for Environment Differences

Let’s go one step further and introduce modules to handle dev/prod variations.
Here’s the directory structure:

📁 .
├── 📁 base
│   ├── 📄 core.yaml
│   └── 📄 localfile.yaml
└── 📁 env
    ├── 📁 dev
    │   ├── 📄 index.yaml
    │   └── 📄 localfile.yaml
    └── 📁 prod
        ├── 📄 index.yaml
        └── 📄 localfile.yaml

Core config (base/core.yaml)

# base/core.yaml
terraform:
  required_providers:
    local:
      source: hashicorp/local
      version: "2.4.0"

---
provider:
  local: {}

Module definition (base/localfile.yaml)

# base/localfile.yaml
!yisp &main
- lambda
- [ props ]
- !quote
  resource:
    local_file:
      hello:
        content: !yisp
        - strings.format
        - "Hello: %s"
        - *props.name
        filename: "hello1.txt"

Module usage (env/dev/localfile.yaml)

# env/dev/localfile.yaml
!yisp
- import
- ["localfile", "../../base/localfile.yaml"]

---
!yisp
- *localfile.main
- name: "alice"

Final merge (env/dev/index.yaml)

# env/dev/index.yaml
!yisp
- lists.reduce
- - include
  - ../../base/core.yaml
  - localfile.yaml
- maps.merge

Evaluating this gives us:

# output
terraform:
  required_providers:
    local:
      source: hashicorp/local
      version: "2.4.0"
provider:
  local: {}
resource:
  local_file:
    hello:
      content: "Hello: alice"
      filename: "hello1.txt"

Here we get a local_file resource that writes "Hello: alice".
For production, you can simply adjust the parameters and reuse the same module.

Conclusion

In this article, we tried using yisp to define Terraform in YAML, while modularizing environment-specific differences.

It’s still uncertain whether this approach is practical in production, but it was an interesting discovery: just like Kubernetes’ kustomize helps manage manifest variations, we can experiment with similar ideas for Terraform.

If this piqued your interest, give it a spin on your own setup!


This content originally appeared on DEV Community and was authored by totegamma


Print Share Comment Cite Upload Translate Updates
APA

totegamma | Sciencx (2025-09-25T10:59:34+00:00) Experimenting with Terraform in YAML. Retrieved from https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/

MLA
" » Experimenting with Terraform in YAML." totegamma | Sciencx - Thursday September 25, 2025, https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/
HARVARD
totegamma | Sciencx Thursday September 25, 2025 » Experimenting with Terraform in YAML., viewed ,<https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/>
VANCOUVER
totegamma | Sciencx - » Experimenting with Terraform in YAML. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/
CHICAGO
" » Experimenting with Terraform in YAML." totegamma | Sciencx - Accessed . https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/
IEEE
" » Experimenting with Terraform in YAML." totegamma | Sciencx [Online]. Available: https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/. [Accessed: ]
rf:citation
» Experimenting with Terraform in YAML | totegamma | Sciencx | https://www.scien.cx/2025/09/25/experimenting-with-terraform-in-yaml-2/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.