We’re using Azure web services for our dev and test environments. Since we only use these environments during the day, I wanted to write some automated functions to turn them off at night and turn them back on in the morning. It can be done with Azure Functions, but I thought it would be easier to build into an Azure Pipeline where developers are all doing their work anyway, so if someone needed to work after hours they would know how to get at it.
First is the PowerShell script to start or stop a service, based on this post.
# This controls an app service. Param( # The tenant ID [Parameter(Mandatory=$true)][string] $TenantId, # The subscription ID [Parameter(Mandatory=$true)] [string] $SubscriptionId, # The App Registration client ID [Parameter(Mandatory=$true)][string] $ClientId, # The App Registration client secret [Parameter(Mandatory=$true)][string] $ClientSecret, # The resource group of the service to control [Parameter(Mandatory=$true)][string] $ResourceGroup, # The name of the service to control [Parameter(Mandatory=$true)][string] $AppService, # The switch if we want to start [switch] $Start = $false, # The switch if we want to start [switch] $Stop = $false ) $StartOrStop = "" if ( $Start ) { $StartOrStop = "start" } if ( $Stop ) { $StartOrStop = "stop" } # Get the authentication token $Auth = Invoke-RestMethod ` -Uri "https://login.microsoftonline.com/$TenantId/oauth2/token?api-version=1.0" ` -Method Post ` -Body @{"grant_type" = "client_credentials"; ` "resource" = "https://management.core.windows.net/"; ` "client_id" = "$ClientId"; ` "client_secret" = "$ClientSecret"} $HeaderValue = "Bearer " + $Auth.access_token # Control the service Write-Output "Executing $AppService $StartOrStop..." Invoke-RestMethod ` -Uri "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Web/sites/$AppService/$StartOrStop`?api-version=2018-02-01" ` -Method Post ` -Headers @{Authorization = $HeaderValue} Write-Output "Done $Command $AppService"
Then there's the pipeline yaml to run the script. This is the "Start" version. I'll leave "Stop" as an exercise for the reader.
name: $(Date:yyyyMMdd)-$(Rev:r) jobs: - job: "Build" pool: vmImage: 'windows-2019' variables: tenantId: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' subscriptionId: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' clientId: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' # Note: clientSecret set in Azure Pipeline resourceGroup: 'MY_RESOURCE_GROUP' appService: 'MY_APP_SERVICE' steps: - task: PowerShell@2 displayName: 'Start $(appService)' inputs: errorActionPreference: Stop targetType: filePath filePath: '$(Build.SourcesDirectory)\ControlAppService.ps1' arguments: '-Start -AppService $(appService) -TenantId $(tenantId) -SubscriptionId $(subscriptionId) -ClientId $(clientId) -ClientSecret $(clientSecret) -ResourceGroup $(resourceGroup)'
I have the clientSecret set up in the Azure Pipeline’s variables as a secret value.
That’s pretty much it. The pipelines are set to run on a timer: Stop at 7pm; Start at 7am.