Skip to content

Terraform

There are some functions specific to AWS. Other Cloud providers will be added in the future.

BigConfig enables you to use Clojure instead of HCL. You should minimize the dynamic features of HCL that you use and use Clojure language features instead. count is an example of dynamic feature that you should avoid. The for expression in Clojure will achieve the same result. sort-nested-map will make sure the the JSON output is always the same, so that you can commit the main.tf.json like you do with main.tf and refactor you Clojure code with confidence because Git will signal to you unexpected changes of main.tf.json.

The sort-nested-map function ensures that the resulting JSON output is consistent. This allows you to commit the main.tf.json file to Git, just as you would with a main.tf file. Committing this file provides a safety net: if you refactor your Clojure code, Git will flag any unexpected changes in the main.tf.json file, giving you confidence in your refactoring process.

The deep-merge operation is essential in Terraform because it allows for the correct merging of attributes within blocks that share a namespace. This ensures that only the leaf nodes (individual attributes) are merged, preventing overwrites of entire nested structures.

(ns core
(:require
[big-config.utils :refer [deep-merge sort-nested-map]]
[big-tofu.core :refer [add-suffix construct]]
[big-tofu.create :as create]
[cheshire.core :as json]))
(let [{:keys [aws-account-id
region] :as data} {:aws-account-id "111111111111"
:region "eu-west-1"
:module "example"}
queues (->> (for [n (range 2)]
(create/sqs (add-suffix :alpha/big-sqs (str "-" n))))
flatten
(map construct))
kms (->> (create/kms :alpha/big-kms)
(map construct))
bucket (format "tf-state-%s-%s" aws-account-id region)
provider (create/provider (assoc data :bucket bucket))
m (->> [provider]
(into kms)
(into queues)
(apply deep-merge)
sort-nested-map)]
(json/generate-string m {:pretty true}))

It’s very common to get the AWS account id at runtime.

(construct caller-identity)
(root-arn caller-identity)

The defrecord Construct is used to construct any type of block. Naming is simplified by qualified keyword: ::foo becomes "org_app_foo::foo".

(ns org.app)
(construct (map->Construct {:group :data
:type :aws_iam_policy_document
:fqn ::foo
:block {}}))

You can reference any property.

(ns org.app)
(reference (map->Construct {:group :data
:type :aws_iam_policy_document
:fqn ::foo
:block {}})
:json)

Some arn for common AWS resources are already defined.

(arn (map->Construct {:group :resource
:type :aws_iam_role
:fqn ::foo
:block {:name "name"}}) "111111111111")
(arn (map->Construct {:group :resource
:type :aws_secretsmanager_secret
:fqn ::foo
:block {:name "name"}}) "111111111111" "us-west-1")