terragrunt-engine-go: A New flight-sync Example Engine

I looked at the last week of commits in terragrunt-engine-go, the Go library home for Terragrunt Engine implementations and examples. Two commits landed, 21 files changed, about 1274 new lines. The headline is the flight ID and token feature (#73), which teaches engines to share one credential across all processes of a Terragrunt invocation.

The problem: one credential exchange per unit

Terragrunt starts one engine process per unit. Without coordination, a terragrunt run --all across ten units makes ten separate credential exchanges with the auth server. That is wasteful, and it invites rate limits or audit noise on anything real.

The fix comes from the Terragrunt side: one invocation is called a flight, and Terragrunt now sends two fields in every InitRequest of a flight:

  • flight_id: a UUIDv7, not secret, same for every engine process in the flight
  • flight_token: 32 random bytes, secret, also shared across the flight

The protocol change shows up in the regenerated proto/engine.pb.go.

How the example engine shares credentials

Most of the code this week lives in a new example under examples/flight-sync. The flow is simple:

  1. The engine opens a directory named after flight_id under its state directory.
  2. It takes an exclusive lock on credential.lock. Other engines wait.
  3. It reads credential, stored encrypted with AES-GCM under a key derived from flight_token. If the file is missing, expired, or fails to decrypt, it exchanges fresh with the auth server and writes it back.
  4. It releases the lock. The next engine finds the stored credential.

So the first engine to grab the lock exchanges, and everyone else reuses its credential. Engines that receive no flight, from older Terragrunt releases, still exchange per process. Locking is platform specific: see lock_unix.go and lock_windows.go in the flight package.

The README shows what this means in practice. With flight support, the stand-in auth server prints a single exchange 1 for a three unit run. Without it, you get one exchange per unit.

Running the example yourself

A Makefile builds terragrunt-engine-flight-sync and a small stand-in auth server, flight-sync-auth, which returns a random credential per exchange and counts them. A three unit run looks like this:

./flight-sync-auth &
cd live
export TG_EXPERIMENTAL_ENGINE=1
export TG_ENGINE_SKIP_CHECK=1
terragrunt run --all plan

Two environment variables configure the engine:

  • FLIGHT_SYNC_AUTH_URL: where to exchange credentials, default http://127.0.0.1:8080/exchange
  • FLIGHT_SYNC_STATE_DIR: where flight directories live, default under the user cache dir

engine/main_test.go starts engine processes the way Terragrunt does and sends them a shared flight, so make test covers the reuse case. The example landed in the separate chore commit adding the example.

What to watch

  • Old flight directories are never cleaned up. The README says a real engine would remove those whose UUIDv7 timestamp is old. Expect cleanup logic in a future pass.
  • Engines that predate flight support still fall back to per process exchange. If you run an engine behind Terragrunt, check your Terragrunt version before assuming credential reuse.
  • The example is the reference for how engine authors should handle flight_id and flight_token. If you maintain a custom engine, this is the pattern to copy.

← All updates