Skip to main content

azure-vm-sdk

Python SDK for managing Azure VMs via OpenTofu.

Prerequisites

  • Python 3.11+
  • uv package manager
uv sync

Usage

Single VM

from azure_vm import AzureClient

client = AzureClient(resource_group="my-rg", location="westeurope")
vm = client.launch(name="my-vm", vm_size="Standard_B2s")
print(vm.info())
vm.delete()

SSH connection retries

SSH connections retry transient network failures up to six times by default. The delay doubles from 1 second to a 10-second cap, with jitter between half and all of each delay. Failed sessions are closed before the next attempt. Authentication, host-key and configuration errors fail immediately; commands that have already started are never replayed.

Set ssh_connect_attempts on AzureClient or AzureVM to change the attempt limit (1 disables retries). ssh_connect_timeout defaults to 15 seconds and limits each TCP connect, SSH banner and authentication wait separately. A new connection is also retried when reconnecting an expired cached session.

Multiple VMs in parallel

Use launch_many to create N VMs simultaneously. All VMs are provisioned in parallel; if any one fails the already-created VMs are destroyed automatically before the exception is re-raised (fail-fast with rollback).

from azure_vm import AzureClient, VmConfig

client = AzureClient(resource_group="my-rg", location="westeurope")

# Different names, sizes, and images
vms = client.launch_many(
    [
        VmConfig(
            name="frontend",
            vm_size="Standard_B1s",
            image_urn="Canonical:0001-com-ubuntu-server-noble:24_04-lts:latest",
        ),
        VmConfig(
            name="backend",
            vm_size="Standard_B2s",
            image_urn="Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest",
            disk_size_gb=64,
        ),
        VmConfig(
            name="db",
            vm_size="Standard_D2s_v3",
            disk_size_gb=128,
        ),
    ]
)

for vm in vms:
    print(vm.name, vm.info().ipv4)

VmConfig accepts the same keyword arguments as launch:

Field Default Description
name None (auto-generated) VM name
vm_size "Standard_B1s" Azure VM size
disk_size_gb 30 OS disk size
image_urn None (Ubuntu 24.04 LTS) Marketplace image URN
cloud_init_config None cloud-init dict or YAML string
ssh_key_path None (inherits from client) Path to SSH public key

max_workers caps the thread pool size (default: one thread per VM):

vms = client.launch_many(configs, max_workers=4)

End-to-end smoke test

Provision a real Azure VM, wait for SSH readiness, run a verification command, and tear it down. Requires Azure credentials and OpenTofu installed.

# Prerequisites
az login
export AZURE_RESOURCE_GROUP=my-resource-group
export AZURE_LOCATION=westeurope
export AZURE_SSH_PUBLIC_KEY=~/.ssh/id_rsa.pub   # optional

# Run with defaults (single VM)
uv run azure-vm-e2e

# Custom VM size and image
uv run azure-vm-e2e --name my-test-vm --vm-size Standard_D2s_v3 \
    --image-urn "Canonical:0001-com-ubuntu-server-noble:24_04-lts:latest" \
    --timeout 300

# Create 3 identical VMs in parallel (names: worker-0, worker-1, worker-2)
uv run azure-vm-e2e --count 3 --name worker --vm-size Standard_B2s

# Create VMs with different names, sizes, and images
uv run azure-vm-e2e --configs '[
  {"name": "frontend", "vm_size": "Standard_B1s"},
  {"name": "backend",  "vm_size": "Standard_B2s", "disk_size_gb": 64},
  {"name": "db",       "vm_size": "Standard_D2s_v3", "disk_size_gb": 128}
]'

Output shows a 5-step progress:

[1/5] Launching VM 'e2e-1747152000' (size=Standard_B1s) ...
       launch completed in 52.3s
[2/5] Waiting for public IP (timeout=300s) ...
       got IP 20.1.2.3 in 18.5s
[3/5] Waiting for SSH on 20.1.2.3:22 ...
       SSH ready on 20.1.2.3 in 42.1s
[4/5] Running verification command ...
       exit=0  stdout=Linux e2e-1747152000 6.8.0-1020-azure ...
       state=running  location=westeurope  resource_group=my-rg
[5/5] Deleting VM 'e2e-1747152000' ...
       done.

SUCCESS — VM 'e2e-1747152000' completed full lifecycle.

Running tests

# Unit tests only (default, no Azure/OpenTofu needed)
uv run pytest

# Include integration tests (requires Azure + OpenTofu installed).
# --no-cov: the 80% coverage gate targets the unit suite, so it would fail on
# an integration-only run.
uv run pytest -m "integration" --no-cov

# Coverage report (already on by default, with an 80% gate; shown explicitly)
uv run pytest --cov=azure_vm --cov-report=term-missing

Quality checks

# Run all three (ruff + basedpyright + import-linter)
uv run azure-vm-quality

Individual checks:

uv run ruff check .                    # Linting (pycodestyle, pyflakes, isort, bugbear, pyupgrade, pydocstyle, …)
uv run ruff format .                   # Formatting
uv run basedpyright                    # Type checking
uv run bandit -c pyproject.toml -r src # Security static analysis
uv run lint-imports                    # Architecture contract enforcement
uv run pre-commit run --all-files      # Every hook above, all at once

Code evaluation tools

Full audit

Runs automated detection for bugs, excessive coupling, simplification opportunities, code smells, and god classes.

uv run azure-vm-eval           # Human-readable report
uv run azure-vm-eval --json    # JSON output (for CI / machine consumption)

Checks performed:

Category What it detects
Bugs Bare/broad except, raise without from, unused exception classes, mutable defaults
Coupling High fan-out modules, circular dependencies, zero fan-in modules
Simplifications Functions over 30 lines, duplicated logic
Smells God classes (lines, methods, fan-out), modules over 250 lines, __init__ leaking internals

Package cohesion report

Measures internal cohesion and inter-module coupling for every module in azure_vm.

uv run azure-vm-package-report           # Cohesion/coupling table
uv run azure-vm-package-report --edges   # Include individual import edges
uv run azure-vm-package-report --orphans # Show modules with zero internal deps

Metrics:

Column Meaning
internal Imports within the same module
outgoing Imports from other azure_vm modules
incoming Times this module is imported by other azure_vm modules
external Imports from third-party packages
instability outgoing / (incoming + outgoing) — 0 = highly stable (depended on by many), 1 = highly unstable (depends on everything)

Dependency graph visualization

uv run pydeps azure_vm --show-deps --max-bacon 2 --nodot

Rendering the diagram itself additionally needs Graphviz (dot) on PATH; --nodot skips that step and prints the dependency analysis as JSON.

Architecture contracts

Defined in .importlinter:

  1. models_and_exceptions_are_independent — foundation layer must not import higher-level packages
  2. backend_is_independent — _backend must not depend on vm or client
  3. internal_modules_are_independent — _templates, _workspace, _discovery must not depend on the public API layer

Project structure

src/azure_vm/
├── __init__.py        Public API re-exports
├── client.py          AzureClient — VM provisioning orchestrator
├── vm.py              AzureVM — single-VM operations (lifecycle, SSH, exec)
├── _workspace.py      Workspace — filesystem, template writing, scan, purge
├── _discovery.py      Azure Marketplace image discovery
├── _templates.py      HCL generation + image URN / SSH path helpers
├── _backend.py        CommandBackend protocol, TofuBackend, FakeBackend, run_command
├── models.py          VmConfig, VmInfo, VmState, ImageInfo
├── exceptions.py      Exception hierarchy
└── testing.py         Test doubles for consumers (FakeBackend, CommandResult)

Metadata

Release files for azure-vm-sdk 0.6.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for azure-vm-sdk 0.6.3
File Size Uploaded
azure_vm_sdk-0.6.3.tar.gz 139.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for azure-vm-sdk 0.6.3
File Interpreter ABI Platform
azure_vm_sdk-0.6.3-py3-none-any.whl Python 3 none any Details

Total release size: 175.0 kB

Release files / azure_vm_sdk-0.6.3.tar.gz

Download URL azure_vm_sdk-0.6.3.tar.gz
Size 139.4 kB
Tags Source
SHA-256 checksum
How to use checksums
33d7d2581180ef010da03b89aedab165e774d94ca79f63bc4ac907bb0aed11bb
BLAKE2b-256 checksum
How to use checksums
d950c0f9c611256c4e893bae9e1dd7b64e05fac9a6534410322a0f3e0dde660b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / azure_vm_sdk-0.6.3-py3-none-any.whl

Download URL azure_vm_sdk-0.6.3-py3-none-any.whl
Size 35.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f82f56bff060e2ccf31ddc09a9444c82802ee6d9eb145a34f9889b10ae154f35
BLAKE2b-256 checksum
How to use checksums
cedc7b774473475641ba6f5b554db6f6edbaab4548bce6fb3c60e6b091549af5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.3 This release

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page