Docs
Open the console →
Guides

Import Terraform Registry modules as blueprints

Platform staff import verified Terraform Registry modules as platform-global blueprints — Cushy VENDORS the module source, parses its variables.tf into form fields, and materializes the source into each org's workspace at apply.

Cushy imports public Terraform Registry modules as platform-global blueprints. Import vendors the module: it downloads the module's .tf source, parses its variables.tf into form fields, and stores the source WITH the blueprint. The blueprint then shows up in every organization's Deploy a blueprint form; each org picks its own infra repo at workspace-create, and the source is materialized into that repo at apply.

Imported by Cushy

Imports are performed by the Cushy platform team. Your organization consumes the imported blueprints from the catalog; you do not run the importer.

Two ways to import

  • Browse & vendor — search the registry (by text, provider, verified-only), preview a module's parsed fields + its registry link + vendored file list, then Vendor & import.
  • Seed top verified — bulk-vendor the top-N verified modules by downloads (optionally filtered to one provider). Non-mappable providers are skipped and reported.

How a module becomes a blueprint

Import maps the registry provider to a cloud (aws→AWS, google→GCP, azurerm→AZR, alicloud→ALI — anything else is skipped), resolves the module's GitHub source, downloads the archive (bounded: ≤60 .tf files, ≤1 MB total), and parses its `variables.tf` with a hand-written HCL type parser — NOT the registry's input metadata. The parsed fields, the module template (a LOCAL-path module block) and the vendored source files are stored on the platform custom-blueprints row (id custom/platform/<namespace>-<name>-<provider>). No Git repo is written at import.

  • string → text field · bool → toggle · number → numeric field.
  • object({…}) → a nested field group: each attribute is its own input (an optional() attribute is not required, and its default applies when left blank).
  • list(…)/set(…)/tuple([…]) → a repeatable list: use + Add to add an entry and × to remove one; each entry renders the element's schema (a list(object({…})) is a list of nested groups).
  • map(…) → repeatable key/value rows.
  • A tags map becomes the standard tags field so the mandatory-tags policy is satisfiable.
  • A variable with no default is required; a variable with a default is optional (its module default applies when left blank).
  • Only genuinely-exotic HCL types (user-defined type aliases, ${} interpolation in a type, deeply heterogeneous tuples) fall back to a passthrough raw-HCL/JSON text field.

Planning + applying a vendored blueprint

Composing the plan wraps the module in a single Terraform module block with a LOCAL source path: module "<slug>" { source = "./blueprints/<slug>" …your inputs }, plus the platform-stamped terraform/provider/backend blocks (no version — it is a local path). At apply, Cushy materializes the vendored .tf under terraform/workspace-<id>/blueprints/<slug>/ next to main.tf, so ./blueprints/<slug> resolves in-dir. Deleting the workspace prunes that directory.

Policy and cost are approximate for a module

A module is opaque at compose time — Cushy cannot see the resources it will create until tofu plan expands it. So the plan shows ONE placeholder resource, and the policy (no-public-bucket / mandatory-tags / region-allowlist) and cost estimate run on that placeholder. The real, per-resource policy and cost only materialize when the real runner runs tofu plan on the expanded module.

Limitations

  • Apply is recorded-only unless real provisioning is enabled for the target account — same as every blueprint.
  • Nested/repeatable inputs are live (object → nested group, list → repeatable entries). optional() and other complex defaults are best-effort — a field left blank uses the module's own default. Binding a NESTED input to another workspace's output is deferred (top-level inputs can still be bound).
  • Vendoring supports public GitHub module sources (and direct .tar.gz archives); private registries / private repos and non-GitHub git hosts are a follow-up. Remote submodule sources inside a module stay remote (fetched at terraform init).
  • Bounded by hard caps: ≤60 .tf files, ≤1 MB total source per blueprint, ≤8 MB archive. Over-cap or an unreachable/unsupported source is an honest error — never a half-stored blueprint.
  • Because the source is materialized into every workspace dir, N workspaces on one blueprint keep N copies in the repo (the cost of a self-contained, standalone-applyable hydrate dir).
  • Removing an imported blueprint disables it (platform rows are never hard-deleted).
Where the importer points

The importer reads the public Terraform Registry and GitHub. Requests are bounded (caps + per-call timeouts) and degrade to an honest error if a source is unreachable — never a fabricated blueprint.