3 min read

Azure Automation RunBook WebApp

Azure Automation RunBook WebApp

Azure Web App Tags to use Runbook

Automation Powershell script (poershell version 7.1)

# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process
# Connect to Azure with system-assigned managed identity
$AzureContext = (Connect-AzAccount -Identity -Subscription "XXXXXXXX").context
$subscriptions = Get-AzSubscription | select-object Id -ExpandProperty Id
foreach ($subscription in $subscriptions) {
	# Set and store context
	Remove-AzContext -InputObject (Get-AzContext) -Force | Out-Null;
	$AzureContext = (Connect-AzAccount -Identity -Subscription $subscription).context
	#Get all WebApps that should be part of the Schedule:
	$WebApps = Get-AzResource -ResourceType "Microsoft.Web/sites" -TagName "Operational-Schedule" -TagValue "Yes"
	Write-Output "Processing Subscription $($subscription) and number of WebApps $($WebApps.length)..."
	foreach ($WebApp in $WebApps) {
		Write-Output "Processing WebApp $($WebApp.Name)..."
		$TimeZone = $($WebApp.Tags)."Operational-Timezone"
		Write-Output "WebApp defined timezone is ($TimeZone), see for available timzones: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11"
		try{
			$TimeZoneAdjusted = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId([DateTime]::Now,$TimeZone)
		}catch{
			Write-Output "Failed to set WebApp timezone due to wrong timezone configured, Norway time defaults, see for correct timzone: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11"
			$TimeZoneAdjusted = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId([DateTime]::Now,"W. Europe Standard Time")
		}
		Write-Output "Current time of WebApp after attempting adjusting the Time Zone to Operational-Timezone is: $TimeZoneAdjusted"
		### Current Time associations
		$Day = $TimeZoneAdjusted.DayOfWeek
		If ($Day -like "S*") {
			$TodayIsWeekend = $true
			$TodayIsWeekday = $false
		} else {
			$TodayIsWeekend = $false
			$TodayIsWeekday = $true
		}
		### Get Exclusions
		$Exclude = $false
		$Reason = ""
		$Exclusions = $($WebApp.Tags)."Operational-Exclusions"
		$Exclusions = $Exclusions.Split(',')
		foreach ($Exclusion in $Exclusions) {
			#Check excluded actions:
			If ($Exclusion.ToLower() -eq "stop") {$WebAppActionExcluded = "Stop"}
			If ($Exclusion.ToLower() -eq "start") {$WebAppActionExcluded = "Start"}
			#Check excluded days and compare with current day
			If ($Exclusion.ToLower() -like "*day") {
				if ($Exclusion -eq $Day) { $Exclude = $true; $Reason=$Day}
			}
			#Check excluded weekdays and copare with Today
			If ($Exclusion.ToLower() -eq "weekdays") {
                if ($TodayIsWeekday) {$Exclude = $true; $Reason="Weekday"}
			}
			#Check excluded weekends and compare with Today
			If ($Exclusion.ToLower() -eq "weekends") {
				if ($TodayIsWeekend) {$Exclude = $true; $Reason="Weekend"}
			}
			If ($Exclusion -eq (Get-Date -UFormat "%b %d")) {
				$Exclude = $true; $Reason = "Date Excluded"
			}
		}
		if (!$Exclude) {
			#Get values from Tags and compare to the current time
			if ($TodayIsWeekday) {
				$ScheduledTime = $($WebApp.Tags)."Operational-Weekdays"
				Write-Output "WebApp is scheduled to run between ($ScheduledTime) on Weekdays."
			} elseif ($TodayIsWeekend) {
				$ScheduledTime = $($WebApp.Tags)."Operational-Weekends"
				Write-Output "WebApp is scheduled to run between ($ScheduledTime) on Weekends."
			}
			if ($ScheduledTime) {
				$ScheduledTime = $ScheduledTime.Split("-")
				$ScheduledStart = $ScheduledTime[0]
				$ScheduledStop = $ScheduledTime[1]
				$ScheduledStartTime = Get-Date $ScheduledStart
				$ScheduledStopTime = Get-Date $ScheduledStop
				If (($TimeZoneAdjusted -gt $ScheduledStartTime) -and ($TimeZoneAdjusted -lt $ScheduledStopTime)) {
					#Current time is within the interval
					Write-Output "WebApp should be running now"
					$WebAppAction = "Start"
				} else {
					#Current time is outside of the operational interval
					Write-Output "WebApp should be stopped now"
					$WebAppAction = "Stop"
				}
				If ($WebAppAction -notlike "$WebAppActionExcluded") { #Make sure that action was not excluded
					#Get WebApp PowerState status
					$WebAppObject = Get-AzWebApp -ResourceGroupName $WebApp.ResourceGroupName -Name $WebApp.Name
					$WebAppstate = $WebAppObject.State.ToLower()
					if (($WebAppAction -eq "Start") -and ($WebAppstate -notlike "*running")) {
						Write-Output "Starting $($WebApp.Name)..."
						Start-AzWebApp -ResourceGroupName $WebApp.ResourceGroupName -Name $WebApp.Name
					} elseif (($WebAppAction -eq "Stop") -and ($WebAppstate -notlike "*stopped")) {
						Write-Output "Stopping $($WebApp.Name)..."
						Stop-AzWebApp -ResourceGroupName $WebApp.ResourceGroupName -Name $WebApp.Name
					} else {
						Write-Output "WebApp $($WebApp.Name) status is: $WebAppstate . No action will be performed ..."
					}
				} else {
					Write-Output "WebApp $($WebApp.Name) is Excluded from changes during this run because Operational-Exclusions Tag contains action $WebAppAction."
				}
			} else {
				Write-Output "Error: Scheduled Running Time for WebApp was not detected. No action will be performed..."
			}
		} else {
			Write-Output "WebApp $($WebApp.Name) is Excluded from changes during this run because Operational-Exclusions Tag contains exclusion $Reason."
		}
}
}
Write-Output "Runbook completed."