This post covers the automation of cloning a Synapse dedicated SQL pool from one workspace to another where locks and encryption exist.

The steps required by the code are as follows:
Variables:
$AzTargetWorkspace
$TargetResourceGroup
$SourceSqlPool
$TargetSqlPool
YAML parameters:
$sourceEnvironment = ${{ parameters.source_env }}
$sourceResourceGroup = ${{ parameters.source_rg }}
$sourceWorkspace = ${{ parameters.source_ws }}
$sourceSqlPool = ${{ parameters.source_sql_pool }}
$targetEnvironment = ${{ parameters.target_env }}
$targetResourceGroup = ${{ parameters.target_rg }}
$targetWorkspace = ${{ parameters.target_ws }}
$targetSqlPool = ${{ parameters.target_sql_pool }}
$keepTargetSqlPool = ${{ parameters.keep_target_sql_pool }}
$databaseScale = ${{ parameters.database_scale }}
YAML variables:
Key Vault URL Prefix= ${{ variables.kv_url_prefix }}
Deletes the workspace lock
- task: AzureCLI@2
name: delete_lock
displayName: Delete workspace lock
inputs:
azureSubscription: ${{ variables.azure_connection }}
ScriptType: ps
ScriptLocation: inlineScript
inlineScript: |
#1
$resourceLocks = $(az lock list `
--resource-group ${{ parameters.target_rg }} `
--query "[?name=='lock-${{ parameters.target_rg }}']" `
| ConvertFrom-Json)
$resourceLockExists = $resourceLocks.count -eq 1
#2
Write-Host "##vso[task.setvariable variable=resource_lock_exists;isOutput=true]$resourceLockExists"
#3
if ( $resourceLockExists ) {
Write-Host "Removing workspace lock 'lock-${{ parameters.target_rg }}'"
az lock delete `
--name lock-${{ variables.target_resource_group }} `
--resource-group ${{ parameters.target_rg }}
}
Change encryption key
- task: AzureCLI@2
name: change_key1
displayName: Change encryption key
inputs:
azureSubscription: ${{ variables.azure_connection }}
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
#1
if ("${{ parameters.source_ws }}" -eq "ws-prd") {
$SourceWsKvKeyName = "key-prd"
}
else
$SourceWsKvKeyName = "key-test"
}
#2
$Keys = az synapse workspace key list `
--workspace-name ${{ parameters.target_ws }} `
--resource-group ${{ parameters.target_rg }} `
--only-show-errors | ConvertFrom-Json
for ($i=0; $i -lt $Keys.Count; $i++) {
$WsKeyName = $Keys[$i].name
$IsActive = $Keys[$i].isActiveCmk
if ($IsActive -eq $false) {
az synapse workspace key delete `
--name $WsKeyName `
--workspace-name ${{ parameters.target_ws }} `
--resource-group ${{ parameters.target_rg }} `
--yes --only-show-errors | Out-Null
}
}
#3
az synapse workspace key create `
--name $SourceWsKvKeyName `
--workspace-name ${{ parameters.target_ws }} `
--resource-group ${{ parameters.target_rg }} `
--key-identifier ${{ variables.kv_url_prefix }}$SourceWsKvKeyName `
--only-show-errors | Out-Null
#4
az synapse workspace update `
--name ${{ parameters.target_ws }} `
--resource-group ${{ parameters.target_rg }} `
--key-name $SourceWsKvKeyName `
--only-show-errors | Out-Null
Delete existing target SQL pool
- task: AzurePowerShell@5
name: manage_database
displayName: Manage existing database
inputs:
azureSubscription: ${{ variables.azure_connection }}
azurePowerShellVersion: LatestVersion
ScriptType: 'inlineScript'
inline: |
#1
$targetPoolExists = Test-AzSynapseSqlPool `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }}
if( $targetPoolExists ) {
if( "${{ parameters.keep_target_sql_pool }}" -eq $true ) {
#2
$pool = Get-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }} | Select-Object Status
$poolStatus = $pool.Status
if ("$poolStatus" -eq "Paused") {
Resume-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }} | Out-Null
}
#3
$restoreDatetime = Get-Date -Format "dd_MM_yyyy_HH.mm"
$backedUpSqlPool = '${{ variables.target_sql_pool }}' + "_" + $restoreDatetime
#4
New-AzSynapseSqlPoolRestorePoint `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }} `
-RestorePointLabel $backedUpSqlPool | Out-Null
#5
$pool = Get-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }}
$databaseId = $pool.Id -replace "Microsoft.Synapse", "Microsoft.Sql" `
-replace "workspaces", "servers" `
-replace "sqlPools", "databases"
#6
$restorePoint = $pool | Get-AzSynapseSqlPoolRestorePoint |
Where-Object {$PSItem.RestorePointLabel -eq $backedUpSqlPool}
Restore-AzSynapseSqlPool `
-FromRestorePoint `
-RestorePoint $restore_point.RestorePointCreationDate `
-TargetSqlPoolName $az_retained_target_sql_pool `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-ResourceId $databaseId `
-PerformanceLevel ${{ parameters.database_scale }} | Out-Null
#7
Suspend-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-Name $backedUpSqlPool | Out-Null
}
#8
Remove-AzSynapseSqlPool `
-WorkspaceName ${{ parameters.target_ws }} `
-Name ${{ parameters.target_sql_pool }} -Force
}
Clone database
- task: AzurePowerShell@5
name: clone_database
displayName: Clone database
inputs:
azureSubscription: ${{ variables.azure_connection }}
azurePowerShellVersion: 'LatestVersion'
ScriptType: 'inlineScript'
inline: |
#1
$pool = Get-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.source_rg }} `
-WorkspaceName ${{ parameters.source_ws }} `
-Name ${{ parameters.source_sql_pool }} | Select-Object Status
$poolStatus = $pool.Status
#2
if ("$poolStatus" -eq "Paused") {
Resume-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.source_rg }} `
-WorkspaceName ${{ parameters.source_ws }} `
-Name ${{ parameters.source_sql_pool }} | Out-Null
}
#3
New-AzSynapseSqlPoolRestorePoint `
-ResourceGroupName ${{ parameters.source_rg }} `
-WorkspaceName ${{ parameters.source_ws }} `
-Name ${{ parameters.source_sql_pool }} `
-RestorePointLabel ${{ parameters.source_sql_pool }} | Out-Null
#4
$pool = Get-AzSynapseSqlPool `
-ResourceGroupName ${{ parameters.source_rg }} `
-WorkspaceName ${{ parameters.source_ws }} `
-Name ${{ parameters.source_sql_pool }}
$ws = Get-AzSynapseWorkspace `
-name ${{ parameters.source_ws }} `
-ResourceGroupName ${{ parameters.source_rg }}
$databaseId = $pool.Id -replace "Microsoft.Synapse", "Microsoft.Sql" `
-replace "workspaces", "servers" `
-replace "sqlPools", "databases" `
-replace "${{ parameters.source_rg }}", $ws.ManagedResourceGroupName
#5
$restorePoint = $Pool | Get-AzSynapseSqlPoolRestorePoint | Select-Object -Last 1
Restore-AzSynapseSqlPool `
-FromRestorePoint `
-RestorePoint
#6
$restorePoint.RestorePointCreationDate `
-TargetSqlPoolName ${{ parameters.target_sql_pool }} `
-ResourceGroupName ${{ parameters.target_rg }} `
-WorkspaceName ${{ parameters.target_ws }} `
-ResourceId $databaseId `
-PerformanceLevel ${{ parameters.database_scale }} | Out-Null
Change encryption key
- task: AzureCLI@2
name: change_key2
displayName: Change encryption key
inputs:
azureSubscription: ${{ variables.azure_connection }}
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
#1
if ( "${{ parameters.target_workspace }}" -eq "ws-prod") {
$TargetWsKvKeyName = "key-synapse-ws-prod"
}
else {
$TargetWsKvKeyName = "key-synapse-ws-test"
}
#2
$Keys = az synapse workspace key list `
--workspace-name ${{ variables.target_workspace_full_name }} `
--resource-group ${{ variables.target_resource_group }} `
--only-show-errors | ConvertFrom-Json
for ($i=0; $i -lt $Keys.Count; $i++) {
$WsKeyName = $Keys[$i].name
$IsActive = $Keys[$i].isActiveCmk
if ($IsActive -eq $false) {
az synapse workspace key delete `
--name $WsKeyName `
--workspace-name ${{ variables.target_workspace_full_name }} `
--resource-group ${{ variables.target_resource_group }} `
--yes --only-show-errors | Out-Null
}
}
#3
az synapse workspace key create `
--name $TargetWsKvKeyName `
--workspace-name ${{ variables.target_workspace_full_name }} `
--resource-group ${{ variables.target_resource_group }} `
--key-identifier ${{ variables.kv_url_prefix }}$TargetWsKvKeyName `
--only-show-errors | Out-Null
#4
az synapse workspace update `
--name ${{ variables.target_workspace_full_name }} `
--resource-group ${{ variables.target_resource_group }} `
--key-name $TargetWsKvKeyName `
--only-show-errors | Out-Null
Create resource lock if one was in place
- task: AzureCLI@2
name: reinstate_lock
displayName: Reinstate workspace lock
inputs:
azureSubscription: ${{ variables.azure_connection }}
ScriptType: ps
ScriptLocation: inlineScript
inlineScript: |
#1
if ( $$(resourceLockExists) ) {
az lock create `
--lock-type CanNotDelete `
--name lock-${{ variables.target_rg }} `
--notes "Managed By Azure DevOps Pipelines" `
--resource-group ${{ parameters.target_rg }}
}