apply

apply is the bulk-upsert primitive. It takes a list of catalog kinds — schema and data — and reconciles them against the project graph in one request, the same way terraform apply reconciles HCL against real resources. It supports plan-only diffs (dryRun), breaking-change gating (force), and post-apply deletions.

terrantula apply --file blueprint.yaml

Backed by POST /projects/:projectId/apply (RBAC: apply:write).

Request

The CLI normalizes one or more YAML/JSON documents (or a directory of them) into this envelope:

FieldTypeRequiredDefaultDescription
itemsAnyKind[]yesSchema + data declarations. Any of the seven kinds.
forcebooleannofalseAllow breaking schema changes (removing a state entities are in; removing a property with values).
deletionsDeletion[]no[]Schema-level kinds to delete after a successful apply, in dependency order.
dryRunbooleannofalsePlan-only — no writes. Returns a diff instead.

Minimal request

items:
  - kind: EntityType
    name: Tenant
    states: [pending, active]
    initialState: pending
  - kind: Entity
    entityType: Tenant
    name: acme
    state: active

Deletions

Only schema-level kinds may be deleted via apply. Entities and relationships are data and are removed through their own routes (or by lifecycle Actions).

FieldTypeRequiredDescription
kindEntityType | Cell | RelationshipType | Action | SecretyesThe schema kind to delete.
namestringyesThe name of the item to delete.
items: []
deletions:
  - { kind: Action, name: LegacyOnboard }
  - { kind: Cell, name: deprecated-pool }

Two-phase processing

Items are processed in two phases, auto-sorted by dependency order within each — you never hand-order a blueprint:

  1. Schema phaseEntityType, Secret, Cell, RelationshipType, Action.
  2. Data phaseEntity, Relationship.

Schema-then-data ordering is why a Cell referencing a freshly-declared EntityType, an Action referencing a new Cell, or an Entity of a new type all resolve correctly inside a single apply. deletions run after the apply, also in dependency order, so the caller never sequences N+1 calls.

Response

FieldTypeDescription
succeeded{ kind, name }[]Items applied successfully.
failed{ kind, name, error }[]Items that failed, each with its error.
skipped{ kind, name, reason }[]Items skipped, each with a reason.
diffDiffPresent only when dryRun: true.

The endpoint returns 200 when every item succeeds, and 207 (Multi-Status) when some items fail — inspect failed for the per-item errors.

Dry-run diff

When dryRun: true, no writes occur and each item is classified — mirroring terraform plan:

FieldTypeDescription
created{ kind, name }[]Items that would be created.
updated{ kind, name, changedFields }[]Items that would change, with the fields that differ.
unchanged{ kind, name }[]Items already matching the desired state.
deleted{ kind, name }[]Items that would be deleted (the requested deletions).
terrantula apply --file blueprint.yaml --dry-run

Breaking changes andforce

Two schema edits are treated as destructive and rejected by default with 409:

  • Removing a state that entities (or relationships) are currently in.
  • Removing a property that has existing values.

Re-run with force: true (CLI --force) to allow them. A dry-run (dryRun: true) also bypasses the destructive check, since it never writes.

Caveats

INFO

apply is the single ingress for declarative catalog changes — the CLI's import-terraform, the UI's bulk import, and terrantula applyall funnel into the same envelope and the same two-phase reconciliation.

WARNING

Deleting an EntityType cascades to its entities. In a dryRun, the deleted list reflects only the requested deletions — the EntityType deletion cascade is notexpanded in the diff. Verify cascades against the live graph before applying.

NOTE

dryRun still requires apply:write— a plan is gated the same as a real apply.

TIP

Keep your whole blueprint in version control and apply it as a directory: terrantula apply --file ./terrantula/. Top-level YAML/JSON files are merged into one atomic envelope; READMEs and other non-catalog files are skipped.