From a6e8eaf6cdab1cc31cf20158216813ed5057a3d8 Mon Sep 17 00:00:00 2001 From: Kris Turner Date: Tue, 17 Mar 2026 09:46:02 -0400 Subject: [PATCH 1/2] refactor: standardize config directory structure (issue #15) - Rename configs/ to config/ (org-wide standard: singular) - Rename variables.template.yml to variables.example.yml (org-wide standard) - Move schema assets from config/variables/assets/ to config/schema/ - Rename infrastructure.schema.json to variables.schema.json - Update all path references across scripts, docs, and README - Update .gitignore to match new paths - Add config/variables.yml to .gitignore Resolves AzureLocal/azurelocal.github.io#15 --- .gitignore | 7 ++-- README.md | 6 ++-- .../Generate-AzureLocal-Parameters.ps1 | 6 ++-- {configs => config}/azure/.gitkeep | 0 .../azure/arm-templates/README.md | 6 ++-- .../cluster-deployment/README.md | 10 +++--- .../cluster-deployment/azuredeploy.json | 0 .../azuredeploy.parameters.ad.json | 0 .../azuredeploy.parameters.json | 0 ...azuredeploy.parameters.local-identity.json | 0 .../azure/arm-templates/examples/README.md | 0 .../single-intent-converged/README.md | 0 .../azuredeploy.parameters.ad.json | 0 ...azuredeploy.parameters.local-identity.json | 0 .../examples/three-intent-separated/README.md | 0 .../azuredeploy.parameters.ad.json | 0 ...azuredeploy.parameters.local-identity.json | 0 .../examples/two-intent-standard/README.md | 0 .../azuredeploy.parameters.ad.json | 0 ...azuredeploy.parameters.local-identity.json | 0 {configs => config}/infrastructure.yml | 0 .../schema}/master-registry.yaml | 4 +-- .../schema/variables.schema.json | 2 +- .../variables.example.yml | 25 ++++++++------ {configs => config}/variables/.gitkeep | 0 config/variables/readme.md | 32 ++++++++++++++++++ configs/variables/readme.md | 14 -------- docs/configuration/variables.md | 4 +-- docs/index.md | 4 +-- .../idrac-management/Enable-IdracVnc.ps1 | 6 ++-- scripts/common/idrac-management/README.md | 10 +++--- .../helpers/Connect-AzureCliSession.ps1 | 2 +- .../helpers/Connect-AzureSession.ps1 | 2 +- .../utilities/helpers/config-loader.ps1 | 6 ++-- .../powershell/Register-ResourceProviders.ps1 | 2 +- .../powershell/Set-RbacRoleAssignments.ps1 | 10 +++--- .../powershell/Test-RbacRoleAssignments.ps1 | 10 +++--- .../powershell/New-VirtualNetwork.ps1 | 2 +- .../powershell/Invoke-HardwareDiscovery.ps1 | 2 +- ...ke-Phase03OsConfiguration-Orchestrated.ps1 | 2 +- .../powershell/Deploy-AzureLocalCluster.ps1 | 2 +- ...voke-VerifyADDomainStatus-Orchestrated.ps1 | 6 ++-- ...nvoke-VerifyClusterHealth-Orchestrated.ps1 | 8 ++--- .../powershell/Deploy-AzureLocalCluster.ps1 | 2 +- ...nvoke-VerifyClusterHealth-Orchestrated.ps1 | 8 ++--- ...VerifyLocalIdentityConfig-Orchestrated.ps1 | 8 ++--- .../Get-VirtualSwitchName-Standalone.ps1 | 2 +- .../Invoke-SSHConnectivity-Orchestrated.ps1 | 2 +- .../Invoke-StorageCSV-Orchestrated.ps1 | 2 +- .../Invoke-StoragePaths-Orchestrated.ps1 | 2 +- .../monitoring/powershell/Monitor-Update.ps1 | 2 +- tools/Generate-SolutionConfig.ps1 | 12 +++---- tools/planning/S2D_Capacity_Calculator_6.xlsx | Bin 32984 -> 58043 bytes 53 files changed, 127 insertions(+), 103 deletions(-) rename {configs => config}/Generate-AzureLocal-Parameters.ps1 (98%) rename {configs => config}/azure/.gitkeep (100%) rename {configs => config}/azure/arm-templates/README.md (96%) rename {configs => config}/azure/arm-templates/cluster-deployment/README.md (94%) rename {configs => config}/azure/arm-templates/cluster-deployment/azuredeploy.json (100%) rename {configs => config}/azure/arm-templates/cluster-deployment/azuredeploy.parameters.ad.json (100%) rename {configs => config}/azure/arm-templates/cluster-deployment/azuredeploy.parameters.json (100%) rename {configs => config}/azure/arm-templates/cluster-deployment/azuredeploy.parameters.local-identity.json (100%) rename {configs => config}/azure/arm-templates/examples/README.md (100%) rename {configs => config}/azure/arm-templates/examples/single-intent-converged/README.md (100%) rename {configs => config}/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.ad.json (100%) rename {configs => config}/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.local-identity.json (100%) rename {configs => config}/azure/arm-templates/examples/three-intent-separated/README.md (100%) rename {configs => config}/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.ad.json (100%) rename {configs => config}/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.local-identity.json (100%) rename {configs => config}/azure/arm-templates/examples/two-intent-standard/README.md (100%) rename {configs => config}/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.ad.json (100%) rename {configs => config}/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.local-identity.json (100%) rename {configs => config}/infrastructure.yml (100%) rename {configs/variables/assets => config/schema}/master-registry.yaml (99%) rename configs/variables/assets/infrastructure.schema.json => config/schema/variables.schema.json (99%) rename configs/variables.template.yml => config/variables.example.yml (77%) rename {configs => config}/variables/.gitkeep (100%) create mode 100644 config/variables/readme.md delete mode 100644 configs/variables/readme.md diff --git a/.gitignore b/.gitignore index 5ddfa1c..16c964e 100644 --- a/.gitignore +++ b/.gitignore @@ -34,9 +34,10 @@ ansible/.vault_pass !.env.example # Central config (actual values — never commit) -configs/infrastructure-*.yml -!configs/infrastructure.yml -configs/credentials/ +config/infrastructure-*.yml +!config/infrastructure.yml +config/variables.yml +config/credentials/ # Log files (keep the directory via .gitkeep) logs/** diff --git a/README.md b/README.md index 262a79a..9b9a482 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Platform automation toolkit for **Azure Local** — deployment scripts, validati | Directory | Description | |-----------|-------------| | **[scripts/](https://github.com/AzureLocal/azurelocal-toolkit/tree/main/scripts)** | 200+ PowerShell scripts organized by deployment stage (02–08), plus common modules, validation, handover, lifecycle, and tools | -| **[configs/](https://github.com/AzureLocal/azurelocal-toolkit/tree/main/configs)** | Master infrastructure config template, ARM templates, and variable registry | +| **[config/](https://github.com/AzureLocal/azurelocal-toolkit/tree/main/configs)** | Master infrastructure config template, ARM templates, and variable registry | | **[tools/](https://github.com/AzureLocal/azurelocal-toolkit/tree/main/tools)** | Planning utilities (S2D capacity calculator) | | **[tests/](https://github.com/AzureLocal/azurelocal-toolkit/tree/main/tests)** | Test infrastructure (future Pester suites) | @@ -34,8 +34,8 @@ The toolkit follows a structured deployment lifecycle: The toolkit uses a config-driven approach: -- **`configs/infrastructure.yml`** — Master configuration template with 14 sections covering Azure tenant, networking, compute, storage, security, and more -- **`configs/variables.template.yml`** — Azure Local-specific variables for deployment +- **`config/infrastructure.yml`** — Master configuration template with 14 sections covering Azure tenant, networking, compute, storage, security, and more +- **`config/variables.example.yml`** — Azure Local-specific variables for deployment ## Related Repositories diff --git a/configs/Generate-AzureLocal-Parameters.ps1 b/config/Generate-AzureLocal-Parameters.ps1 similarity index 98% rename from configs/Generate-AzureLocal-Parameters.ps1 rename to config/Generate-AzureLocal-Parameters.ps1 index 07a8ae4..f9dcab5 100644 --- a/configs/Generate-AzureLocal-Parameters.ps1 +++ b/config/Generate-AzureLocal-Parameters.ps1 @@ -20,7 +20,7 @@ - storageNetworkList (from network_intents with storage_networks) .PARAMETER ConfigPath - Path to the infrastructure YAML file. Defaults to configs/infrastructure.yml + Path to the infrastructure YAML file. Defaults to config/infrastructure.yml relative to the repository root. .PARAMETER AuthType @@ -35,11 +35,11 @@ Show what would be generated without writing the file. .EXAMPLE - .\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure-azl-demo.yml" -AuthType AD + .\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure-azl-demo.yml" -AuthType AD Generates AD parameters file from the azl-demo config. .EXAMPLE - .\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure-azl-lab.yml" -AuthType LocalIdentity -WhatIf + .\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure-azl-lab.yml" -AuthType LocalIdentity -WhatIf Shows what would be generated for local identity without writing a file. #> diff --git a/configs/azure/.gitkeep b/config/azure/.gitkeep similarity index 100% rename from configs/azure/.gitkeep rename to config/azure/.gitkeep diff --git a/configs/azure/arm-templates/README.md b/config/azure/arm-templates/README.md similarity index 96% rename from configs/azure/arm-templates/README.md rename to config/azure/arm-templates/README.md index b3c5325..5fb6a20 100644 --- a/configs/azure/arm-templates/README.md +++ b/config/azure/arm-templates/README.md @@ -43,13 +43,13 @@ Use the config-driven generation script to populate parameters from `infrastruct ```powershell # Generate AD parameter file -.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure.yml" -AuthType AD +.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure.yml" -AuthType AD # Generate Local Identity parameter file -.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure.yml" -AuthType LocalIdentity +.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure.yml" -AuthType LocalIdentity ``` -The script reads all 54 parameters from `infrastructure.yml`, resolves Key Vault references, and writes a deployment-ready JSON file. See `configs/Generate-AzureLocal-Parameters.ps1` for full documentation. +The script reads all 54 parameters from `infrastructure.yml`, resolves Key Vault references, and writes a deployment-ready JSON file. See `config/Generate-AzureLocal-Parameters.ps1` for full documentation. ### Option 2: Manual Placeholder Replacement diff --git a/configs/azure/arm-templates/cluster-deployment/README.md b/config/azure/arm-templates/cluster-deployment/README.md similarity index 94% rename from configs/azure/arm-templates/cluster-deployment/README.md rename to config/azure/arm-templates/cluster-deployment/README.md index 5c90b4b..a39eff5 100644 --- a/configs/azure/arm-templates/cluster-deployment/README.md +++ b/config/azure/arm-templates/cluster-deployment/README.md @@ -30,13 +30,13 @@ Use the generation script to populate all 54 parameters from `infrastructure.yml ```powershell # AD auth -.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure.yml" -AuthType AD +.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure.yml" -AuthType AD # Local Identity auth -.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure.yml" -AuthType LocalIdentity +.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure.yml" -AuthType LocalIdentity ``` -The script reads the YAML config, maps all values, and writes a deployment-ready JSON. See `configs/Generate-AzureLocal-Parameters.ps1` for full documentation. +The script reads the YAML config, maps all values, and writes a deployment-ready JSON. See `config/Generate-AzureLocal-Parameters.ps1` for full documentation. ### Option B: Manual Replacement @@ -101,10 +101,10 @@ Key differences: Instead of manually filling placeholders, use the generation script: ```powershell -.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "configs/infrastructure.yml" -AuthType AD +.\configs\Generate-AzureLocal-Parameters.ps1 -ConfigPath "config/infrastructure.yml" -AuthType AD ``` -See `configs/Generate-AzureLocal-Parameters.ps1` for full documentation. +See `config/Generate-AzureLocal-Parameters.ps1` for full documentation. ## Validated Examples diff --git a/configs/azure/arm-templates/cluster-deployment/azuredeploy.json b/config/azure/arm-templates/cluster-deployment/azuredeploy.json similarity index 100% rename from configs/azure/arm-templates/cluster-deployment/azuredeploy.json rename to config/azure/arm-templates/cluster-deployment/azuredeploy.json diff --git a/configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.ad.json b/config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.ad.json similarity index 100% rename from configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.ad.json rename to config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.ad.json diff --git a/configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.json b/config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.json similarity index 100% rename from configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.json rename to config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.json diff --git a/configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.local-identity.json b/config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.local-identity.json similarity index 100% rename from configs/azure/arm-templates/cluster-deployment/azuredeploy.parameters.local-identity.json rename to config/azure/arm-templates/cluster-deployment/azuredeploy.parameters.local-identity.json diff --git a/configs/azure/arm-templates/examples/README.md b/config/azure/arm-templates/examples/README.md similarity index 100% rename from configs/azure/arm-templates/examples/README.md rename to config/azure/arm-templates/examples/README.md diff --git a/configs/azure/arm-templates/examples/single-intent-converged/README.md b/config/azure/arm-templates/examples/single-intent-converged/README.md similarity index 100% rename from configs/azure/arm-templates/examples/single-intent-converged/README.md rename to config/azure/arm-templates/examples/single-intent-converged/README.md diff --git a/configs/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.ad.json b/config/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.ad.json similarity index 100% rename from configs/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.ad.json rename to config/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.ad.json diff --git a/configs/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.local-identity.json b/config/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.local-identity.json similarity index 100% rename from configs/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.local-identity.json rename to config/azure/arm-templates/examples/single-intent-converged/azuredeploy.parameters.local-identity.json diff --git a/configs/azure/arm-templates/examples/three-intent-separated/README.md b/config/azure/arm-templates/examples/three-intent-separated/README.md similarity index 100% rename from configs/azure/arm-templates/examples/three-intent-separated/README.md rename to config/azure/arm-templates/examples/three-intent-separated/README.md diff --git a/configs/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.ad.json b/config/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.ad.json similarity index 100% rename from configs/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.ad.json rename to config/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.ad.json diff --git a/configs/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.local-identity.json b/config/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.local-identity.json similarity index 100% rename from configs/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.local-identity.json rename to config/azure/arm-templates/examples/three-intent-separated/azuredeploy.parameters.local-identity.json diff --git a/configs/azure/arm-templates/examples/two-intent-standard/README.md b/config/azure/arm-templates/examples/two-intent-standard/README.md similarity index 100% rename from configs/azure/arm-templates/examples/two-intent-standard/README.md rename to config/azure/arm-templates/examples/two-intent-standard/README.md diff --git a/configs/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.ad.json b/config/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.ad.json similarity index 100% rename from configs/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.ad.json rename to config/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.ad.json diff --git a/configs/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.local-identity.json b/config/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.local-identity.json similarity index 100% rename from configs/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.local-identity.json rename to config/azure/arm-templates/examples/two-intent-standard/azuredeploy.parameters.local-identity.json diff --git a/configs/infrastructure.yml b/config/infrastructure.yml similarity index 100% rename from configs/infrastructure.yml rename to config/infrastructure.yml diff --git a/configs/variables/assets/master-registry.yaml b/config/schema/master-registry.yaml similarity index 99% rename from configs/variables/assets/master-registry.yaml rename to config/schema/master-registry.yaml index 1ce5518..7bd7146 100644 --- a/configs/variables/assets/master-registry.yaml +++ b/config/schema/master-registry.yaml @@ -2,7 +2,7 @@ # Master Variable Registry - Azure Local Cloudnology Cloud Management Platform # ============================================================================= # Version: 4.0.0 -# Schema: infrastructure.schema.json (v4.0.0) +# Schema: variables.schema.json (v4.0.0) # Last Updated: 2026-03-05 # # This file defines ALL variable names, types, and descriptions used across @@ -83,7 +83,7 @@ _metadata: change: "Added B2B, GitLab, Arc Resource Bridge, cluster networking, monitoring extended" reason: "Variable audit from 157 PowerShell scripts" cross_references: - - source: "infrastructure.schema.json" + - source: "variables.schema.json" relationship: "validates infrastructure files against these definitions" - source: "registry-reference.mdx" relationship: "human-readable documentation of this registry" diff --git a/configs/variables/assets/infrastructure.schema.json b/config/schema/variables.schema.json similarity index 99% rename from configs/variables/assets/infrastructure.schema.json rename to config/schema/variables.schema.json index acec3db..0027ff3 100644 --- a/configs/variables/assets/infrastructure.schema.json +++ b/config/schema/variables.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/Azure Local Cloud/azl-env/schemas/infrastructure.schema.json", + "$id": "https://github.com/Azure Local Cloud/azl-env/schemas/variables.schema.json", "title": "Azure Local Infrastructure Configuration (v4.0.0)", "description": "JSON Schema for validating Azure Local environment infrastructure.yml files. Aligned with master-registry.yaml v4.0.0 — 13-section hierarchy. NOTE: This schema is currently hand-maintained and MUST be kept in sync with master-registry.yaml (the canonical source). TODO: Auto-generate this schema from master-registry.yaml to prevent drift.", "type": "object", diff --git a/configs/variables.template.yml b/config/variables.example.yml similarity index 77% rename from configs/variables.template.yml rename to config/variables.example.yml index f5c8fe5..4b01f0c 100644 --- a/configs/variables.template.yml +++ b/config/variables.example.yml @@ -1,16 +1,21 @@ -################################################################################ -# Azure Local Toolkit - Variables Template +# ============================================================================= +# variables.example.yml +# Central configuration — single source of truth for all deployment phases. # -# Copy this file to your own variables.yml and fill in your environment values. -# This template contains the minimum required variables for a deployment. +# Copy this file to variables.yml and fill in your values: +# cp config/variables.example.yml config/variables.yml # -# For the full variable reference, see: -# - configs/infrastructure.yml (complete 14-section schema) -# - configs/variables/assets/master-registry.yaml (variable definitions) +# DO NOT commit variables.yml — it is excluded by .gitignore. +# +# Key Vault References: +# Secrets use keyvault:// URIs and are resolved at runtime. +# Format: keyvault:/// +# NEVER put actual passwords or secrets in this file. # -# All secrets should be stored in Azure Key Vault and referenced as: -# keyvault:/// -################################################################################ +# For the full variable reference, see: +# - config/infrastructure.yml (complete 14-section schema) +# - config/schema/master-registry.yaml (variable definitions) +# ============================================================================= # ============================================================================= # SITE diff --git a/configs/variables/.gitkeep b/config/variables/.gitkeep similarity index 100% rename from configs/variables/.gitkeep rename to config/variables/.gitkeep diff --git a/config/variables/readme.md b/config/variables/readme.md new file mode 100644 index 0000000..8b96761 --- /dev/null +++ b/config/variables/readme.md @@ -0,0 +1,32 @@ +# Variables + +This directory provides supplementary variable information for the Azure Local Toolkit. + +## Config Structure + +``` +config/ +├── infrastructure.yml # Full 14-section config (platform deployments) +├── variables.example.yml # Copyable template with IIC example values +├── variables.yml # Your actual config (gitignored) +├── schema/ +│ ├── master-registry.yaml # Complete variable definitions with types/defaults +│ └── variables.schema.json # JSON Schema for validation +└── variables/ + └── readme.md # This file +``` + +## Quick Start + +```bash +cp config/variables.example.yml config/variables.yml +# Edit config/variables.yml with your environment values +``` + +## References + +- `config/variables.example.yml` — minimal starting template (IIC fictional data) +- `config/infrastructure.yml` — full 14-section configuration reference +- `config/schema/master-registry.yaml` — authoritative variable definitions +- `config/schema/variables.schema.json` — JSON Schema for CI validation + diff --git a/configs/variables/readme.md b/configs/variables/readme.md deleted file mode 100644 index 6b99dd8..0000000 --- a/configs/variables/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -# Variable Assets - -This directory contains the variable registry and schema for the Azure Local Toolkit. - -## Files - -- **master-registry.yaml** — Complete variable definitions with types, defaults, and examples -- **infrastructure.schema.json** — JSON Schema for validating infrastructure.yml - -## Usage - -See `configs/variables.template.yml` for a minimal starting template. -See `configs/infrastructure.yml` for the full 14-section configuration reference. - diff --git a/docs/configuration/variables.md b/docs/configuration/variables.md index 63e041b..f9105d7 100644 --- a/docs/configuration/variables.md +++ b/docs/configuration/variables.md @@ -16,8 +16,8 @@ Master configuration template with 14 sections covering the full Azure Local dep - Active Directory - And more... -This file serves as a **metadata and schema registry**. Copy `variables.template.yml` for your deployment-specific values. +This file serves as a **metadata and schema registry**. Copy `variables.example.yml` for your deployment-specific values. -## variables.template.yml +## variables.example.yml Azure Local-specific variables extracted from the master config. Copy this file to `variables.yml` (gitignored) and fill in your environment values. diff --git a/docs/index.md b/docs/index.md index 5a685d8..bd25534 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,7 @@ Platform automation toolkit for **Azure Local** — deployment scripts, validati | Directory | Description | |-----------|-------------| | **scripts/** | 200+ PowerShell scripts organized by deployment stage (02–08), plus common modules, validation, handover, lifecycle, and tools | -| **configs/** | Master infrastructure config template, ARM templates, and variable registry | +| **config/** | Master infrastructure config template, ARM templates, and variable registry | | **tools/** | Planning utilities (S2D capacity calculator) | | **tests/** | Test infrastructure (future Pester suites) | @@ -35,7 +35,7 @@ Platform automation toolkit for **Azure Local** — deployment scripts, validati ## Getting Started 1. Clone the repository -2. Copy `configs/variables.template.yml` to `configs/variables.yml` +2. Copy `config/variables.example.yml` to `config/variables.yml` 3. Fill in your environment-specific values 4. Follow the deployment stage guides in order (02 → 08) diff --git a/scripts/common/idrac-management/Enable-IdracVnc.ps1 b/scripts/common/idrac-management/Enable-IdracVnc.ps1 index 94137cd..c7d7ea2 100644 --- a/scripts/common/idrac-management/Enable-IdracVnc.ps1 +++ b/scripts/common/idrac-management/Enable-IdracVnc.ps1 @@ -66,15 +66,15 @@ Ignore SSL certificate validation errors (useful for self-signed iDRAC certificates). .EXAMPLE - .\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" + .\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" Config-driven: enables VNC on all nodes using YAML settings and Key Vault credentials. .EXAMPLE - .\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -TargetNode "node-01" + .\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -TargetNode "node-01" Config-driven: targets only a specific node. .EXAMPLE - .\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -WhatIf + .\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -WhatIf Config-driven dry run: shows what would be configured without making changes. .EXAMPLE diff --git a/scripts/common/idrac-management/README.md b/scripts/common/idrac-management/README.md index 3487ce7..4090a80 100644 --- a/scripts/common/idrac-management/README.md +++ b/scripts/common/idrac-management/README.md @@ -42,20 +42,20 @@ Enables and configures VNC access on Dell iDRAC via Redfish API. ```powershell # Enable VNC on all nodes using infrastructure.yml settings -.\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -IgnoreCertificateErrors +.\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -IgnoreCertificateErrors # Target a single node -.\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -TargetNode "node-01" +.\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -TargetNode "node-01" # Dry run — show what would change without applying -.\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -WhatIf +.\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -WhatIf # Override VNC port from config default -.\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -VNCPort 5902 +.\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -VNCPort 5902 # Provide credentials explicitly (skips Key Vault resolution) $cred = Get-Credential -UserName "idrac_admin" -.\Enable-IdracVnc.ps1 -ConfigPath "configs/infrastructure.yml" -Credential $cred +.\Enable-IdracVnc.ps1 -ConfigPath "config/infrastructure.yml" -Credential $cred ``` **Usage — Standalone mode:** diff --git a/scripts/common/utilities/helpers/Connect-AzureCliSession.ps1 b/scripts/common/utilities/helpers/Connect-AzureCliSession.ps1 index f3ddfbe..255344f 100644 --- a/scripts/common/utilities/helpers/Connect-AzureCliSession.ps1 +++ b/scripts/common/utilities/helpers/Connect-AzureCliSession.ps1 @@ -41,7 +41,7 @@ .EXAMPLE # Read values from infrastructure.yml - .\Connect-AzureCliSession.ps1 -ConfigPath "../../configs/infrastructure.yml" + .\Connect-AzureCliSession.ps1 -ConfigPath "../../config/infrastructure.yml" .NOTES File Name : Connect-AzureCliSession.ps1 diff --git a/scripts/common/utilities/helpers/Connect-AzureSession.ps1 b/scripts/common/utilities/helpers/Connect-AzureSession.ps1 index 9cb3780..3884144 100644 --- a/scripts/common/utilities/helpers/Connect-AzureSession.ps1 +++ b/scripts/common/utilities/helpers/Connect-AzureSession.ps1 @@ -45,7 +45,7 @@ .EXAMPLE # Read values from infrastructure.yml - .\Connect-AzureSession.ps1 -ConfigPath "../../configs/infrastructure.yml" + .\Connect-AzureSession.ps1 -ConfigPath "../../config/infrastructure.yml" .NOTES File Name : Connect-AzureSession.ps1 diff --git a/scripts/common/utilities/helpers/config-loader.ps1 b/scripts/common/utilities/helpers/config-loader.ps1 index 8e25386..5b96b90 100644 --- a/scripts/common/utilities/helpers/config-loader.ps1 +++ b/scripts/common/utilities/helpers/config-loader.ps1 @@ -538,13 +538,13 @@ function Get-AvailableSolutions { .DESCRIPTION Primary function for deployment scripts to load configuration. - Loads configs/infrastructure.yml from the repository root. + Loads config/infrastructure.yml from the repository root. This is the simplified loader for scripts that need direct access to infrastructure configuration without solution-based merging. .PARAMETER ConfigPath - Optional. Path to infrastructure.yml. Defaults to configs/infrastructure.yml + Optional. Path to infrastructure.yml. Defaults to config/infrastructure.yml in the repository root. .EXAMPLE @@ -563,7 +563,7 @@ function Get-InfrastructureConfig { [string]$ConfigPath ) - # Default to configs/infrastructure.yml in repo root + # Default to config/infrastructure.yml in repo root if (-not $ConfigPath) { $ConfigPath = Join-Path $script:RepoRoot "configs\infrastructure.yml" } diff --git a/scripts/deploy/02-azure-foundation/phase-02-resource-providers/task-01-register-resource-providers/powershell/Register-ResourceProviders.ps1 b/scripts/deploy/02-azure-foundation/phase-02-resource-providers/task-01-register-resource-providers/powershell/Register-ResourceProviders.ps1 index 9ed64ca..17c5ef3 100644 --- a/scripts/deploy/02-azure-foundation/phase-02-resource-providers/task-01-register-resource-providers/powershell/Register-ResourceProviders.ps1 +++ b/scripts/deploy/02-azure-foundation/phase-02-resource-providers/task-01-register-resource-providers/powershell/Register-ResourceProviders.ps1 @@ -14,7 +14,7 @@ .PARAMETER ConfigFile Path to the infrastructure.yml configuration file. - Defaults to configs/infrastructure.yml in the repository root. + Defaults to config/infrastructure.yml in the repository root. .PARAMETER WaitForRegistration If specified, waits for all provider registrations to complete. diff --git a/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Set-RbacRoleAssignments.ps1 b/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Set-RbacRoleAssignments.ps1 index 1813b42..8750e7b 100644 --- a/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Set-RbacRoleAssignments.ps1 +++ b/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Set-RbacRoleAssignments.ps1 @@ -6,7 +6,7 @@ Loads config from infrastructure.yml, assigns roles at subscription/resource group scope, supports WhatIf and verification mode. .PARAMETER ConfigPath - Path to infrastructure.yml config file. Defaults to configs/infrastructure.yml in the repository root. + Path to infrastructure.yml config file. Defaults to config/infrastructure.yml in the repository root. .PARAMETER ServicePrincipalDisplayName Display name of the deployment service principal. @@ -22,13 +22,13 @@ If specified, only verifies assignments (no changes). .EXAMPLE - .\Set-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -ServicePrincipalDisplayName "sp-azurelocal-deploy" -WhatIf + .\Set-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -ServicePrincipalDisplayName "sp-azurelocal-deploy" -WhatIf .EXAMPLE - .\Set-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -UserPrincipalName "deployment-user@yourdomain.com" -VerifyOnly + .\Set-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -UserPrincipalName "deployment-user@yourdomain.com" -VerifyOnly .EXAMPLE - .\Set-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -ObjectId "55555555-5555-5555-5555-555555555555" + .\Set-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -ObjectId "55555555-5555-5555-5555-555555555555" .NOTES Requires: Az.Accounts, Az.Resources, powershell-yaml modules @@ -40,7 +40,7 @@ param( [Parameter(Mandatory = $false)] [ValidateScript({Test-Path $_})] - [string]$ConfigPath = "configs/infrastructure.yml", + [string]$ConfigPath = "config/infrastructure.yml", [Parameter(Mandatory = $false)] [string]$ServicePrincipalDisplayName, diff --git a/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Test-RbacRoleAssignments.ps1 b/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Test-RbacRoleAssignments.ps1 index e61112f..c0805db 100644 --- a/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Test-RbacRoleAssignments.ps1 +++ b/scripts/deploy/02-azure-foundation/phase-03-rbac-permissions/powershell/Test-RbacRoleAssignments.ps1 @@ -6,7 +6,7 @@ Loads config from infrastructure.yml, validates role assignments at subscription and resource group scope. .PARAMETER ConfigPath - Path to infrastructure.yml config file. Defaults to configs/infrastructure.yml in the repository root. + Path to infrastructure.yml config file. Defaults to config/infrastructure.yml in the repository root. .PARAMETER ServicePrincipalDisplayName Display name of the deployment service principal to validate. @@ -18,13 +18,13 @@ Entra ID Object ID of the principal to validate (optional). .EXAMPLE - .\Validate-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -ServicePrincipalDisplayName "sp-azurelocal-deploy" + .\Validate-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -ServicePrincipalDisplayName "sp-azurelocal-deploy" .EXAMPLE - .\Validate-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -UserPrincipalName "deployment-user@yourdomain.com" + .\Validate-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -UserPrincipalName "deployment-user@yourdomain.com" .EXAMPLE - .\Validate-RbacRoleAssignments.ps1 -ConfigPath "configs/infrastructure.yml" -ObjectId "55555555-5555-5555-5555-555555555555" + .\Validate-RbacRoleAssignments.ps1 -ConfigPath "config/infrastructure.yml" -ObjectId "55555555-5555-5555-5555-555555555555" .NOTES Requires: Az.Accounts, Az.Resources, powershell-yaml modules @@ -36,7 +36,7 @@ param( [Parameter(Mandatory = $false)] [ValidateScript({Test-Path $_})] - [string]$ConfigPath = "configs/infrastructure.yml", + [string]$ConfigPath = "config/infrastructure.yml", [Parameter(Mandatory = $false)] [string]$ServicePrincipalDisplayName, diff --git a/scripts/deploy/02-azure-foundation/phase-04-azure-management-infrastructure/task-01-virtual-network/powershell/New-VirtualNetwork.ps1 b/scripts/deploy/02-azure-foundation/phase-04-azure-management-infrastructure/task-01-virtual-network/powershell/New-VirtualNetwork.ps1 index e9a5b81..97e3063 100644 --- a/scripts/deploy/02-azure-foundation/phase-04-azure-management-infrastructure/task-01-virtual-network/powershell/New-VirtualNetwork.ps1 +++ b/scripts/deploy/02-azure-foundation/phase-04-azure-management-infrastructure/task-01-virtual-network/powershell/New-VirtualNetwork.ps1 @@ -28,7 +28,7 @@ .\New-VirtualNetwork.ps1 -ResourceGroupName "rg-azlmgmt-prd-eus-01" -Location "eastus" .EXAMPLE - .\New-VirtualNetwork.ps1 -ConfigFile "configs/infrastructure.yml" + .\New-VirtualNetwork.ps1 -ConfigFile "config/infrastructure.yml" .NOTES Author: Azure Local Cloud AzureLocalCloud Team diff --git a/scripts/deploy/04-cluster-deployment/phase-01-hardware-provisioning/task-02-hardware-discovery-via-dell-redfish-api/powershell/Invoke-HardwareDiscovery.ps1 b/scripts/deploy/04-cluster-deployment/phase-01-hardware-provisioning/task-02-hardware-discovery-via-dell-redfish-api/powershell/Invoke-HardwareDiscovery.ps1 index 1435b39..2fcfd60 100644 --- a/scripts/deploy/04-cluster-deployment/phase-01-hardware-provisioning/task-02-hardware-discovery-via-dell-redfish-api/powershell/Invoke-HardwareDiscovery.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-01-hardware-provisioning/task-02-hardware-discovery-via-dell-redfish-api/powershell/Invoke-HardwareDiscovery.ps1 @@ -63,7 +63,7 @@ iDRAC ATTRIBUTES - Full dump of all iDRAC settings - Output JSON files saved to configs/network-devices/bmc/.json. + Output JSON files saved to config/network-devices/bmc/.json. Optionally calls Update-InfrastructureYml-FromDiscovery.ps1 on completion. CREDENTIAL RESOLUTION ORDER diff --git a/scripts/deploy/04-cluster-deployment/phase-03-os-configuration/task-12-complete-combined-script-all-steps/powershell/Invoke-Phase03OsConfiguration-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-03-os-configuration/task-12-complete-combined-script-all-steps/powershell/Invoke-Phase03OsConfiguration-Orchestrated.ps1 index 939d33e..824e51d 100644 --- a/scripts/deploy/04-cluster-deployment/phase-03-os-configuration/task-12-complete-combined-script-all-steps/powershell/Invoke-Phase03OsConfiguration-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-03-os-configuration/task-12-complete-combined-script-all-steps/powershell/Invoke-Phase03OsConfiguration-Orchestrated.ps1 @@ -129,7 +129,7 @@ function Resolve-ConfigPath { if (Test-Path $r) { return $r } } catch {} } - # Attempt to find any infrastructure*.yml in a configs/ subdirectory + # Attempt to find any infrastructure*.yml in a config/ subdirectory foreach ($dir in @((Join-Path $PSScriptRoot "configs"), ".\configs")) { if (Test-Path $dir) { $found = @(Get-ChildItem -Path $dir -Filter "infrastructure*.yml" -File -ErrorAction SilentlyContinue) diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 index 43d41e7..1b6c791 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 @@ -242,7 +242,7 @@ else { } if (-not $generatorScript) { - throw "Generate-AzureLocal-Parameters.ps1 not found. Pass -ParametersFile with a pre-built file, or ensure the generator is in configs/." + throw "Generate-AzureLocal-Parameters.ps1 not found. Pass -ParametersFile with a pre-built file, or ensure the generator is in config/." } Write-Log "Generator script: $generatorScript" diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyADDomainStatus-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyADDomainStatus-Orchestrated.ps1 index 38665d0..df29d20 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyADDomainStatus-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyADDomainStatus-Orchestrated.ps1 @@ -9,7 +9,7 @@ mandatory contract (ConfigPath, Credential, TargetNode, WhatIf, LogPath). .PARAMETER ConfigPath - Path to the infrastructure YAML config (default: configs/infrastructure.yml). + Path to the infrastructure YAML config (default: config/infrastructure.yml). .PARAMETER Credential PSCredential for remote node access. Falls back to Key Vault → interactive prompt. @@ -27,7 +27,7 @@ .\Invoke-VerifyADDomainStatus-Orchestrated.ps1 .EXAMPLE - .\Invoke-VerifyADDomainStatus-Orchestrated.ps1 -ConfigPath "configs/infrastructure-azl-demo.yml" -WhatIf + .\Invoke-VerifyADDomainStatus-Orchestrated.ps1 -ConfigPath "config/infrastructure-azl-demo.yml" -WhatIf .NOTES Author: Azure Local Cloud AzureLocalCloud @@ -85,7 +85,7 @@ Write-Log "Log: $LogPath" # ── Config Loading ───────────────────────────────────────────────────── if (-not $ConfigPath) { - $candidates = @("configs/infrastructure.yml", "configs/infrastructure.yaml") + $candidates = @("config/infrastructure.yml", "config/infrastructure.yaml") foreach ($c in $candidates) { if (Test-Path $c) { $ConfigPath = $c; break } } diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 index f099916..ef65bb8 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/active-directory/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 @@ -14,7 +14,7 @@ 3. Interactive Get-Credential prompt .PARAMETER ConfigPath - Path to infrastructure.yml. Defaults to 'configs/infrastructure.yml' relative + Path to infrastructure.yml. Defaults to 'config/infrastructure.yml' relative to the working directory. .PARAMETER Credential @@ -38,9 +38,9 @@ Execution: Run from management server with access to infrastructure.yml .EXAMPLE - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -TargetNode iic-01-n01 - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -WhatIf + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -TargetNode iic-01-n01 + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -WhatIf #> [CmdletBinding(SupportsShouldProcess)] diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 index 43d41e7..1b6c791 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-01-initiate-deployment-via-arm-template/powershell/Deploy-AzureLocalCluster.ps1 @@ -242,7 +242,7 @@ else { } if (-not $generatorScript) { - throw "Generate-AzureLocal-Parameters.ps1 not found. Pass -ParametersFile with a pre-built file, or ensure the generator is in configs/." + throw "Generate-AzureLocal-Parameters.ps1 not found. Pass -ParametersFile with a pre-built file, or ensure the generator is in config/." } Write-Log "Generator script: $generatorScript" diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 index f099916..ef65bb8 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyClusterHealth-Orchestrated.ps1 @@ -14,7 +14,7 @@ 3. Interactive Get-Credential prompt .PARAMETER ConfigPath - Path to infrastructure.yml. Defaults to 'configs/infrastructure.yml' relative + Path to infrastructure.yml. Defaults to 'config/infrastructure.yml' relative to the working directory. .PARAMETER Credential @@ -38,9 +38,9 @@ Execution: Run from management server with access to infrastructure.yml .EXAMPLE - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -TargetNode iic-01-n01 - .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -WhatIf + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -TargetNode iic-01-n01 + .\Invoke-VerifyClusterHealth-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -WhatIf #> [CmdletBinding(SupportsShouldProcess)] diff --git a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 index 6e952c7..cfe011d 100644 --- a/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-05-cluster-deployment/local-identity/task-02-verify-deployment-completion/powershell/Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 @@ -19,7 +19,7 @@ Source: https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-local-identity-with-key-vault .PARAMETER ConfigPath - Path to infrastructure.yml. Defaults to 'configs/infrastructure.yml' relative + Path to infrastructure.yml. Defaults to 'config/infrastructure.yml' relative to the working directory. .PARAMETER Credential @@ -43,9 +43,9 @@ Execution: Run from management server with access to infrastructure.yml .EXAMPLE - .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml - .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -TargetNode iic-01-n01,iic-01-n02 - .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath configs/infrastructure.yml -WhatIf + .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath config/infrastructure.yml + .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -TargetNode iic-01-n01,iic-01-n02 + .\Invoke-VerifyLocalIdentityConfig-Orchestrated.ps1 -ConfigPath config/infrastructure.yml -WhatIf #> [CmdletBinding(SupportsShouldProcess)] diff --git a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-01-deploy-sdn/powershell/Get-VirtualSwitchName-Standalone.ps1 b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-01-deploy-sdn/powershell/Get-VirtualSwitchName-Standalone.ps1 index 4de6ada..f949cbb 100644 --- a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-01-deploy-sdn/powershell/Get-VirtualSwitchName-Standalone.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-01-deploy-sdn/powershell/Get-VirtualSwitchName-Standalone.ps1 @@ -27,7 +27,7 @@ $switches | Format-Table Name, SwitchType, NetAdapterInterfaceDescription -AutoS $primary = $switches | Select-Object -First 1 Write-Host "================================================================" -ForegroundColor Green -Write-Host " Copy this value into configs/infrastructure.yml:" -ForegroundColor Green +Write-Host " Copy this value into config/infrastructure.yml:" -ForegroundColor Green Write-Host "" Write-Host " compute:" -ForegroundColor White Write-Host " azure_local:" -ForegroundColor White diff --git a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-04-ssh-connectivity-to-nodes/powershell/Invoke-SSHConnectivity-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-04-ssh-connectivity-to-nodes/powershell/Invoke-SSHConnectivity-Orchestrated.ps1 index 781360e..9e3b122 100644 --- a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-04-ssh-connectivity-to-nodes/powershell/Invoke-SSHConnectivity-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-04-ssh-connectivity-to-nodes/powershell/Invoke-SSHConnectivity-Orchestrated.ps1 @@ -19,7 +19,7 @@ No WinRM/PSRemoting required — the Arc agent handles the OpenSSH install. .PARAMETER ConfigPath - Path to infrastructure YAML config. Defaults to configs/infrastructure.yml + Path to infrastructure YAML config. Defaults to config/infrastructure.yml relative to CWD (repo root). .PARAMETER TargetNode diff --git a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StorageCSV-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StorageCSV-Orchestrated.ps1 index f6f7a76..58e5216 100644 --- a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StorageCSV-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StorageCSV-Orchestrated.ps1 @@ -16,7 +16,7 @@ 3. Interactive Get-Credential prompt .PARAMETER ConfigPath - Path to infrastructure YAML. Defaults to configs/infrastructure.yml in CWD. + Path to infrastructure YAML. Defaults to config/infrastructure.yml in CWD. .PARAMETER Credential Override credential resolution — skips Key Vault and prompt. diff --git a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StoragePaths-Orchestrated.ps1 b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StoragePaths-Orchestrated.ps1 index 2d3c180..f6ee409 100644 --- a/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StoragePaths-Orchestrated.ps1 +++ b/scripts/deploy/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration/powershell/Invoke-StoragePaths-Orchestrated.ps1 @@ -14,7 +14,7 @@ via az CLI from the management server. .PARAMETER ConfigPath - Path to infrastructure YAML. Defaults to configs/infrastructure.yml in CWD. + Path to infrastructure YAML. Defaults to config/infrastructure.yml in CWD. .PARAMETER Credential Not used for storage path registration (Azure CLI handles auth via az login). diff --git a/scripts/lifecycle/updates/monitoring/powershell/Monitor-Update.ps1 b/scripts/lifecycle/updates/monitoring/powershell/Monitor-Update.ps1 index 52f1352..3efa648 100644 --- a/scripts/lifecycle/updates/monitoring/powershell/Monitor-Update.ps1 +++ b/scripts/lifecycle/updates/monitoring/powershell/Monitor-Update.ps1 @@ -29,7 +29,7 @@ 3. Existing Connect-AzAccount / Get-AzContext .PARAMETER ConfigPath - Path to the infrastructure YAML config file (e.g. configs/infrastructure-azl-lab.yml). + Path to the infrastructure YAML config file (e.g. config/infrastructure-azl-lab.yml). When supplied, ResourceGroupName, ClusterName, SubscriptionId, TenantId, NodeIPs, KeyVaultName, and credentials are all resolved automatically from the config. Any explicitly supplied parameters override the config values. diff --git a/tools/Generate-SolutionConfig.ps1 b/tools/Generate-SolutionConfig.ps1 index 0acd5ce..b79f864 100644 --- a/tools/Generate-SolutionConfig.ps1 +++ b/tools/Generate-SolutionConfig.ps1 @@ -5,9 +5,9 @@ Generate a solution-specific YAML config from solutions.yaml + master-registry + infrastructure-.yml. .DESCRIPTION - Reads the solutions definition (configs/solutions.yaml), the master variable registry - (configs/variables/assets/master-registry.yaml), and an environment-specific infrastructure - file (configs/infrastructure-.yml) to produce a per-solution config file containing + Reads the solutions definition (config/solutions.yaml), the master variable registry + (config/schema/master-registry.yaml), and an environment-specific infrastructure + file (config/infrastructure-.yml) to produce a per-solution config file containing only the variables that solution needs — with actual environment values populated. Output path follows the convention: solutions//solution-.yml @@ -125,9 +125,9 @@ $outputData = [ordered]@{ generated_at = (Get-Date -Format "yyyy-MM-dd HH:mm:ss") generator = "Generate-SolutionConfig.ps1 v1.0.0" source_files = @( - "configs/solutions.yaml" - "configs/variables/assets/master-registry.yaml" - "configs/infrastructure-$Environment.yml" + "config/solutions.yaml" + "config/schema/master-registry.yaml" + "config/infrastructure-$Environment.yml" ) } } diff --git a/tools/planning/S2D_Capacity_Calculator_6.xlsx b/tools/planning/S2D_Capacity_Calculator_6.xlsx index 34fe3639680f3822ddbb5a3e88e0405139b7c0dd..c2367d3874e184185ceade3a3239b1aa73ae3159 100644 GIT binary patch literal 58043 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 delta 28834 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 From f0680b3ff6807592618d216326a886315263604f Mon Sep 17 00:00:00 2001 From: Kris Turner Date: Tue, 17 Mar 2026 10:02:30 -0400 Subject: [PATCH 2/2] ci: add validate-config workflow Validates infrastructure.yml against schema and checks variables.example.yml syntax. Part of AzureLocal/azurelocal.github.io#15 --- .github/workflows/validate-config.yml | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/validate-config.yml diff --git a/.github/workflows/validate-config.yml b/.github/workflows/validate-config.yml new file mode 100644 index 0000000..6271056 --- /dev/null +++ b/.github/workflows/validate-config.yml @@ -0,0 +1,72 @@ +# ============================================================================= +# validate-config.yml — Validate config files against schema +# ============================================================================= +# Triggered on PRs and pushes that touch config/ or this workflow. +# Validates YAML syntax and JSON Schema compliance. +# ============================================================================= + +name: Validate Configuration + +on: + push: + branches: [main] + paths: + - 'config/**' + - '.github/workflows/validate-config.yml' + pull_request: + branches: [main] + paths: + - 'config/**' + workflow_dispatch: + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install dependencies + run: pip install pyyaml jsonschema + + - name: Validate infrastructure.yml against schema + run: | + python3 -c " + import yaml, json, sys + from jsonschema import validate, ValidationError + + with open('config/infrastructure.yml') as f: + data = yaml.safe_load(f) + + with open('config/schema/variables.schema.json') as f: + schema = json.load(f) + + try: + validate(instance=data, schema=schema) + print('✅ config/infrastructure.yml passes schema validation') + except ValidationError as e: + print(f'❌ Schema validation failed: {e.message}') + print(f' Path: {\" > \".join(str(p) for p in e.absolute_path)}') + sys.exit(1) + " + + - name: Validate variables.example.yml syntax + run: | + python3 -c " + import yaml, sys + with open('config/variables.example.yml') as f: + data = yaml.safe_load(f) + if data is None: + print('❌ variables.example.yml is empty') + sys.exit(1) + print('✅ config/variables.example.yml is valid YAML') + "