Public/New-VmPowerSchedule.ps1
|
function New-VmPowerSchedule { <# .SYNOPSIS Build a schedule from parameters instead of writing the JSON by hand .DESCRIPTION JSON is what a schedule is stored as, the way ARM JSON is what Bicep is stored as. This is the door you author through: friendly parameters in, a validated schedule out, and a clear error rather than a schedule that misbehaves at half past six. The object it returns is the long form - a list of actions, each with one action type, because that is how Microsoft.ComputeSchedule models one. Pipe it to Set-VmPowerSchedule to store it, or to Show-VmPowerScheduleCalendar to see what it will actually do before anything else sees it. .PARAMETER Name Catalogue name, and the value machines carry in their PowerSchedule tag. Lowercase letters, digits and hyphens, 3 to 40 characters, because it is also an allowedValues entry in the generated policy. .PARAMETER TimeZone Windows form ('W. Europe Standard Time') or IANA form ('Europe/Zurich'). Both resolve on the Linux workers that run PowerShell 7.2 in Azure Automation. .PARAMETER Weekdays Shorthand for Monday to Friday, as 'HH:mm-HH:mm'. Compiles into a Start and a Deallocate. .PARAMETER Daily The same shorthand, every day of the week. .PARAMETER Days Days the explicit form applies to. Defaults to every day. .PARAMETER Start Time to start the machines, in the explicit form. .PARAMETER Stop Time to deallocate them. Omit for a schedule that starts machines and never stops them. .PARAMETER ExceptDate Dates to skip, as yyyy-MM-dd. No holiday calendar ships with this tool: Switzerland alone has cantonal holidays, and a calendar that looks authoritative and is wrong is worse than none. .PARAMETER MinimumDwellMinutes Leave a machine alone for this long after acting on it. Azure bills a five-minute minimum per start, so a schedule that flaps costs money as well as being wrong. .PARAMETER DisplayName Human label for the workbook. Defaults to the name. .EXAMPLE # The common case, in one line New-VmPowerSchedule -Name office-hours-ch -TimeZone 'Europe/Zurich' -Weekdays '07:30-18:30' .EXAMPLE # Explicit days, and a Friday that ends earlier is a second schedule rather than a special case New-VmPowerSchedule -Name build-agents -TimeZone 'UTC' -Days Monday, Tuesday, Wednesday, Thursday -Start 06:00 -Stop 22:00 .EXAMPLE # Managed but never stopped: better than leaving a machine untagged, because untagged is # indistinguishable from forgotten New-VmPowerSchedule -Name always-on -TimeZone 'Europe/Zurich' -Start 06:00 .EXAMPLE # See what it does before storing it New-VmPowerSchedule -Name office-hours-ch -TimeZone 'Europe/Zurich' -Weekdays '07:30-18:30' -ExceptDate 2026-12-24, 2026-12-25 | Show-VmPowerScheduleCalendar -Days 14 .INPUTS None .OUTPUTS AzureVMPowerManagement.VmPowerSchedule .NOTES RequiredPermissions: None. This command builds an object and touches nothing. Prerequisites: PowerShell 7.2 or later. Writes: Nothing. Storing the result is Set-VmPowerSchedule's job. #> [CmdletBinding(DefaultParameterSetName = 'Shorthand')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'New- is a state-changing verb, but this builds an object in memory and touches nothing. Set-VmPowerSchedule is where anything is stored, and that is where ShouldProcess belongs.')] [OutputType('AzureVMPowerManagement.VmPowerSchedule')] param( [Parameter(Mandatory, Position = 0)] [string]$Name, [Parameter(Mandatory)] [string]$TimeZone, [Parameter(Mandatory, ParameterSetName = 'Shorthand')] [string]$Weekdays, [Parameter(Mandatory, ParameterSetName = 'Daily')] [string]$Daily, [Parameter(ParameterSetName = 'Explicit')] [ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')] [string[]]$Days, [Parameter(Mandatory, ParameterSetName = 'Explicit')] [string]$Start, [Parameter(ParameterSetName = 'Explicit')] [string]$Stop, [Parameter()] [string[]]$ExceptDate, [Parameter()] [ValidateRange(0, 1440)] [int]$MinimumDwellMinutes = 30, [Parameter()] [string]$DisplayName ) $raw = @{ name = $Name timeZone = $TimeZone exceptDates = @($ExceptDate) minimumDwellMinutes = $MinimumDwellMinutes } if ($DisplayName) { $raw['displayName'] = $DisplayName } switch ($PSCmdlet.ParameterSetName) { 'Shorthand' { $raw['weekdays'] = $Weekdays } 'Daily' { $raw['daily'] = $Daily } 'Explicit' { $applyTo = if ($Days) { $Days } else { 'All' } $actions = @(@{ action = 'Start'; at = $Start; weekDays = $applyTo }) if ($Stop) { $actions += @{ action = 'Deallocate'; at = $Stop; weekDays = $applyTo } } $raw['actions'] = $actions } } Expand-VmPowerSchedule -Schedule $raw } |