Date: 2026-05-11
Time: 15:49
This is a complete Azure infrastructure provisioning example that demonstrates FTL2's cloud automation capabilities. It provisions a full web application stack — resource group, virtual network, subnets, security group, public IP, NIC, and a Linux VM — then configures the VM with nginx over SSH. It showcases FTL2's async context manager API, Ansible collection integration (azure.azcollection), secret bindings, state management, dynamic host registration, and check mode, all in a single Python script.
Three invocation modes via CLI flags:
uv run python example_azure_web_stack.py # Full provision + configure
uv run python example_azure_web_stack.py --check # Dry run (no changes)
uv run python example_azure_web_stack.py --teardown # Delete everything
The core pattern is async with automation(...) as ftl: — the automation context manager handles setup, collection installation, and cleanup. Modules are called via dot-notation on the ftl object using the FQCN path:
await ftl.azure.azcollection.azure_rm_resourcegroup(
name=RESOURCE_GROUP,
location=LOCATION,
tags={"environment": "demo", "managed_by": "ftl2"},
)
After provisioning, the script dynamically registers the new VM as a host and runs commands against it using host targeting (ftl[VM_NAME].command(...)).
automation() context manager parameters used:
autoinstalldeps=True — automatically installs the azure.azcollection if missingcheck_mode=bool — enables dry-run mode (no actual changes)verbose=True — detailed outputsecret_bindings — maps module FQCN patterns to env var names for credential injection (wildcard azure.azcollection.* applies to all modules in the collection)state_file — path to a JSON file for persisting provisioned resource state across runsRequired environment variables:
AZURECLIENTID, AZURESECRET, AZURESUBSCRIPTIONID, AZURETENANT — Azure service principal credentialsAZUREVMSSH_PUBKEY (optional) — SSH public key for VM accessState API:
ftl.state.add(key, dict) — persist resource metadataftl.state.remove(key) — remove on teardownDynamic host registration:
ftl.addhost(hostname, ansiblehost, ansible_user, groups) — register a host for immediate useawaited before the next.not check_mode and not ftl.failed — avoids configuring a VM that wasn't actually created.state="absent" and forcedeletenonempty=True on the resource group, which cascades to all contained resources.ftl.results provides a list with .success and .changed attributes; ftl.errors gives structured error objects with .module and .error fields.ftl.failed flag: A boolean that tracks whether any operation has failed during the session.ftl[VMNAME].command(...) and ftl[VMNAME].ansible.builtin.service(...) show how to run modules against a specific registered host rather than all hosts.ftl2.automation — the main user-facing entry point for FTL2azure.azcollection (installed via ansible-galaxy collection install or auto-installed by autoinstalldeps)azurermresourcegroup, azurermvirtualnetwork, azurermsubnet, azurermsecuritygroup, azurermpublicipaddress, azurermpublicipaddressinfo, azurermnetworkinterface, azurerm_virtualmachine, ansible.builtin.command, ansible.builtin.service.ftl2-state-azure.json — shared between provision and teardown runs for tracking what was created