AzLocal.UpdateManagement

0.7.63

PowerShell module to manage Azure Local (formerly Azure Stack HCI) cluster updates using Azure Update Manager APIs. Provides functions to start updates, check update status, list available updates, and monitor update runs. Renamed from AzStackHci.ManageUpdates in v0.7.3 to align with the Azure Local product name.

Minimum PowerShell version

5.1

Installation Options

Copy and Paste the following command to install this package using PowerShellGet More Info

Install-Module -Name AzLocal.UpdateManagement

Copy and Paste the following command to install this package using Microsoft.PowerShell.PSResourceGet More Info

Install-PSResource -Name AzLocal.UpdateManagement

You can deploy this package directly to Azure Automation. Note that deploying packages with dependencies will deploy all the dependencies to Azure Automation. Learn More

Manually download the .nupkg file to your system's default download location. Note that the file won't be unpacked, and won't include any dependencies. Learn More

Owners

Copyright

(c) Microsoft. All rights reserved.

Package Details

Author(s)

  • Neil Bird Microsoft

Tags

Azure AzureLocal AzureStackHCI Updates UpdateManager HCI Automation CICD Pipeline ServiceNow ITSM Incident

Functions

Connect-AzureLocalServicePrincipal Start-AzureLocalClusterUpdate Get-AzureLocalClusterUpdateReadiness Get-AzureLocalClusterInventory Get-AzureLocalClusterInfo Get-AzureLocalUpdateSummary Get-AzureLocalAvailableUpdates Get-AzureLocalUpdateRuns Set-AzureLocalClusterUpdateRingTag Invoke-AzureLocalFleetOperation Get-AzureLocalFleetProgress Test-AzureLocalFleetHealthGate Export-AzureLocalFleetState Resume-AzureLocalFleetUpdate Stop-AzureLocalFleetUpdate Test-AzureLocalClusterHealth Get-AzureLocalFleetStatusData New-AzureLocalFleetStatusHtmlReport Test-AzureLocalUpdateScheduleAllowed Reset-AzureLocalSideloadedTag Get-AzureLocalItsmConfig Test-AzureLocalItsmConnection New-AzureLocalIncident Copy-AzureLocalPipelineExample Copy-AzureLocalItsmSample

PSEditions

Desktop Core

Dependencies

This module has no dependencies.

Release Notes

## Version 0.7.63 - PowerShell 7 ParserError fix in fleet-update-status pipeline samples

### Fixed (critical)

- fleet-update-status.yml samples (GitHub Actions and Azure DevOps)
 failed on the Create Status Summary step under pwsh 7 (default
 shell on GH-hosted Windows runners) with
 "ParserError: The Unicode escape sequence is not valid". Inside
 the PS double-quoted here-string that builds the Markdown summary,
 Markdown code-span backticks before file names like
 update-summaries.csv and update-runs.csv were interpreted as the
 PS 7 `u{xxxx} Unicode escape (which expects `{` next); PS 5.1 had
 silently swallowed the backtick. Other file refs in the same block
 had latent corruption under both shells (`r -> CR, `a -> BEL,
 `c -> dropped backtick). All Markdown code-span backticks in the
 affected blocks have been doubled, which renders as a literal
 backtick in the output string under both PS 5.1 and PS 7. No
 module code paths are affected; only the sample YAMLs.

### Pipeline migration

If you have copied fleet-update-status.yml into your repo, refresh
the samples via:
 Copy-AzureLocalPipelineExample -Destination <path> -Platform GitHub      -Update
 Copy-AzureLocalPipelineExample -Destination <path> -Platform AzureDevOps -Update

## Version 0.7.62 - Apply-updates pipeline now consumes the readiness CSV; health gate, JUnit Status mapping, tag-write RBAC fixes

### Fixed (critical)

- Start-AzureLocalClusterUpdate Step 3b critical-health gate was being
 silently bypassed. The caller invoked Test-AzureLocalClusterHealth
 without -PassThru; the function logs to the host stream only and
 returns $null without -PassThru, so the predicate
 `$healthResults[0].CriticalCount -gt 0` always evaluated false even
 when the function had just logged "BLOCKED (N critical)". Apply
 would then write "No critical health issues found - cluster is
 eligible for update" and proceed to PATCH the update despite
 critical health failures. Two additional call sites in
 Get-AzureLocalUpdateRuns had the same omission. All three now pass
 -PassThru.
- Set-AzLocalClusterTagsMerge (used by Start-AzureLocalClusterUpdate to
 stamp UpdateVersionInProgress, by Reset-AzureLocalSideloadedTag, and
 by the sideloaded auto-reset path) now writes tags via the ARM tags
 subresource (PATCH .../providers/Microsoft.Resources/tags/default,
 api-version=2021-04-01) instead of the full cluster resource. This
 narrows the required RBAC from `microsoft.azurestackhci/clusters/write`
 to `Microsoft.Resources/tags/write` (built-in Tag Contributor),
 matching the documented behaviour. Two PATCHes are emitted when
 needed: operation=Merge for keys being set, operation=Delete for
 keys whose input value is $null. Idempotent: skips keys whose value
 already matches and Delete keys that are not present.
- Export-ResultsToJUnitXml previously rendered Status values NotReady,
 NotConnected, NoUpdatesAvailable, NoReadyUpdates as <system-out>
 (passed) instead of <skipped>, producing misleading "all green" CI
 summaries when apply had actually skipped clusters. UpdateNotFound
 now renders as <error type="UpdateNotFound"> instead of <system-out>.
 The summary <testsuite tests/failures/errors/skipped/> counts and
 the per-testcase element now agree with the apply-updates reality.
- Get-HealthCheckFailureSummary now emits Critical-severity entries
 before Warning before the top-5 truncation; previously a Critical
 hidden behind 5+ Warnings was dropped, and the readiness gate
 silently failed to downgrade ReadyForUpdate. Informational entries
 remain excluded.

### Changed

- apply-updates pipeline samples (GitHub Actions + Azure DevOps) now
 consume the readiness CSV from the check-readiness job instead of
 re-discovering clusters by UpdateRing tag. The apply step downloads
 the readiness-report artifact, filters rows where
 ReadyForUpdate=True, and invokes Start-AzureLocalClusterUpdate
 -ClusterResourceIds @(...) against that exact list. Apply still
 re-validates each cluster (Step 1b connectivity, Step 3b health,
 Step 3c schedule, Step 3b1 sideloaded) as defence in depth.
 This guarantees the readiness gate's decision is ENFORCED rather
 than advisory: a cluster flagged Blocked in readiness will not be
 touched by apply even if its tag still matches the ring.
- Get-AzureLocalClusterUpdateReadiness output (and the readiness CSV)
 gains a ClusterResourceId column - the full ARM resource ID - so
 the apply step can pass it straight to
 Start-AzureLocalClusterUpdate -ClusterResourceIds without a second
 Resource Graph query. Populated on every row, including NotFound/
 Error rows (set from the input cluster's ResourceId where known).

### Pipeline migration

If you have copied apply-updates.yml into your repo, refresh it via:
 Copy-AzureLocalPipelineExample -Destination <path> -Platform GitHub -Update
 Copy-AzureLocalPipelineExample -Destination <path> -Platform AzureDevOps -Update
The install step's drift detector will also emit a ::notice/warning
log pointing at this once you bump REQUIRED_MODULE_VERSION to 0.7.62.

## Version 0.7.61 - Readiness gates: ClusterState + Critical health checks now block ReadyForUpdate

### Changed

- Get-AzureLocalClusterUpdateReadiness and Get-AzureLocalFleetStatusData
 now downgrade ReadyForUpdate to $false when either of these is true,
 even if ARM otherwise reports a Ready update:
 - ClusterState is not 'ConnectedRecently' (e.g. NotConnectedRecently,
   Disconnected) - ARM cannot reliably push an update to a cluster it
   has not heard from recently.
 - HealthCheckFailures contains at least one [Critical] severity entry.
 Both functions emit a new BlockingReasons CSV column listing the
 reason(s) (e.g. "NotConnectedRecently", "CriticalHealthCheck",
 "CriticalHealthCheck; NotConnectedRecently") so operators can see why
 an otherwise-ready cluster was held back.
- Start-AzureLocalClusterUpdate gains a connectivity gate (Step 1b)
 immediately after cluster lookup: clusters whose properties.status is
 not 'ConnectedRecently' are skipped with Status='NotConnected' and a
 row written to Update_Skipped.csv before any update is attempted.
 Complements the existing Step 3b critical-health gate.
- Console summary on Get-AzureLocalClusterUpdateReadiness now reports
 "Blocked by Readiness Gate: N" alongside SBE-prereq blocks. The
 per-cluster console line shows "Blocked (<reason>)" in red.

### Fixed

- Get-AzureLocalClusterUpdateReadiness JUnit XML export was emitting
 Status='Skipped' for every Ready cluster due to a boolean/string
 comparison bug (`$_.ReadyForUpdate -eq 'Yes'` against a [bool]).
 Status now correctly reports 'Ready' / 'Blocked' / 'Failed' / 'Skipped'.

## Version 0.7.60 - GitHub Actions samples refreshed for Node 24 + checks:write fix on apply-updates

Summary: all five GitHub Actions sample workflows bumped to Node 24-
compatible action majors (actions/checkout v5, actions/upload-artifact v6,
azure/login v3, dorny/test-reporter v3) to clear the "Node.js 20 actions
are deprecated" banner ahead of the Sept 2026 hard-removal. apply-updates
GH Actions sample also gained `checks: write` in both jobs, fixing
`HttpError: Resource not accessible by integration` from dorny/test-reporter
on workflow_dispatch runs (sibling workflows already had it). Full notes
in CHANGELOG.md.

## Version 0.7.50 - Pipelines install from PSGallery + Copy-AzureLocalPipelineExample gains -Update + new Copy-AzureLocalItsmSample

Summary: pipeline examples (5 GitHub Actions + 5 Azure DevOps YAMLs)
now install the module from PSGallery at runtime instead of importing
a vendored copy (default latest, optional pin via REQUIRED_MODULE_VERSION).
Copy-AzureLocalPipelineExample reshaped: -Flatten and -Force removed
(neither survived first real-world use), replaced by -Update for
controlled refresh with per-file ShouldContinue prompts and
-Confirm:$false bypass for unattended use. New public function
Copy-AzureLocalItsmSample copies the bundled ITSM connector sample
(azurelocal-itsm.yml + templates/incident-body.md) into a user-chosen
destination (default .\.itsm, matching the workflow defaults). Not
flagged as breaking: the v0.7.4 -Flatten/-Force surface had not been
adopted at removal time. Full notes in CHANGELOG.md.

## Version 0.7.41 - Hotfix: parallel fleet reads broken by v0.7.3 NestedModules refactor

Summary: hotfix for every fleet read/write function that dispatched
through Invoke-FleetJobsInParallel (and for
New-AzureLocalFleetStatusHtmlReport / Get-AzureLocalFleetStatusData).
Under -ThrottleLimit > 1 against PSGallery-installed v0.7.4, per-batch
Start-Job scriptblocks could not see module-private helpers, returning
State=Error: "Cannot use '&' to invoke in the context of module ...
because it is not imported." Inline (-ThrottleLimit 1) was unaffected.
Centralised resolution in a new private helper
Get-AzLocalModuleRootManifestPath; added regression Pester tests for
the parallel path. Full notes in CHANGELOG.md.

## Versions 0.7.4 and earlier

Highlights: ITSM ticketing (ServiceNow) phase 1 in 0.7.4, opt-in via
raise_itsm_ticket=true plus ./.itsm/azurelocal-itsm.yml. Module renamed
from AzStackHci.ManageUpdates to AzLocal.UpdateManagement in v0.7.3,
monolithic .psm1 split into Public/Private NestedModules. Earlier:
parallel fleet read paths fixed for -ThrottleLimit > 1, EndTime column
on Get-AzureLocalUpdateRuns, UpdateSideloaded auto-reset workflow, ARG
pagination beyond 1000 results, mid-run token refresh, CSV-injection
sanitisation. Full notes in CHANGELOG.md.

For full release notes on this and previous versions, see:
https://github.com/NeilBird/Azure-Local/blob/main/AzLocal.UpdateManagement/CHANGELOG.md

FileList

Version History

Version Downloads Last updated
0.7.63 (current version) 0 5/16/2026
0.7.60 1 5/15/2026
0.7.50 9 5/15/2026
0.7.41 4 5/13/2026
0.7.3 3 5/13/2026