From c890e5b46c52d42e622a25139bc67ca48bc69658 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Mon, 4 May 2026 07:29:32 -0400 Subject: [PATCH] test harness + Get-PCProfile: alias-aware lookups for rename reorg Phase 5 + 6 of the gea-shopfloor-* rename. Get-PCProfile.ps1: when the legacy profileKey ("Standard-Machine", "CMM", etc.) is missing from siteConfig.pcProfiles, walks the alias group and returns the first matching new key ("gea-shopfloor-collections", "gea-shopfloor-cmm", etc.). Vice versa: a fleet PC writing the new string finds its profile under the old key. Same alias map shape as GE-Enforce + Install-FromManifest, kept in sync manually for now - extract to shared file later if drift becomes a problem. matrix.json: adds 3 new rows for gea-shopfloor-nocollections, gea-shopfloor-common (Timeclock+Lab merge), gea-shopfloor-heattreat (placeholder). Existing rows for legacy names retained; the new verify-state alias resolution lets either be requested. verify-state.ps1: Test-MatrixEntryMatches walks the alias map so harness invocation with "Standard Machine" or "gea-shopfloor-collections" both resolve to the same matrix row. Smoke-tested via qga-as-SYSTEM on win11: legacy Standard/Machine, new gea-shopfloor-collections, and new gea-shopfloor-nocollections all return 10/10 pass against current VM state. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Shopfloor/lib/Get-PCProfile.ps1 | 28 +++++++++++++ .../common/test/lib/verify-state.ps1 | 29 +++++++++++++- .../shopfloor-setup/common/test/matrix.json | 39 +++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/playbook/shopfloor-setup/Shopfloor/lib/Get-PCProfile.ps1 b/playbook/shopfloor-setup/Shopfloor/lib/Get-PCProfile.ps1 index 0355bfa..ac9f991 100644 --- a/playbook/shopfloor-setup/Shopfloor/lib/Get-PCProfile.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/lib/Get-PCProfile.ps1 @@ -69,11 +69,39 @@ if (Test-Path -LiteralPath $subtypeFile) { # Build the profile key: "Standard-Machine", "CMM", "Display-Lobby", etc. $profileKey = if ($pcSubtype) { "$pcType-$pcSubtype" } else { $pcType } +# 2026-05-03 rename: when the legacy key (e.g. "Standard-Machine") is not +# present in pcProfiles, fall through to the new gea-shopfloor-* equivalent +# (e.g. "gea-shopfloor-collections"). Vice versa: a fleet PC that already +# writes "gea-shopfloor-collections" finds its profile under either key. +$pcProfileAliasGroups = @( + @('Standard-Machine', 'gea-shopfloor-collections', 'gea-shopfloor-nocollections'), + @('Standard-Timeclock', 'gea-shopfloor-common'), + @('Lab', 'gea-shopfloor-common'), + @('CMM', 'gea-shopfloor-cmm'), + @('Keyence', 'gea-shopfloor-keyence'), + @('WaxAndTrace', 'gea-shopfloor-waxtrace'), + @('Genspect', 'gea-shopfloor-genspect'), + @('Display', 'gea-shopfloor-display'), + @('Heattreat', 'gea-shopfloor-heattreat') +) + # Look up the profile in pcProfiles. Fall back to $null (callers use # site-wide defaults or hardcoded values). $pcProfile = $null if ($siteConfig -and $siteConfig.pcProfiles -and $profileKey) { $pcProfile = $siteConfig.pcProfiles.$profileKey + if (-not $pcProfile) { + foreach ($g in $pcProfileAliasGroups) { + if ($g -icontains $profileKey) { + foreach ($alias in $g) { + if ($alias -ieq $profileKey) { continue } + $candidate = $siteConfig.pcProfiles.$alias + if ($candidate) { $pcProfile = $candidate; break } + } + break + } + } + } } if ($pcProfile) { diff --git a/playbook/shopfloor-setup/common/test/lib/verify-state.ps1 b/playbook/shopfloor-setup/common/test/lib/verify-state.ps1 index 0f9f1f0..5ee8a64 100644 --- a/playbook/shopfloor-setup/common/test/lib/verify-state.ps1 +++ b/playbook/shopfloor-setup/common/test/lib/verify-state.ps1 @@ -25,7 +25,34 @@ if (-not (Test-Path -LiteralPath $MatrixPath)) { } $matrix = Get-Content -LiteralPath $MatrixPath -Raw | ConvertFrom-Json -$entry = $matrix.pcTypes | Where-Object { $_.PCType -eq $PCType -and ($_.PCSubType -eq $PCSubType -or [string]::IsNullOrEmpty($_.PCSubType)) } | Select-Object -First 1 +# Alias resolution mirrors the GE-Enforce + Get-PCProfile alias maps so +# the harness can be invoked with either legacy ("Standard","CMM",...) +# or new ("gea-shopfloor-collections","gea-shopfloor-cmm",...) names +# and find the right matrix row. +$pcTypeAliasGroups = @( + @{ keys = @('Standard-Machine','gea-shopfloor-collections') }, + @{ keys = @('Standard-Machine-NoCollections','gea-shopfloor-nocollections') }, + @{ keys = @('Standard-Timeclock','Lab','gea-shopfloor-common') }, + @{ keys = @('CMM','gea-shopfloor-cmm') }, + @{ keys = @('Keyence','gea-shopfloor-keyence') }, + @{ keys = @('WaxAndTrace','gea-shopfloor-waxtrace') }, + @{ keys = @('Genspect','gea-shopfloor-genspect') }, + @{ keys = @('Display','gea-shopfloor-display') }, + @{ keys = @('Heattreat','gea-shopfloor-heattreat') }, + @{ keys = @('Shopfloor') } +) +function Test-MatrixEntryMatches { + param($Entry, [string]$Type, [string]$SubType) + $entryKey = if ($Entry.PCSubType) { "$($Entry.PCType)-$($Entry.PCSubType)" } else { $Entry.PCType } + $requestKey = if ($SubType) { "$Type-$SubType" } else { $Type } + if ($entryKey -ieq $requestKey) { return $true } + foreach ($g in $pcTypeAliasGroups) { + if ($g.keys -icontains $entryKey -and $g.keys -icontains $requestKey) { return $true } + } + return $false +} + +$entry = $matrix.pcTypes | Where-Object { Test-MatrixEntryMatches -Entry $_ -Type $PCType -SubType $PCSubType } | Select-Object -First 1 if (-not $entry) { Write-Host "[FAIL] no matrix entry for PCType=$PCType PCSubType=$PCSubType" exit 1 diff --git a/playbook/shopfloor-setup/common/test/matrix.json b/playbook/shopfloor-setup/common/test/matrix.json index 0f16333..a2f4fcc 100644 --- a/playbook/shopfloor-setup/common/test/matrix.json +++ b/playbook/shopfloor-setup/common/test/matrix.json @@ -56,6 +56,45 @@ "driftScenarios": [] }, + { + "PCType": "gea-shopfloor-nocollections", "PCSubType": "", + "scopes": ["common", "gea-shopfloor-nocollections"], + "_comment": "Variant of Machine-with-collections that omits UDC. Manifest is identical to gea-shopfloor-collections minus the UDC application + UDC Webserver Settings + UDC Data Restore entries (3 dropped). Verifies eDNC + eMxInfo + FMS reg drift-catchers same as collections.", + "apps": [ + { "$ref": "common.all" }, + { "$ref": "common.fmsResolver" }, + { "$ref": "common.oracle" }, + { "$ref": "common.openText" }, + { "name": "FMS Primary host", "verify": { "method": "Registry", "path": "HKLM:\\SOFTWARE\\WOW6432Node\\GE Aircraft Engines\\Dnc\\FMS", "name": "FMSHostPrimary", "value": "wjfms3.ae.ge.com" } }, + { "name": "FMS Secondary host", "verify": { "method": "Registry", "path": "HKLM:\\SOFTWARE\\WOW6432Node\\GE Aircraft Engines\\Dnc\\FMS", "name": "FMSHostSecondary", "value": "10.233.112.158" } }, + { "name": "eDNC bundles NTLARS", "verify": { "method": "FileVersion", "path": "C:\\Program Files (x86)\\Dnc\\bin\\DncMain.exe", "value": "6.4.5.0" } } + ], + "driftScenarios": [] + }, + + { + "PCType": "gea-shopfloor-common", "PCSubType": "", + "scopes": ["common", "gea-shopfloor-common"], + "_comment": "Merged Timeclock+Lab type. Common-scope FMS hosts pin applies (PCTypes filter includes Standard, which aliases to common via the rename map). No machine-specific stack (no eDNC, UDC, FMS reg). Differences between Timeclock and Lab originally - now handled per-PC via Configure-PC.ps1's pcProfiles.gea-shopfloor-common.startupItems lookup.", + "apps": [ + { "$ref": "common.all" }, + { "$ref": "common.fmsResolver" }, + { "$ref": "common.oracle" }, + { "$ref": "common.openText" } + ], + "driftScenarios": [] + }, + + { + "PCType": "gea-shopfloor-heattreat", "PCSubType": "", + "scopes": ["common", "gea-shopfloor-heattreat"], + "_comment": "Placeholder - empty Applications array on the share manifest. Common-scope apps still apply per their PCTypes filters (most are *). When heattreat-specific apps are identified, drop them in apps/ and add Applications + matrix rows.", + "apps": [ + { "$ref": "common.all" } + ], + "driftScenarios": [] + }, + { "PCType": "CMM", "PCSubType": "", "scopes": ["common", "cmm"],