Infrastructure orchestration

Your config shouldn’t need a human to look things up first.

SpellCraft evaluates Jsonnet with live cloud APIs in reach, then emits plain Terraform JSON. Account IDs, existing buckets and enabled services are discovered while the configuration renders.

It does not replace Terraform and owns no state of its own. Adoption is incremental, and reversible: delete SpellCraft tomorrow and your infrastructure is exactly where you left it.

Start reading npm init spellcraft my-infra
Figure 1 — What runs when
manifest.jsonnet what you write evaluate SpellFrame plugins loaded AWS / GCP live, at render time real values render/main.tf.json — ordinary Terraform

A whole spell fits on a screen.

Top-level keys are filenames. Values are the file contents. That is the entire model — and the account number in this bucket name was never typed by anyone.

manifest.jsonnet
// Runs at evaluation time, against your real account.
local plugins = import "@c6fc/spellcraft-plugins/module.libsonnet";

local account = plugins.aws.auth.getCallerIdentity().Account;

{
  "providers.tf.json": {
    provider: plugins.aws.terraform.providerAliases("us-east-1"),
  },

  "artifacts.tf.json": plugins.aws.terraform.s3.bucket(
    "artifacts-%s" % account,
    "us-west-2",
    { versioning: "Enabled" },
  ),
}

Why not just write more Terraform modules?

Because three of the things you want from a module are not things a module can do.

I.

Modules don’t resolve dependencies

A module cannot declare that it needs another module at a version. Plugins are npm packages, so npm install does what it already does everywhere else in your stack — including transitively.

II.

There is no runtime before apply

Enabling the API a resource depends on has to happen first. Plugins coordinate on lifecycle events, so the bootstrap runs itself rather than living in a README as step zero.

III.

HCL cannot reach out

count and for_each are not a programming language. Jsonnet composes properly, and native functions call real APIs while the configuration is being evaluated.

The standard library

All 9 nodes →