Skip to content

Importing ARM Templates

llms.txt lists every page for an agent
Optional: hand this page to your coding agentThe steps work by hand too.
Show the whole prompt
Read https://intentius.io/chant/lexicons/azure/importing/.
Run `npx chant import <template.json>` for each ARM template I name, and check that `npx chant build` writes a template with the same resources, parameters and dependsOn as the original.
Run `npx chant lint src`, fix what it finds, and open a pull request with src/ and a list of anything the import left out or changed. Keep the original templates.
Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.

The Azure lexicon can parse existing ARM template JSON and generate equivalent chant TypeScript code.

Terminal window
# Import an existing ARM template
chant import template.json
# This creates src/main.ts with typed resource declarations

The import pipeline has two stages:

  1. Parser (ArmParser) — Parses ARM JSON into an intermediate representation (IR)
  2. Generator (ArmGenerator) — Converts IR to idiomatic TypeScript
  • Resources — All resources with their types, names, and properties
  • Parameters — Converted to CoreParameter declarations
  • Resource-level fields — sku, kind, identity, tags, zones, plan, location
  • Bracket expressions — Converted to intrinsic function calls:
    • [resourceId(...)] becomes ResourceId(...)
    • [reference(...)] becomes Reference(...)
    • [parameters('name')] becomes parameter reference
    • [resourceGroup().location] becomes Azure.ResourceGroupLocation
    • [subscription().subscriptionId] becomes Azure.SubscriptionId
    • [concat(...)] becomes Concat(...)
    • [uniqueString(...)] becomes UniqueString(...)
  • dependsOn — Preserved as dependency declarations

Input ARM template:

{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string",
"metadata": { "description": "Storage account name" }
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-05-01",
"name": "[parameters('storageName')]",
"location": "[resourceGroup().location]",
"kind": "StorageV2",
"sku": { "name": "Standard_LRS" },
"properties": {
"supportsHttpsTrafficOnly": true
}
}
]
}

Generated TypeScript:

import { StorageAccount, Azure } from "@intentius/chant-lexicon-azure";
export const storage = new StorageAccount({
location: Azure.ResourceGroupLocation,
kind: "StorageV2",
sku: { name: "Standard_LRS" },
supportsHttpsTrafficOnly: true,
});

The lexicon detects ARM templates by checking for:

  • A $schema property containing deploymentTemplate
  • A resources array
Terminal window
# Auto-detect and import
chant import template.json # detects ARM format automatically
  1. Import an existing ARM template to TypeScript
  2. Modify the TypeScript (add resources, apply composites, etc.)
  3. Build back to ARM JSON
  4. Deploy with Azure CLI
Terminal window
chant import legacy-template.json
# Edit src/main.ts as needed
chant build --output dist/template.json
az deployment group create --template-file dist/template.json

chant