Source/RunbookEntrypoint.ps1 (77 lines of code) (raw):
<#
.SYNOPSIS
Provides fast failover for a large set of Azure SQL databases.
.DESCRIPTION
Provides fast failover for a large set of Azure SQL databases.
.PARAMETER SubscriptionId
Specifies the subscription that contains the target databases. If omitted, the subscription that contains this runbook will be assumed.
.PARAMETER ServerName
Specifies the name of the logical server that contains the target databases. If omitted, all logical servers in the target subscription will be targeted.
.INPUTS
None. You can't pipe objects to this script.
.OUTPUTS
Output messages intended for user interface, for compatibility with Azure Automation.
#>
#Read input parameters subscriptionId and ResourceGroupName and LogicalServerName
param(
# SubscriptionId: This is the ID of the subscription where the resources to be failed over are located.
# Use * to target the default subscription in the tenant.
[Parameter(Mandatory=$true)]
[string]$SubscriptionId,
# ResourceGroupName: This is the name of the resource group where the resources to be failed over are located.
# Use * to target all resource groups in the subscription.
[Parameter(Mandatory=$true)]
[string]$ResourceGroupName = "Use * for all resource groups",
# LogicalServerName: This is the name of the logical server where the resources to be failed over are located.
# Use * to target all logical servers in the subscription.
[Parameter(Mandatory=$true)]
[string]$LogicalServerName = "Use * for all logical servers or comma-delimited list of server names with no quotes",
# branch_name: This is the name of the branch to use to get the scripts that are eecuted by the runbook.
# Use main to target the main branch, leaving this empty will default to main.
[Parameter(Mandatory=$false)]
[string]$branch_name="main"
)
$scriptStartTime = (Get-Date).ToUniversalTime().ToString("o")
Write-Output "Executing RunbookEntrypoint.ps1 with PS ver $($PSVersionTable.PSVersion) at $($scriptStartTime) on $($env:COMPUTERNAME) as $($env:USERNAME) from branch_name: $branch_name"
# Gets all script files from the specified remote URI (github repo) and puts them in the specified local path (runbook path).
function Get-File ([string]$remoteRootUri, [string]$remoteFile, [string]$localRootPath, [ref]$localFilePath = '') {
$remoteFileUri = "$($remoteRootUri)/$($remoteFile)"
$localFileName = [System.IO.Path]::GetFileName($remoteFile)
$downloadedFilePath = "$($localRootPath)\$($localFileName)"
Write-Output "Downloading $($remoteFileUri)..."
Invoke-WebRequest -Uri $remoteFileUri -OutFile $downloadedFilePath
Unblock-File $downloadedFilePath
$localFilePath.Value = $downloadedFilePath
}
function Get-AllFiles ([string]$remoteRootUri, [string]$localRootPath, [ref]$allFiles) {
# A comment about the $localFilePaths output parameter: In PS a "Write-Output $x" is equivalent to "return $x".
# We cannot use the output stream for function return values because, in Azure Automation, the output stream is
# dedicated to logging. (Write-Host is not displayed.) So we use function output parameters instead of 'return'.
$manifestFilePath = [string]""
Get-File -remoteRootUri $remoteRootUri -remoteFile 'Source/RunbookEntrypointManifest.json' -localRootPath $localRootPath -localFilePath ([ref]$manifestFilePath)
$allFiles.Value = (Get-Content $manifestFilePath | ConvertFrom-Json)
# create the script objects and set their execution parameters
foreach ($file in $allFiles.Value) {
$localFilePath = ''
Get-File -remoteRootUri $remoteRootUri -remoteFile $file.File -localRootPath $localRootPath -localFilePath ([ref]$localFilePath)
Add-Member -InputObject $file -NotePropertyName LocalFilePath -NotePropertyValue $localFilePath
Add-Member -InputObject $file -NotePropertyName SubscriptionId -NotePropertyValue $SubscriptionId
Add-Member -InputObject $file -NotePropertyName ResourceGroupName -NotePropertyValue $ResourceGroupName
Add-Member -InputObject $file -NotePropertyName LogicalServerName -NotePropertyValue $LogicalServerName
}
}
# Make script stop on exception
$ErrorActionPreference = "Stop"
$remoteRootUri = "https://raw.githubusercontent.com/Azure/AzureSqlBulkFailover/$branch_name"
$localRootPath = [System.IO.Path]::Combine($env:TEMP, "AzureSqlBulkFailover_$([System.Guid]::NewGuid())")
New-Item -Path $localRootPath -ItemType "directory" | Out-Null
$allFiles = @()
Get-AllFiles -remoteRootUri $remoteRootUri -localRootPath $localRootPath -allFiles ([ref]$allFiles)
$scriptsToExecute = ($allFiles | Where-Object { $_.Execute -eq $true })
$scriptNum = 0
foreach ($scriptToExecute in $scriptsToExecute) {
$scriptNum++
Write-Output "----`r`n---- Executing $($scriptToExecute.File) ($($scriptNum) of $($scriptsToExecute.Length))...`r`n----"
$scriptToExecute | Format-List -Property *
& ($scriptToExecute.LocalFilePath) -ScriptProperties $scriptToExecute
}