Public/Invoke-BridgeStatusComparison.ps1
|
function Invoke-BridgeStatusComparison { <# .SYNOPSIS Συγκρίνει τις λίστες καταστάσεων γεφυρών και ενεργοποιεί ειδοποιήσεις. .DESCRIPTION Η Invoke-BridgeStatusComparison συγκρίνει την προηγούμενη και την τρέχουσα κατάσταση γεφυρών και καλεί ειδικούς handlers για αλλαγές (άνοιγμα/κλείσιμο). .PARAMETER PreviousState Η προηγούμενη λίστα καταστάσεων. .PARAMETER CurrentState Η τρέχουσα λίστα καταστάσεων. .PARAMETER ApiKey Το API Key για OCR αν απαιτηθεί. .PARAMETER PoUserKey Το User Key για Pushover ειδοποίηση. .PARAMETER PoApiKey Το API Token για Pushover ειδοποίηση. .PARAMETER Configuration (Προαιρετικό) Αντικείμενο διαμόρφωσης. Αν δεν παρέχεται, δημιουργείται αυτόματα. .OUTPUTS [System.Boolean] .EXAMPLE Invoke-BridgeStatusComparison -PreviousState $prev -CurrentState $curr -ApiKey 'abc' -PoUserKey 'user' -PoApiKey 'token' .NOTES Καταγράφει αλλαγές και ενεργοποιεί κατάλληλες ειδοποιήσεις. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'ApiKey', Justification = 'Το κλειδί API διαβάζεται από τα Docker secrets κατά το runtime, όχι από είσοδο χρήστη. Η μετατροπή σε SecureString δεν προσφέρει κανένα όφελος σε αυτό το μη διαδραστικό pipeline.')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'PoUserKey', Justification = 'Το κλειδί API διαβάζεται από τα Docker secrets κατά το runtime, όχι από είσοδο χρήστη. Η μετατροπή σε SecureString δεν προσφέρει κανένα όφελος σε αυτό το μη διαδραστικό pipeline.')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'PoApiKey', Justification = 'Το κλειδί API διαβάζεται από τα Docker secrets κατά το runtime, όχι από είσοδο χρήστη. Η μετατροπή σε SecureString δεν προσφέρει κανένα όφελος σε αυτό το μη διαδραστικό pipeline.')] [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter()] [AllowNull()] [AllowEmptyCollection()] [object[]]$PreviousState = @(), [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [object[]]$CurrentState, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$ApiKey, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$PoUserKey, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$PoApiKey, [Parameter()] [PSCustomObject]$Configuration ) try { if (-not $Configuration) { $Configuration = New-BridgeConfiguration } if (-not $PreviousState -or $PreviousState.Count -eq 0) { # Πρώτη εκτέλεση: όλες οι γέφυρες είναι νέες (=>) $diff = $CurrentState | ForEach-Object { [PSCustomObject]@{ gefyraName = $_.gefyraName gefyraStatus = $_.gefyraStatus ImageUrl = $_.ImageUrl ImageHash = $_.ImageHash SideIndicator = '=>' } } } else { # Use ImageHash if it is present on any ClosedWithSchedule states, otherwise fall back to ImageUrl $hasPreviousHash = $PreviousState | Where-Object { $_.gefyraStatus -eq $Configuration.Statuses.ClosedWithSchedule -and $null -ne $_.ImageHash } $hasCurrentHash = $CurrentState | Where-Object { $_.gefyraStatus -eq $Configuration.Statuses.ClosedWithSchedule -and $null -ne $_.ImageHash } $compareProperty = @('gefyraName', 'gefyraStatus') if ($hasPreviousHash -and $hasCurrentHash) { $compareProperty += 'ImageHash' } else { $compareProperty += 'ImageUrl' } $compareSplat = @{ ReferenceObject = $PreviousState DifferenceObject = $CurrentState Property = $compareProperty IncludeEqual = $true } $diff = Compare-Object @compareSplat } if (-not $diff) { $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = '✅ Καμία αλλαγή στις γέφυρες.' } Write-BridgeLog @writeBridgeLogSplat return $false } $changesTriggered = $false $closedStatuses = @( $Configuration.Statuses.ClosedForMaintenance, $Configuration.Statuses.ClosedWithSchedule, $Configuration.Statuses.PermanentlyClosed ) $handlerMap = @{} foreach ($status in $closedStatuses) { $handlerMap["$status|=>"] = 'Closed' } $handlerMap["$($Configuration.Statuses.Open)|=>"] = 'Opened' foreach ($change in $diff) { $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = "🌉 $($change.gefyraName) ➜ $($change.gefyraStatus) ($($change.SideIndicator))" } Write-BridgeLog @writeBridgeLogSplat if ($change.SideIndicator -eq '==') { $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = "Καμία ουσιαστική αλλαγή στην $($change.gefyraName)." } Write-BridgeLog @writeBridgeLogSplat continue } if ($change.SideIndicator -ne '=>') { # Skip any '<=' side indicators to prevent double notifications continue } $prevBridge = @($PreviousState) | Where-Object { $_.gefyraName -eq $change.gefyraName } | Select-Object -First 1 if ($prevBridge -and $prevBridge.gefyraStatus -eq $change.gefyraStatus) { # The status did not change. If it is NOT ClosedWithSchedule, skip it! if ($change.gefyraStatus -ne $Configuration.Statuses.ClosedWithSchedule) { $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = "Καμία ουσιαστική αλλαγή στην $($change.gefyraName)." } Write-BridgeLog @writeBridgeLogSplat continue } else { $currentBridge = @($CurrentState) | Where-Object { $_.gefyraName -eq $change.gefyraName } | Select-Object -First 1 if ($currentBridge -and [string]::IsNullOrEmpty($currentBridge.ImageHash) -and -not [string]::IsNullOrEmpty($prevBridge.ImageHash)) { $currentBridge.ImageHash = $prevBridge.ImageHash $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = "Αποτυχία λήψης νέου hash. Επαναχρησιμοποίηση προηγούμενου hash για την $($change.gefyraName)." } Write-BridgeLog @writeBridgeLogSplat continue } $writeBridgeLogSplat = @{ Level = 'Verbose' Stage = 'Ανάλυση' Message = "Εντοπίστηκε ενημέρωση του προγράμματος κλεισίματος για την $($change.gefyraName)." } Write-BridgeLog @writeBridgeLogSplat } } $key = "$($change.gefyraStatus)|$($change.SideIndicator)" if ($handlerMap.ContainsKey($key)) { $type = $handlerMap[$key] # Χρήση helper function για επίλυση bridge state $resolveBridgeStateForChangeSplat = @{ Change = $change PreviousState = $PreviousState CurrentState = $CurrentState } $changedBridgeState = Resolve-BridgeStateForChange @resolveBridgeStateForChangeSplat if ($changedBridgeState.Count -gt 0) { $changesTriggered = $true $notificationSplat = @{ CurrentState = $changedBridgeState PoUserKey = $PoUserKey PoApiKey = $PoApiKey Configuration = $Configuration } if ($type -eq 'Closed') { $notificationSplat.ApiKey = $ApiKey Invoke-BridgeClosedNotification @notificationSplat } else { Invoke-BridgeOpenedNotification @notificationSplat } } continue } else { $writeBridgeLogSplat = @{ Stage = 'Σφάλμα' Message = "❓ Άγνωστο combo: $key" Level = 'Warning' } Write-BridgeLog @writeBridgeLogSplat } } return $changesTriggered } catch { $writeBridgeLogSplat = @{ Level = 'Warning' Stage = 'Σφάλμα' Message = "❌ $($_.Exception.Message)" } Write-BridgeLog @writeBridgeLogSplat throw } } |