Private/Test-MaintenanceWindow.ps1
|
function Test-MaintenanceWindow { <# .SYNOPSIS Checks if a computer is currently within a defined maintenance window. .DESCRIPTION Reads maintenance window definitions from the engine configuration file at $env:USERPROFILE\.runbookengine\maintenance-windows.json. Supports both one-time windows and recurring weekly windows. Window format: { ComputerName, Pattern, Start, End, Recurring, DayOfWeek } #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$ComputerName, [Parameter()] [string]$ConfigPath ) if (-not $ConfigPath) { $ConfigPath = Join-Path $env:USERPROFILE '.runbookengine\maintenance-windows.json' } $result = [PSCustomObject]@{ ComputerName = $ComputerName InWindow = $false WindowName = $null WindowStart = $null WindowEnd = $null IsRecurring = $false CheckedAt = (Get-Date).ToString('o') } if (-not (Test-Path $ConfigPath)) { Write-Verbose "No maintenance windows configuration found at $ConfigPath" return $result } try { $windowsJson = Get-Content -Path $ConfigPath -Raw -ErrorAction Stop $windows = $windowsJson | ConvertFrom-Json -ErrorAction Stop } catch { Write-Warning "Failed to parse maintenance windows configuration: $_" return $result } if (-not $windows -or $windows.Count -eq 0) { Write-Verbose "No maintenance windows defined." return $result } $now = Get-Date foreach ($window in $windows) { # Check if this window applies to this computer $matches = $false if ($window.ComputerName -and $window.ComputerName -eq $ComputerName) { $matches = $true } elseif ($window.Pattern) { if ($ComputerName -like $window.Pattern) { $matches = $true } } if (-not $matches) { continue } if ($window.Recurring -eq $true) { # Recurring window - check day of week and time $targetDay = $window.DayOfWeek $currentDay = $now.DayOfWeek.ToString() if ($targetDay -and $currentDay -eq $targetDay) { # Parse start and end as time-only values try { $startTime = [DateTime]::Parse($window.Start) $endTime = [DateTime]::Parse($window.End) # Build today's window start and end $windowStart = Get-Date -Hour $startTime.Hour -Minute $startTime.Minute -Second 0 $windowEnd = Get-Date -Hour $endTime.Hour -Minute $endTime.Minute -Second 0 # Handle overnight windows (end time less than start time) if ($windowEnd -lt $windowStart) { $windowEnd = $windowEnd.AddDays(1) } if ($now -ge $windowStart -and $now -le $windowEnd) { $result.InWindow = $true $result.WindowName = if ($window.Name) { $window.Name } else { "Recurring $targetDay window" } $result.WindowStart = $windowStart.ToString('o') $result.WindowEnd = $windowEnd.ToString('o') $result.IsRecurring = $true return $result } } catch { Write-Verbose "Failed to parse recurring window times: $_" } } } else { # One-time window - check exact datetime range try { $windowStart = [DateTime]::Parse($window.Start) $windowEnd = [DateTime]::Parse($window.End) if ($now -ge $windowStart -and $now -le $windowEnd) { $result.InWindow = $true $result.WindowName = if ($window.Name) { $window.Name } else { "One-time window" } $result.WindowStart = $windowStart.ToString('o') $result.WindowEnd = $windowEnd.ToString('o') $result.IsRecurring = $false return $result } } catch { Write-Verbose "Failed to parse one-time window dates: $_" } } } return $result } |