Skip to main content
Version: Next

Variable Management Standard

Standard Azure

DOCUMENT CATEGORY: Standard
SCOPE: All AzureLocal solution repositories
PURPOSE: Canonical variable naming, structure, and management pattern

Status: Active


Overview

Every AzureLocal solution repository follows a single, standardized pattern for managing deployment variables. This ensures consistency, validation, and automation compatibility across all solutions.

Core principle: One config file, one schema, one reference doc — per repo.

ArtifactLocationPurpose
Example configconfig/variables.example.ymlTemplate with placeholder values — copy to variables.yml
Active configconfig/variables.ymlEnvironment-specific values (never committed)
JSON Schemaconfig/schema/variables.schema.jsonValidation rules enforced by CI
Reference docdocs/reference/variables.mdHuman-readable variable catalog

Repository Matrix

RepositoryConfigSchemaReference DocCI Workflow
azurelocal-toolkitvariables.example.ymlschemareferencevalidate-config.yml
azurelocal-sofs-fslogixvariables.example.ymlschemareferencevalidate-config.yml
aurelocal-avdvariables.example.ymlschemareferencevalidate-config.yml
azurelocal-loadtoolsvariables.example.ymlschemareferencevalidate-config.yml
azurelocal-vm-conversion-toolkitvariables.example.ymlschemareferencevalidate-config.yml

Directory Structure

Every repository follows this layout:

repo-root/
├── config/
│ ├── variables.example.yml # Committed — template
│ ├── variables.yml # .gitignored — your values
│ └── schema/
│ └── variables.schema.json # JSON Schema for CI validation
├── docs/
│ └── reference/
│ └── variables.md # Human-readable variable catalog
└── .github/
└── workflows/
└── validate-config.yml # CI: validates example against schema

Naming Conventions

File Naming

FileNameNotes
Example configvariables.example.ymlAlways .example.yml, never .template.yml
Active configvariables.ymlNever committed
Schemavariables.schema.jsonDraft 2020-12 JSON Schema
Reference docvariables.mdAlways at docs/reference/variables.md

Variable Naming

ScopeConventionExample
Top-level sectionssnake_caseazure_local, session_hosts
Keys within sectionssnake_casesubscription_id, cluster_name
BooleansDescriptive nameenable_real_time: true
Secretskeyvault:// URIkeyvault://kv-name/secret-name
Azure resource IDsFull ARM path/subscriptions/.../providers/...
Enum valuessnake_caseauth_method: "managed_identity"

Section Organization

Each variables.example.yml is organized into logical sections separated by comment headers:

# =============================================================================
# Section Name
# =============================================================================
section_name:
key: "value"

Common sections across repos include:

  • azure — Subscription, tenant, resource group, location
  • keyvault — Key Vault name and auth method
  • azure_local — Cluster-specific configuration
  • tags — Resource tagging (present in every repo)

Solution-specific sections are documented in each repo's docs/reference/variables.md.


Secret Management

Secrets are never stored in plaintext in variables.yml. All sensitive values use the keyvault:// URI format:

credentials:
admin_password: "keyvault://kv-mysite/admin-password"

Resolution flow:

  1. Tool parses the URI → vault name + secret name
  2. Tool calls az keyvault secret show (or SDK equivalent)
  3. Secret value is passed directly — never written to disk

Repos that use Key Vault references: toolkit, sofs-fslogix, avd, loadtools


Schema Validation

Every repo includes a JSON Schema that validates the structure of variables.example.yml. The CI workflow runs on every PR and push to config/**:

# .github/workflows/validate-config.yml
name: Validate Config
on:
push:
paths: ['config/**']
pull_request:
paths: ['config/**']

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install pyyaml jsonschema
- run: |
python -c "
import yaml, jsonschema, sys
schema = yaml.safe_load(open('config/schema/variables.schema.json'))
data = yaml.safe_load(open('config/variables.example.yml'))
jsonschema.validate(data, schema)
print('Validation PASSED')
"

Getting Started with a New Repo

When adding a new solution repository to the org:

  1. Create config/variables.example.yml with solution-specific sections
  2. Create config/schema/variables.schema.json with Draft 2020-12 JSON Schema
  3. Create docs/reference/variables.md documenting every variable with type, required, description, and default
  4. Add .github/workflows/validate-config.yml (copy from any existing repo)
  5. Add config/variables.yml to .gitignore
  6. Update this page with a link in the Repository Matrix table