Tags: Azure/ALZ-PowerShell-Module
Tags
fix: bump hcl2json parser to v0.6.9 for namespaced provider functions (… …#535) ## Summary Bumps the pinned `hcl2json` (HCLToJSON) parser version from `v0.6.0` to **`v0.6.9`** in `Deploy-Accelerator.ps1`, so the accelerator can parse Terraform **provider-defined (namespaced) functions**. ## Root cause When running `Deploy-Accelerator`, the ALZ module downloads the `tmccombs/hcl2json` binary and uses it to convert the accelerator's `variables.*.tf` template files into JSON to build the input config schema. A template in the `alz-terraform-accelerator` repo (`templates/platform_landing_zone/variables.connectivity.virtual.wan.tf`) now uses a provider-defined function: ```hcl || can(provider::azapi::parse_resource_id("Microsoft.Network/virtualWans", var.virtual_wan_settings.virtual_wan.id).name) ``` The pinned `hcl2json` `v0.6.0` vendors `github.com/hashicorp/hcl/v2 v2.17.0`, which predates support for the namespaced `provider::<ns>::<func>()` call syntax (added to `hashicorp/hcl/v2` in **v2.20.0**, "Support for namespaced functions"). So `v0.6.0` parses `provider` as a normal identifier, hits the first `::`, and fails: ``` Failed to convert file: parse config: [...variables.connectivity.virtual.wan.tf:1043,22-23: Missing argument separator; A comma is required to separate each function argument from the next.] ``` (col 22–23 is exactly the first `::`.) ## Fix Bump to `hcl2json` **`v0.6.9`** (latest release), which vendors `hashicorp/hcl/v2 v2.24.0` and fully supports the namespaced function syntax. This unblocks parsing of `provider::azapi::parse_resource_id` in the platform landing zone variables. ## Notes - `Private/Tools/Get-HCLParserTool.ps1` needs **no changes** — it builds the asset filename as `hcl2json_<os>_<arch>` (plus `.exe` on Windows) and downloads from `https://github.com/tmccombs/hcl2json/releases/download/<toolVersion>/<asset>`. The `v0.6.9` release assets keep the same naming scheme, so the downloader is compatible. - `v0.6.0` was the only hard-coded reference to the parser version in the repo; the `.gitignore` entry for the binary is version-agnostic and the unit tests mock `Get-HCLParserTool`. - Module versioning is handled by release automation (release-drafter), so the `.psd1` ModuleVersion is intentionally left untouched, matching repo precedent. ## Validation `Invoke-Build -File .\src\ALZ.build.ps1 -Task TestLocal` → **Build succeeded. 7 tasks, 0 errors, 0 warnings.** - PSScriptAnalyzer (Module + Tests): clean - Pester: **47 passed, 0 failed, 0 skipped** ## Files changed - `src/ALZ/Public/Deploy-Accelerator.ps1` — `toolVersion` `v0.6.0` → `v0.6.9` Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix: handle expired gh CLI tokens and macOS restricted file access (#533 ) ## Summary Fixes two classes of user-reported failures: 1. **GitHub API 403s when the `gh` CLI token is expired.** The module attaches the token from `gh auth token` to API requests; when that token is expired or has insufficient scopes, `api.github.com` returns 403 and the deployment fails with a misleading downstream error (`The release v does not exist...`). 2. **macOS file access errors** on protected paths when reading files without `-Force`. ## Changes ### GitHub auth resiliency - `Invoke-GitHubApiRequest`: when the attached `gh` token causes a 401/403, automatically retry once without auth (anonymous, subject to rate limits) and warn the user to run `gh auth login`. Applies to all three code paths (file download, `SkipHttpErrorCheck`, standard API call). Factored repeated logic into `Disable-AuthAndWarn` and `Get-StatusCodeFromError` helpers. - `Get-GithubReleaseTag`: on 401/403, throw an actionable error naming the likely cause (expired gh token or rate limiting) and the fix (`gh auth login`) instead of the generic "check your internet connection" message. - `Test-NetworkConnectivity`: inspect the status code from the `api.github.com` probe and record 401/403 as a Failure with the same guidance, so connectivity checks surface this issue up front. ### macOS file access - Added `-Force` to every `Get-Item`, `Get-ChildItem`, and `Get-Content` call across the module so reads succeed on macOS paths where hidden/protected attributes would otherwise block access. (`Test-Path` / `Resolve-Path` intentionally untouched — they do not support `-Force`.) ### UX - `Get-AzureContext`: clarified that "Querying Azure for management groups, subscriptions, and regions..." can take up to 30 seconds. ## Testing - `Invoke-Build -File .\src\ALZ.build.ps1` — passes locally. - Existing `Test-NetworkConnectivity.Tests.ps1` still covers the mocked success/failure paths.
feat: add SMB scenarios 10 and 11, load scenarios from JSON config (#532 ) ## Summary Adds missing SMB scenarios 10 and 11 to the accelerator folder structure creation, and refactors scenario management to use the existing `TerraformScenarios.json` config file as the single source of truth. Closes Azure/Azure-Landing-Zones#4105 ## Changes ### TerraformScenarios.json - Added `path` property to each scenario entry, mapping scenario numbers to their tfvars file paths - Scenarios 10 and 11 were already present (labels only) — now they also have paths: - **10**: `smb-single-region/hub-and-spoke-vnet.tfvars` - **11**: `smb-single-region/virtual-wan.tfvars` ### New-AcceleratorFolderStructure.ps1 - Replaced hardcoded `` hashtable with dynamic loading from `TerraformScenarios.json` - Fixed `int64`/`int32` type mismatch when looking up scenario paths (JSON parser returns `int64`, parameter is `[int]`/`int32` — without the cast, hashtable lookup returns `` and `Copy-Item` creates a directory instead of copying the file)
refactor: extract Terraform scenarios to JSON config and add SMB scen… …arios (#531) ## Summary Azure/Azure-Landing-Zones#4095 Extract the hardcoded Terraform scenario options from `Request-AcceleratorConfigurationInput.ps1` into a dedicated `TerraformScenarios.json` config file, making it easier to add, remove, or update scenarios without modifying PowerShell code. ## Changes - **New file**: `TerraformScenarios.json` - JSON array of scenario objects with `label` and `value` properties - **Modified**: `Request-AcceleratorConfigurationInput.ps1` - loads scenarios from the JSON file via `ConvertFrom-Json` instead of inline array - **Added scenarios 10-11**: SMB Single-Region Hub and Spoke VNet / Virtual WAN (per Azure/alz-terraform-accelerator#305)
Add verbose logging to Invoke-HttpRequestWithRetry (#530) Adds Write-Verbose logging to Invoke-HttpRequestWithRetry so HTTP request details and errors are visible when running with -Verbose. ## Changes - Log request method, URI, retry config, timeout, and download path on entry - Log each attempt number - Log transient status codes before retrying - Log final status code on success with SkipHttpErrorCheck - Log download completion with file path - Log status code and exception message on errors
Refactor HTTP requests to use centralized Invoke-HttpRequestWithRetry (… …#529) ## Summary Introduces a new `Invoke-HttpRequestWithRetry` cmdlet that centralizes HTTP retry logic for transient errors (408, 429, 500, 502, 503, 504) and refactors existing callers to use it. ## Changes - **New cmdlet**: `Invoke-HttpRequestWithRetry` in `Private/Shared` — wraps `Invoke-WebRequest` with configurable retry count, interval, and transient status code handling - **Refactored** `Invoke-GitHubApiRequest` to delegate retry logic to the new shared cmdlet instead of implementing its own retry loop - **Updated** `Test-NetworkConnectivity` to use `Invoke-HttpRequestWithRetry` instead of calling `Invoke-WebRequest` directly - **Updated** `Get-TerraformTool` to use `Invoke-HttpRequestWithRetry` for HashiCorp API calls and file downloads - **Updated** unit tests to mock `Invoke-HttpRequestWithRetry` instead of `Invoke-WebRequest` ## Benefits - Single place to maintain retry logic, reducing duplication - Consistent retry behavior across all HTTP calls in the module - Easier to test and extend retry behavior in the future
feat: centralize GitHub API requests with auth and retry logic (#528) ## Summary Introduces a centralized `Invoke-GitHubApiRequest` function that consolidates all GitHub API calls with: - **Automatic authentication** via GitHub CLI (`gh auth token`) when available, increasing API rate limits - **Configurable retry logic** for transient HTTP errors (408, 429, 500, 502, 503, 504) - **Consistent error handling** across all GitHub API interactions ## Changes ### New Function - **`Invoke-GitHubApiRequest`** — Central function for all GitHub HTTP requests with auth header injection and retry support ### Updated Functions - **`Get-GithubRelease`** — Uses `Invoke-GitHubApiRequest` instead of `Invoke-WebRequest` for downloading release artifacts - **`Get-GithubReleaseTag`** — Uses `Invoke-GitHubApiRequest` instead of `Invoke-RestMethod` with inline retry logic removed - **`Get-HCLParserTool`** — Uses `Invoke-GitHubApiRequest` for downloading HCL parser binaries - **`Test-NetworkConnectivity`** — Routes `api.github.com` connectivity check through `Invoke-GitHubApiRequest` - **`New-ModuleSetup`** — Propagates `maxRetryCount` parameter; fixes `isFirstRun` → `firstRun` variable references - **`New-FolderStructure`** — Accepts and passes through `maxRetryCount` parameter - **`Deploy-Accelerator`** — Adds `github_max_retry_count` parameter (alias: `gmrc`, `githubMaxRetryCount`) ### Tests - Updated `Test-NetworkConnectivity.Tests.ps1` to mock `Invoke-GitHubApiRequest` for the GitHub API endpoint
feat: Add NetworkConnectivity pre-flight check to Test-AcceleratorReq… …uirement (#527) - [x] Understand current state of checks in `Deploy-Accelerator.ps1` and `Test-NetworkConnectivity.ps1` - [x] Add `https://www.powershellgallery.com` endpoint to `Test-NetworkConnectivity.ps1` - [x] Add `NetworkConnectivity` to the checks in `Deploy-Accelerator.ps1` (guarded by `skip_internet_checks`) - [x] Update `Test-NetworkConnectivity.Tests.ps1` endpoint count assertions: 5 → 6 - [x] All 47 unit tests pass <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> ## Summary Add a new `NetworkConnectivity` check to `Test-AcceleratorRequirement` (and the underlying `Test-Tooling` plumbing) that probes the external URLs the module must reach during a Bicep deployment, before any download or API call is attempted. ## Background Currently the module has no pre-flight network reachability check. It assumes connectivity is present and only surfaces failures at the point of use (e.g. inside `Invoke-WebRequest`/`Invoke-RestMethod`). This makes it hard for users in restricted environments to diagnose connectivity issues early. ## Changes Required ### 1. New file: `src/ALZ/Private/Tools/Checks/Test-NetworkConnectivity.ps1` Create a new check function following the same pattern as the existing checks (e.g. `Test-GitInstallation.ps1`). It should: - Probe each of the external endpoints the module calls during a Bicep deployment using `Invoke-WebRequest` with `-Method Head` (or a lightweight GET where HEAD is not supported), with a short timeout (e.g. 10 seconds) and `-SkipHttpErrorCheck` / `-ErrorAction SilentlyContinue` so it doesn't throw. - Return a `Results` array and a `HasFailure` bool in the same shape as all other checks. - Treat any endpoint that **cannot be reached** (connection error / timeout) as a **Failure**, and any reachable endpoint (even a non-200 status, which may just be auth) as a **Success** — the goal is reachability, not authentication. - The endpoints to check are: | Endpoint | Purpose | |---|---| | `https://api.github.com` | GitHub API (release tag lookups) | | `https://github.com` | Bootstrap & starter module downloads | | `https://api.releases.hashicorp.com` | Terraform version resolution | | `https://releases.hashicorp.com` | Terraform binary download | | `https://management.azure.com` | Azure Management API | Example skeleton (follow the pattern of `Test-GitInstallation.ps1`): ```powershell function Test-NetworkConnectivity { [CmdletBinding()] param() $results = @() $hasFailure = $false $endpoints = @( @{ Uri = "https://api.github.com"; Description = "GitHub API (release lookups)" }, @{ Uri = "https://github.com"; Description = "GitHub (module downloads)" }, @{ Uri = "https://api.releases.hashicorp.com"; Description = "HashiCorp Releases API (Terraform version)" }, @{ Uri = "https://releases.hashicorp.com"; Description = "HashiCorp Releases (Terraform binary download)" }, @{ Uri = "https://management.azure.com"; Description = "Azure Management API" } ) foreach ($endpoint in $endpoints) { Write-Verbose "Testing network connectivity to $($endpoint.Uri)" try { $response = Invoke-WebRequest -Uri $endpoint.Uri -Method Head -TimeoutSec 10 -SkipHttpErrorCheck -ErrorAction Stop -UseBasicParsing $results += @{ message = "Network connectivity to $($endpoint.Description) ($($endpoint.Uri)) is available." result = "Success" } } catch { $results += @{ message = "Cannot reach $($endpoint.Description) ($($endpoint.Uri)). Check network/firewall settings. Error: $($_.Exception.Message)" result = "Failure" } $hasFailure = $true } } return @{ Results = $results HasFailure = $hasFailure } } ``` ### 2. Update `src/ALZ/Private/Tools/Test-Tooling.ps1` - Add `"NetworkConnectivity"` to the `[ValidateSet(...)]` on the `$Checks` parameter. - Add a new `if ($Checks -contains "NetworkConnectivity")` block that calls `Test-NetworkConnectivity` and accumulates results, following the same pattern as the other checks. ### 3. Update `src/ALZ/Public/Test-AcceleratorRequirement.ps1` - Add `"NetworkConnectivity"` to the `[ValidateSet(...)]` on the `$Checks` parameter. - Add `"NetworkConnectivity"` to the **default** value of `$Checks` so it runs automatically when `Test-AcceleratorRequirement` is called with no arguments. - Update the `.SYNOPSIS`/`.DESCRIPTION` doc comment to mention the network connectivity check. ### 4. Add unit tests: `src/Tests/Unit/Private/Test-NetworkConnectivity.Tests.ps1` Add Pester unit tests for `Test-NetworkConnectivity` following the pattern used by other tests in `src/Tests/Unit/`. Cover at minimum: - All endpoints reachable → no failure, all Success results. - One or more endpoints unreachable (mock `Invoke-WebRequest` to throw) → `HasFailure = $true`, correct Failure messages. ## Notes - **Do not** add `NetworkConnectivity` to the default checks inside `Deploy-Accelerator.ps1` — it already has its own `$skip_internet_checks` bypass path and calling a network check there would be redundant. The check belongs in `Test-AcceleratorRequirement` only. - Keep the check **non-blocking** in the sense that it should check all endpoints and report all failures, not stop at the first unreachable one. - Follow t... </details> <!-- START COPILOT CODING AGENT SUFFIX --> *This pull request was created from Copilot chat.* > <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/Azure/ALZ-PowerShell-Module/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jtracey93 <41163455+jtracey93@users.noreply.github.com>
PreviousNext