Cattle: multi-stack greenfield (the golden path)

Tags: Modeling · Automation · Self-host Substrate: bare Terraform + GitHub Actions (greenfield, one stack per entity)

The canonical Terrantula pattern for greenfield multi-tenant SaaS infrastructure. If you're starting a fresh IaC repo and want Terrantula to drive it from day one, this is the layout. It exercises the full cascade: one command creates the entity graph and opens the right PRs in the right dependency order.

What you'll see

Every customer needs a dedicated AWS sub-account, an Argo CD project, a cluster binding, and the tenant control-plane resources that compose all three. Each lives in its own Terraform stack with its own state file, and the Tenant stack reads the upstreams via terraform_remote_state — so it must apply after them.

One OnboardTenant command drives the whole cascade:

  1. A create-entity operation creates the Tenant entity (pending).
  2. Cascade createEntity rules create three more entities — AWSAccount, ArgoProject, ClusterBinding — plus three relationships from the tenant to each. (4 entities, 3 relationships.)
  3. Each EntityType declares its applier, so four Apply Actions auto-fire: ApplyAWSAccount, ApplyArgoProject, ApplyClusterBinding, and ApplyTenant.
  4. Action.dependsOn gates ordering. The three upstream applies fire immediately, each opening a PR with one entity's Terraform. ApplyTenant depends on all three; it inspects the graph, sees the upstreams aren't done, and transitions to blocked.
  5. As each upstream PR merges, a postMergeDispatch fires a repository_dispatch event; one entity-generic workflow runs terraform apply in that entity's directory and calls back.
  6. After the third upstream succeeds, the block-and-resume scanner unblocks ApplyTenant, which opens the tenant PR. Merge → dispatch → apply → callback → Tenant-acme becomes active.

One command, the right four PRs in the right order, no human orchestration. Each workflow runs terraform apply; Terrantula opens the PRs and never applies.

Try it

run-demo.sh boots a local stack, applies the blueprint, fires OnboardTenant, and asserts the cascade graph. Without a real GitHub token the upstream PR opens fail with a 401 (expected); the cascade-graph assertions still pass — 4 entities, 3 relationships, 4 Apply ActionRuns, and ApplyTenant reaching blocked.

bash examples/cattle-multi-stack-greenfield/run-demo.sh

With real PRs against a fork of customer-iac-repo/:

export GITHUB_TOKEN=<your-pat-with-repo-scope>
export GITHUB_TARGET_REPO=<your-org>/<your-iac-repo-fork>
bash examples/cattle-multi-stack-greenfield/run-demo.sh

Key files

FileWhat it is
run-demo.shThe end-to-end runner (local stack + cascade-graph assertions).
terrantula/blueprint.yaml4 EntityTypes + 3 RelationshipTypes + 4 Apply + 4 Deprovision actions + OnboardTenant with cascadeRules.
customer-iac-repo/README.mdThe directory + workflow conventions the customer's repo follows.
customer-iac-repo/.github/workflows/terrantula-entity-apply.ymlThe entity-generic terraform apply workflow (one for the whole fleet).
customer-iac-repo/infra/_modules/Reusable per-entity-type modules (aws-account, argo-project, cluster-binding, tenant).

View on GitHub

examples/cattle-multi-stack-greenfield