Skip to content

Local Testing — Azure (floci-az)

floci-az emulates Azure’s resource CRUD but not the Microsoft.Resources/deployments provider, so az deployment has nothing to talk to. azApply closes the gap: it reads the ARM template chant synthesizes and PUTs each resource straight to floci-az’s ARM resource endpoints, in dependency order, resolving ARM expressions from live responses as it goes.

A storage account, described as data. It synthesizes to an ARM template:

// src/azure/infra.ts — StorageAccountSecure is a composite (secure defaults)
export const { storageAccount } = StorageAccountSecure({
name: "triostore",
location: "eastus",
sku: "Standard_LRS",
tags: { project: "cross-cloud-demo" },
});

chant run azure boots floci-az, builds the ARM template, applies it with azApply, verifies the account over the ARM endpoint, and removes the container.

ops/azure.op.ts
export default Op({
name: "azure",
taskQueue: "trio-azure",
phases: [
phase("Emulator", [flociAzUp()]),
phase("Build", [build(".", { script: "build:azure" })]),
phase("Apply", [azApply("dist/azure.json", { resourceGroup: "trio-rg", location: "eastus", endpoint: "http://localhost:4577" })]),
phase("Verify", [httpCheck("http://localhost:4577/subscriptions/.../providers/Microsoft.Storage/storageAccounts/triostore?api-version=2025-06-01")]),
phase("Teardown", [flociAzDown()]),
],
});

az deployment submits a whole template to the deployments provider and lets Azure order and resolve it. floci-az has no such provider, so azApply does that work itself:

  • Reads the ARM template chant emitted and ensures the resource group exists.
  • Orders resources by their resourceId/reference references — a referenced resource applies before the one that references it — and detects cycles.
  • Evaluates ARM expressions as it applies: resourceGroup(), subscription(), concat, uniqueString, resourceId(...), plus the runtime-state functions reference('name') and listKeys(id, apiVersion), resolved from the live PUT responses of resources applied earlier in the run.
  • PUTs each resource to {endpoint}{resourceId}?api-version=... and captures the response so later resources can reference it.

This is the same evaluation a real ARM deployment performs; azApply just runs it client-side against the emulator’s resource CRUD.

Requires Docker and curl on PATH.

Terminal window
cd examples/local-cloud-trio
npm install
chant run azure

azDelete is the inverse of azApply: it reads the same template and deletes the resources it declares, in reverse dependency order (a referrer goes before what it references), idempotently.

azApply also takes prune: true for an owned-only prune — after applying, it deletes chant-managed resources of a templated type whose name is no longer in the template. chant stamps a managed-by: chant tag on everything it applies and only ever prunes tagged resources, so a foreign resource sharing the group is never touched.

Drop the endpoint override and azApply targets real Azure ARM. The template, the ordering, and the expression evaluation are unchanged — only the resource-manager host differs.