mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
Moved folders and copies tested scrips
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Manage Transition to Pay-as-you-go subscription
|
||||
|
||||
## Overview
|
||||
|
||||
**schedule-pay-transition.ps1** is a PowerShell script that either:
|
||||
|
||||
- **Runs once**: Downloads and invokes environment‑specific “pay transition” scripts for Azure, Arc, or both.
|
||||
- **Schedules itself**: Registers a Windows Scheduled Task to run daily at 2 AM, invoking itself in “Single” mode.
|
||||
|
||||
It supports optional cleanup of downloaded files and passing extra parameters (target resource group, subscription, etc.) to the downstream scripts.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **PowerShell 5+.**
|
||||
- **User running needs to be Azure Subscription owner or contributor to be able to run the script.**
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
| Name | Mandatory | Type | Acceptable Values | Description |
|
||||
|------------------------|-----------|---------|--------------------------|----------------------------------------------------------------------------------------------|
|
||||
| `-Target` | Yes | String | `Arc`, `Azure`, `Both` | Which environment(s) to process. |
|
||||
| `-RunMode` | Yes | String | `Single`, `Scheduled` | `Single` runs immediately; `Scheduled` registers an NT Task to run daily at 2 AM. |
|
||||
| `-cleanDownloads` | No | Boolean | | If `$true`, deletes the download folder after a single run. |
|
||||
| `-UsePcoreLicense` | No | String | `Yes`, `No` | Passed to Arc script to control PCore licensing behavior (defaults to `No`). |
|
||||
| `-targetResourceGroup` | No | String | | Subscription resource group to target in downstream scripts. |
|
||||
| `-targetSubscription` | No | String | | Subscription ID to target in downstream scripts. |
|
||||
| `-AutomationAccountName` | No | String | | Automation Account name for the “General” runbook import operation. |
|
||||
| `-Location` | No | String | | Azure region for the “General” runbook import operation. |
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Script URL Configuration**
|
||||
- **General**: points to `set-azurerunbook.ps1` (imports & publishes the helper runbook).
|
||||
- **Azure**: points to `modify-azure-sql-license-type.ps1`.
|
||||
- **Arc**: points to `modify-license-type.ps1` for Arc‑enabled SQL.
|
||||
|
||||
2. **Download Folder**
|
||||
- Creates `.\PayTransitionDownloads\` (relative) if missing.
|
||||
- Downloads chosen script(s) into it.
|
||||
|
||||
3. **Invoke-RemoteScript**
|
||||
- Downloads a script via `Invoke-RestMethod`.
|
||||
- Invokes it with splatted parameter hashtable derived from `$scriptUrls[...] .Args`.
|
||||
|
||||
4. **Modes**
|
||||
- **Single**: Invokes the selected scripts immediately and (optionally) cleans up.
|
||||
- **Scheduled**: Registers or updates a Scheduled Task (run as SYSTEM) to call itself every day at 2 AM with `-RunMode Single`.
|
||||
|
||||
5. **Cleanup**
|
||||
- If `-cleanDownloads $true`, removes the download folder after a single run.
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Run Immediately
|
||||
#### Both Environments
|
||||
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 -Target Both -RunMode Single -cleanDownloads $true `
|
||||
-UsePcoreLicense Yes `
|
||||
-targetSubscription "00000000-0000-0000-0000-000000000000" `
|
||||
-targetResourceGroup "MyRG" `
|
||||
-AutomationAccountName "MyAutoAcct" `
|
||||
-Location "EastUS"
|
||||
````
|
||||
|
||||
### Arc Only, Single Run, With Cleanup
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 `
|
||||
-Target Arc `
|
||||
-RunMode Single `
|
||||
-cleanDownloads $true `
|
||||
-UsePcoreLicense Yes `
|
||||
-targetSubscription "11111111-1111-1111-1111-111111111111" `
|
||||
-targetResourceGroup "ArcRG"
|
||||
````
|
||||
|
||||
### Both Azure & Arc, Single Run, Full Parameters
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 `
|
||||
-Target Both `
|
||||
-RunMode Single `
|
||||
-cleanDownloads $true `
|
||||
-UsePcoreLicense No `
|
||||
-targetSubscription "22222222-2222-2222-2222-222222222222" `
|
||||
-targetResourceGroup "HybridRG" `
|
||||
-AutomationAccountName "MyAutomationAccount" `
|
||||
-Location "EastUS"
|
||||
```
|
||||
### Scheduled-Run Scenarios
|
||||
|
||||
#### Schedule Daily for Azure Only
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 `
|
||||
-Target Azure `
|
||||
-RunMode Scheduled
|
||||
```
|
||||
#### Schedule Daily for Arc Only
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 `
|
||||
-Target Arc `
|
||||
-RunMode Scheduled
|
||||
```
|
||||
|
||||
#### Schedule Daily for Both Environments
|
||||
```powershell
|
||||
.\schedule-pay-transition.ps1 `
|
||||
-Target Both `
|
||||
-RunMode Scheduled
|
||||
```
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Schedules or executes pay-transition operations for Azure and/or Arc.
|
||||
|
||||
.DESCRIPTION
|
||||
Depending on parameters, this script either:
|
||||
- Downloads and runs the Azure and/or Arc pay-transition scripts once, or
|
||||
- Registers a Windows Scheduled Task to invoke itself daily at 2 AM.
|
||||
|
||||
.PARAMETER Target
|
||||
Which environment(s) to process:
|
||||
- Arc
|
||||
- Azure
|
||||
- Both
|
||||
|
||||
.PARAMETER RunMode
|
||||
Whether to run immediately or schedule recurring runs:
|
||||
- Single : Download & invoke once, then exit.
|
||||
- Scheduled : Create or update the scheduled task calling this script daily.
|
||||
|
||||
.EXAMPLE
|
||||
# Run immediately for both Azure and Arc
|
||||
.\manage-payg-transition.ps1 -Target Both -RunMode Single
|
||||
|
||||
.EXAMPLE
|
||||
# Schedule daily runs for Azure only
|
||||
.\manage-payg-transition.ps1 -Target Azure -RunMode Scheduled
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory, Position=0)]
|
||||
[ValidateSet("Arc","Azure","Both")]
|
||||
[string]$Target,
|
||||
|
||||
[Parameter(Mandatory, Position=1)]
|
||||
[ValidateSet("Single","Scheduled")]
|
||||
[string]$RunMode,
|
||||
|
||||
[Parameter(Mandatory = $false, Position=2)]
|
||||
[bool]$cleanDownloads=$false,
|
||||
|
||||
[Parameter (Mandatory= $false)]
|
||||
[ValidateSet("Yes","No", IgnoreCase=$false)]
|
||||
[string] $UsePcoreLicense="No",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$targetResourceGroup=$null,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$targetSubscription=$null,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$AutomationAccResourceGroupName,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$AutomationAccountName="aaccAzureArcSQLLicenseType",
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Location=$null
|
||||
)
|
||||
$git = "sql-server-samples"
|
||||
$environment = "microsoft"
|
||||
if($null -ne $env:MYAPP_ENV) {
|
||||
$git = "arc-sql-dashboard"
|
||||
$environment = $env:MYAPP_ENV
|
||||
}
|
||||
# === Configuration ===
|
||||
$scriptUrls = @{
|
||||
General = @{
|
||||
URL = "https://raw.githubusercontent.com/$($environment)/$($git)/refs/heads/master/samples/manage/azure-hybrid-benefit/modify-license-type/set-azurerunbook.ps1"
|
||||
Args = @{
|
||||
ResourceGroupName= "'$($AutomationAccResourceGroupName)'"
|
||||
AutomationAccountName= $AutomationAccountName
|
||||
Location= $Location
|
||||
targetResourceGroup= $targetResourceGroup
|
||||
targetSubscription= $targetSubscription}
|
||||
}
|
||||
Azure = @{
|
||||
URL = "https://raw.githubusercontent.com/$($environment)/$($git)/refs/heads/master/samples/manage/azure-hybrid-benefit/modify-license-type/modify-azure-sql-license-type.ps1"
|
||||
Args = @{
|
||||
Force_Start_On_Resources = $true
|
||||
SubId = [string]$targetSubscription
|
||||
ResourceGroup = [string]$targetResourceGroup
|
||||
}
|
||||
}
|
||||
Arc = @{
|
||||
URL = "https://raw.githubusercontent.com/$($environment)/$($git)/refs/heads/master/samples/manage/azure-hybrid-benefit/modify-license-type/modify-arc-sql-license-type.ps1"
|
||||
Args =@{
|
||||
LicenseType= "PAYG"
|
||||
Force = $true
|
||||
UsePcoreLicense=[string]$UsePcoreLicense
|
||||
SubId = [string]$targetSubscription
|
||||
ResourceGroup = [string]$targetResourceGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
# Define a dedicated download folder
|
||||
$downloadFolder = './manage-payg-transition/'
|
||||
# Ensure destination folder exists
|
||||
if (-not (Test-Path $downloadFolder)) {
|
||||
Write-Host "Creating folder: $downloadFolder"
|
||||
New-Item -Path $downloadFolder -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
# Helper to download a script and invoke it
|
||||
function Invoke-RemoteScript {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Url,
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet("Arc","Azure","Both")]
|
||||
[string]$Target,
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet("Single","Scheduled")]
|
||||
[string]$RunMode
|
||||
)
|
||||
$fileName = Split-Path $Url -Leaf
|
||||
$dest = Join-Path $downloadFolder $fileName
|
||||
|
||||
|
||||
Write-Host "Downloading $Url to $dest..."
|
||||
Invoke-RestMethod -Uri $Url -OutFile $dest
|
||||
|
||||
$scriptname = $dest
|
||||
$wrapper = @()
|
||||
$wrapper += @"
|
||||
`$ResourceGroupName= '$($AutomationAccResourceGroupName)'
|
||||
`$AutomationAccountName= '$AutomationAccountName'
|
||||
`$Location= '$Location'
|
||||
$(if ($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") { "`$targetResourceGroup= '$targetResourceGroup'" })
|
||||
$(if ($null -ne $targetSubscription -and $targetSubscription -ne "") { "`$targetSubscription= '$targetSubscription'" })
|
||||
"@
|
||||
if($Target -eq "Both" -or $Target -eq "Arc") {
|
||||
|
||||
$supportfileName = Split-Path $scriptUrls.Arc.URL -Leaf
|
||||
$supportdest = Join-Path $downloadFolder $supportfileName
|
||||
Write-Host "Downloading $($scriptUrls.Arc.URL) to $supportdest..."
|
||||
Invoke-RestMethod -Uri $scriptUrls.Arc.URL -OutFile $supportdest
|
||||
|
||||
$supportfileName = Split-Path $scriptUrls.Azure.URL -Leaf
|
||||
$supportdest = Join-Path $downloadFolder $supportfileName
|
||||
Write-Host "Downloading $scriptUrls.Azure.URL to $supportdest..."
|
||||
Invoke-RestMethod -Uri $scriptUrls.Azure.URL -OutFile $supportdest
|
||||
|
||||
$nextline = if(($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") -or ($null -ne $targetSubscription -and $targetSubscription -ne "")) {"``"}
|
||||
$nextline2 = if(($null -ne $targetSubscription -and $targetSubscription -ne "")){"``"}
|
||||
$wrapper += @"
|
||||
`$RunbookArg =@{
|
||||
LicenseType= 'PAYG'
|
||||
Force = `$true
|
||||
$(if ($null -ne $UsePcoreLicense) { "UsePcoreLicense='$UsePcoreLicense'" } else { "" })
|
||||
$(if ($null -ne $targetSubscription -and $targetSubscription -ne "") { "SubId='$targetSubscription'" })
|
||||
$(if ($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") { "ResourceGroup='$targetResourceGroup'" })
|
||||
}
|
||||
|
||||
$scriptname -ResourceGroupName `$ResourceGroupName -AutomationAccountName `$AutomationAccountName -Location `$Location -RunbookName 'ModifyLicenseTypeArc' ``
|
||||
-RunbookPath '$(Split-Path $scriptUrls.Arc.URL -Leaf)' ``
|
||||
-RunbookArg `$RunbookArg $($nextline)
|
||||
$(if ($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") { "-targetResourceGroup `$targetResourceGroup $nextline2" })
|
||||
$(if ($null -ne $targetSubscription -and $targetSubscription -ne "") { "-targetSubscription `$targetSubscription" })
|
||||
"@
|
||||
|
||||
}
|
||||
|
||||
if($Target -eq "Both" -or $Target -eq "Azure") {
|
||||
|
||||
$supportfileName = Split-Path $scriptUrls.Azure.URL -Leaf
|
||||
$supportdest = Join-Path $downloadFolder $supportfileName
|
||||
Write-Host "Downloading $($scriptUrls.Azure.URL) to $supportdest..."
|
||||
Invoke-RestMethod -Uri $scriptUrls.Azure.URL -OutFile $supportdest
|
||||
|
||||
$nextline = if(($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") -or ($null -ne $targetSubscription -and $targetSubscription -ne "")) {"``"}
|
||||
$nextline2 = if(($null -ne $targetSubscription -and $targetSubscription -ne "")){"``"}
|
||||
$wrapper += @"
|
||||
`$RunbookArg =@{
|
||||
Force_Start_On_Resources = `$true
|
||||
$(if ($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") { "ResourceGroup= '$targetResourceGroup'" })
|
||||
$(if ($null -ne $targetSubscription -and $targetSubscription -ne "") { "SubId= '$targetSubscription'" })
|
||||
|
||||
}
|
||||
|
||||
$scriptname -ResourceGroupName `$ResourceGroupName -AutomationAccountName `$AutomationAccountName -Location `$Location -RunbookName 'ModifyLicenseTypeAzure' ``
|
||||
-RunbookPath '$(Split-Path $scriptUrls.Azure.URL -Leaf)'``
|
||||
-RunbookArg `$RunbookArg $($nextline)
|
||||
$(if ($null -ne $targetResourceGroup -and $targetResourceGroup -ne "") { "-targetResourceGroup `$targetResourceGroup $nextline2" })
|
||||
$(if ($null -ne $targetSubscription -and $targetSubscription -ne "") { "-targetSubscription `$targetSubscription" })
|
||||
|
||||
"@
|
||||
|
||||
}
|
||||
$wrapper | Out-File -FilePath './runnow.ps1' -Encoding UTF8
|
||||
.\runnow.ps1
|
||||
}
|
||||
|
||||
# === Single run: download & invoke the appropriate script(s) ===
|
||||
if($RunMode -eq "Single") {
|
||||
$wrapper = @()
|
||||
if ($Target -eq "Both" -or $Target -eq "Arc") {
|
||||
$fileName = Split-Path $scriptUrls.Arc.URL -Leaf
|
||||
$dest = Join-Path $downloadFolder $fileName
|
||||
|
||||
|
||||
$wrapper +="$dest ``"
|
||||
foreach ($arg in $scriptUrls.Arc.Args.Keys) {
|
||||
if ("" -ne $scriptUrls.Arc.Args[$arg]) {
|
||||
$wrapper+="-$($arg)='$($scriptUrls.Arc.Args[$arg])'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($Target -eq "Both" -or $Target -eq "Azure") {
|
||||
$fileName = Split-Path $scriptUrls.Azure.URL -Leaf
|
||||
$dest = Join-Path $downloadFolder $fileName
|
||||
|
||||
|
||||
$wrapper +="$dest ``"
|
||||
foreach ($arg in $scriptUrls.Azure.Args.Keys) {
|
||||
if ("" -ne $scriptUrls.Azure.Args[$arg]) {
|
||||
$wrapper+="-$($arg)='$($scriptUrls.Azure.Args[$arg])'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wrapper | Out-File -FilePath './runnow.ps1' -Encoding UTF8
|
||||
.\runnow.ps1
|
||||
|
||||
Write-Host "Single run completed."
|
||||
}else{
|
||||
Write-Host "Run 'Scheduled'."
|
||||
Invoke-RemoteScript -Url $scriptUrls.General.URL -Target $Target -RunMode $RunMode
|
||||
}
|
||||
# === Cleanup downloaded files & folder ===
|
||||
if($cleanDownloads -eq $true) {
|
||||
if (Test-Path $downloadFolder) {
|
||||
Write-Host "Cleaning up downloaded scripts in $downloadFolder..."
|
||||
try {
|
||||
Remove-Item -Path $downloadFolder -Recurse -Force
|
||||
Write-Host "Cleanup successful: removed $downloadFolder"
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Cleanup failed: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates or uses an Azure Automation account and imports a runbook.
|
||||
|
||||
.DESCRIPTION
|
||||
This script:
|
||||
- Connects to Azure (PowerShell + CLI).
|
||||
- Creates the resource group if it doesn't exist.
|
||||
- Creates the Automation account (with system identity) if it doesn't exist.
|
||||
- Assigns a set of built‑in roles to that managed identity.
|
||||
- Imports or updates the specified runbook, publishes it.
|
||||
- Creates a daily schedule (if missing) and links it to the runbook.
|
||||
- Starts a one‑off job of the runbook.
|
||||
|
||||
.PARAMETER ResourceGroupName
|
||||
The resource group in which to create/use the Automation account.
|
||||
|
||||
.PARAMETER AutomationAccountName
|
||||
The Automation account name.
|
||||
|
||||
.PARAMETER Location
|
||||
Azure region for the RG and account (e.g. "EastUS").
|
||||
|
||||
.PARAMETER RunbookName
|
||||
The name under which to import/publish the runbook.
|
||||
|
||||
.PARAMETER RunbookPath
|
||||
Full path to the local .ps1 runbook file.
|
||||
|
||||
.PARAMETER RunbookType
|
||||
Runbook type: "PowerShell", "PowerShell72", "PowerShellWorkflow", "Graph", "Python2", or "Python3".
|
||||
Default: "PowerShell72".
|
||||
|
||||
.PARAMETER targetResourceGroup
|
||||
(Optional) Resource group passed into the runbook as a parameter.
|
||||
|
||||
.PARAMETER targetSubscription
|
||||
(Optional) Subscription ID passed into the runbook as a parameter.
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$ResourceGroupName,
|
||||
[Parameter(Mandatory)][string]$AutomationAccountName,
|
||||
[Parameter(Mandatory)][string]$Location,
|
||||
[Parameter(Mandatory)][string]$RunbookName,
|
||||
[Parameter(Mandatory)][string]$RunbookPath,
|
||||
[Parameter()][Hashtable]$RunbookArg,
|
||||
[ValidateSet("PowerShell","PowerShell72","PowerShellWorkflow","Graph","Python2","Python3")]
|
||||
[string]$RunbookType = "PowerShell72",
|
||||
[string]$targetResourceGroup,
|
||||
[string]$targetSubscription
|
||||
)
|
||||
# Suppress unnecessary logging output
|
||||
$VerbosePreference = "SilentlyContinue"
|
||||
$DebugPreference = "SilentlyContinue"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
$InformationPreference = "SilentlyContinue"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$context = $null
|
||||
# Define role assignments to apply
|
||||
$roleAssignments = @(
|
||||
@{ RoleName = "SQL DB Contributor"; Description = "For Azure SQL Databases and Azure SQL Elastic Pools" },
|
||||
@{ RoleName = "SQL Managed Instance Contributor"; Description = "For Azure SQL Managed Instances and Azure SQL Instance Pools" },
|
||||
@{ RoleName = "Data Factory Contributor"; Description = "For Azure Data Factory SSIS Integration Runtimes" },
|
||||
@{ RoleName = "Virtual Machine Contributor"; Description = "For SQL Servers in Azure Virtual Machines" },
|
||||
@{RoleName = "SQL Server Contributor"; Description = "For Elastic-Pools in Azure Virtual Machines"},
|
||||
@{RoleName = "Azure Connected Machine Resource Administrator"; Description = "For SQL Servers in Arc Virtual Machines"},
|
||||
@{RoleName = "Reader"; Description = "For read resources in the subscription"}
|
||||
)
|
||||
function Connect-Azure {
|
||||
try {
|
||||
Write-Output "Testing if it is connected to Azure."
|
||||
# Attempt to retrieve the current Azure context
|
||||
$context = Get-AzContext -ErrorAction SilentlyContinue
|
||||
|
||||
if ($null -eq $context -or $null -eq $context.Account) {
|
||||
Write-Output "Not connected to Azure. Executing Connect-AzAccount..."
|
||||
if($UseManageIdentity){
|
||||
Connect-AzAccount -Identity -ErrorAction Stop | Out-Null
|
||||
} else {
|
||||
Connect-AzAccount -ErrorAction Stop | Out-Null
|
||||
}
|
||||
$context = Get-AzContext
|
||||
Write-Output "Connected to Azure as: $($context.Account)"
|
||||
}
|
||||
else {
|
||||
Write-Output "Already connected to Azure as: $($context.Account)"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "An error occurred while testing the Azure connection: $_"
|
||||
}
|
||||
# Ensure the user is logged in to Azure
|
||||
try {
|
||||
$account = az account show 2>$null | ConvertFrom-Json
|
||||
if ($account) {
|
||||
Write-Output "Logged in as: $($account.user.name)"
|
||||
}
|
||||
} catch {
|
||||
Write-Output "Not logged in. Run 'az login'."
|
||||
if($UseManageIdentity){
|
||||
az login --Identity | Out-Null
|
||||
} else {
|
||||
az login | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
function LoadAzModules {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$SubscriptionId,
|
||||
[Parameter(Mandatory)][string]$ResourceGroupName,
|
||||
[Parameter(Mandatory)][string]$AutomationAccountName
|
||||
)
|
||||
|
||||
|
||||
# List of modules to import from PSGallery
|
||||
$modules = @(
|
||||
'AzureAD',
|
||||
'Az.Accounts',
|
||||
'Az.ConnectedMachine',
|
||||
'Az.ResourceGraph'
|
||||
)
|
||||
try {
|
||||
$existing = Get-AzAutomationModule -ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName -Name $mod -ErrorAction SilentlyContinue
|
||||
if ($existing) {
|
||||
Write-Output "Removing existing Automation module '$mod'..." -ForegroundColor Magenta
|
||||
Remove-AzAutomationModule -ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName -Name $mod -Force
|
||||
Write-Output " → Removed '$mod'." -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Could not check/remove existing module '$mod': $_"
|
||||
}
|
||||
|
||||
foreach ($mod in $modules) {
|
||||
# Remove existing module from Automation account, if present
|
||||
try {
|
||||
$existing = Get-AzAutomationModule -ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName -Name $mod -ErrorAction SilentlyContinue
|
||||
if ($existing) {
|
||||
Write-Output "Removing existing Automation module '$mod'..." -ForegroundColor Magenta
|
||||
Remove-AzAutomationModule -ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName -Name $mod -Force
|
||||
Write-Output " → Removed '$mod'." -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Could not check/remove existing module '$mod': $_"
|
||||
}
|
||||
Write-Output "Resolving latest version for module '$mod' from PowerShell Gallery..." -ForegroundColor Yellow
|
||||
try {
|
||||
$info = Find-Module -Name $mod -Repository PSGallery -ErrorAction Stop
|
||||
$version = $info.Version.ToString()
|
||||
$contentUri = "https://www.powershellgallery.com/api/v2/package/$mod/$version"
|
||||
Write-Output "Importing '$mod' version $version into Automation account..." -ForegroundColor Cyan
|
||||
Import-AzAutomationModule `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-Name $mod `
|
||||
-ContentLinkUri $contentUri `
|
||||
-RuntimeVersion 5.1 `
|
||||
-ErrorAction Stop | Out-Null
|
||||
|
||||
Import-AzAutomationModule `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-Name $mod `
|
||||
-ContentLinkUri $contentUri `
|
||||
-RuntimeVersion 7.2 `
|
||||
-ErrorAction Stop | Out-Null
|
||||
|
||||
Write-Output " → Queued '$mod' v$version for import." -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to import module '$mod': $_"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "All specified modules have been queued for import. Check the Automation account in the portal for status." -ForegroundColor Cyan
|
||||
}
|
||||
# Connect to Azure.
|
||||
Write-Output "Connecting to Azure..."
|
||||
Connect-Azure
|
||||
$context = Get-AzContext -ErrorAction Stop
|
||||
if ($null -ne $targetSubscription -and $targetSubscription -ne $context.Subscription.Id -and $targetSubscription -ne "") {
|
||||
$context = Set-AzContext -Subscription $targetSubscription -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Check if the resource group exists; if not, create it.
|
||||
if (-not (Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue)) {
|
||||
Write-Output "Creating Resource Group '$ResourceGroupName' in region '$Location'..."
|
||||
New-AzResourceGroup -Name $ResourceGroupName -Location $Location | Out-Null
|
||||
}
|
||||
else {
|
||||
Write-Output "Resource Group '$ResourceGroupName' already exists."
|
||||
}
|
||||
|
||||
# Check if the Automation Account exists; if not, create it.
|
||||
$automationAccount = Get-AzAutomationAccount -ResourceGroupName $ResourceGroupName -Name $AutomationAccountName -ErrorAction SilentlyContinue
|
||||
if ($null -eq $automationAccount) {
|
||||
Write-Output "Automation Account '$AutomationAccountName' not found. Creating it..."
|
||||
$automationAccount = New-AzAutomationAccount -Name $AutomationAccountName -ResourceGroupName $ResourceGroupName -Location $Location -AssignSystemIdentity
|
||||
} else {
|
||||
Write-Output "Automation Account '$AutomationAccountName' already exists."
|
||||
}
|
||||
if (-not (Get-AzAutomationModule -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name 'Az.ResourceGraph')) {
|
||||
Import-AzAutomationModule `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-Name 'Az.ResourceGraph' `
|
||||
-ContentLinkUri "https://www.powershellgallery.com/packages/Az.ResourceGraph/1.2.0"
|
||||
-ErrorAction Stop
|
||||
}
|
||||
LoadAzModules -SubscriptionId $context.Subscription.Id -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName
|
||||
# Assign roles to the Automation Account's system-assigned managed identity.
|
||||
$principalId = $automationAccount.Identity.PrincipalId
|
||||
$Scope = "/subscriptions/$($context.Subscription.Id)"
|
||||
Write-Output $principalId
|
||||
if ($null -eq $principalId) {
|
||||
Write-Output "The Automation Account does not have a system-assigned managed identity enabled." -ForegroundColor Yellow
|
||||
exit
|
||||
} else {
|
||||
Write-Output "Automation Account Object ID (PrincipalId): $principalId" -ForegroundColor Green
|
||||
foreach ($assignment in $roleAssignments) {
|
||||
$roleName = $assignment.RoleName
|
||||
|
||||
try {
|
||||
if($null -eq (Get-AzRoleAssignment -ObjectId $principalId -RoleDefinitionName $roleName -Scope $Scope)) {
|
||||
Write-Output "Assigning role '$roleName' to Managed Identity '$AutomationAccountName' at scope '$Scope'..." -ForegroundColor Yellow
|
||||
New-AzRoleAssignment -ObjectId $principalId -RoleDefinitionName $roleName -Scope "/subscriptions/$($context.Subscription.Id)" -ErrorAction Stop | Out-Null
|
||||
Write-Output "Role '$roleName' assigned successfully." -ForegroundColor Green
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to assign role '$roleName': $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
$downloadFolder = './PayTransitionDownloads/'
|
||||
# Import the runbook into the Automation Account.
|
||||
if ((Get-AzAutomationRunbook -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name $RunbookName -ErrorAction SilentlyContinue)) {
|
||||
Write-Output "Removing old Runbook '$RunbookName' from Automation Account '$AutomationAccountName'..."
|
||||
Remove-AzAutomationRunbook -AutomationAccountName $AutomationAccountName -Name $RunbookName -ResourceGroupName $ResourceGroupName -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
}
|
||||
if (-not (Get-AzAutomationRunbook -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name $RunbookName -ErrorAction SilentlyContinue)) {
|
||||
Write-Output "Importing Runbook '$RunbookName' from file '$RunbookPath' into Automation Account '$AutomationAccountName'..."
|
||||
Import-AzAutomationRunbook -AutomationAccountName $AutomationAccountName `
|
||||
-Name $RunbookName `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-Path "$($downloadFolder)$($RunbookPath)" `
|
||||
-Type $RunbookType `
|
||||
-Force `
|
||||
-Published `
|
||||
-LogProgress $True | Out-Null
|
||||
}
|
||||
|
||||
|
||||
# Create a daily schedule for the runbook (if it doesn't exist).
|
||||
$ScheduleName = "$($RunbookName)_defaultschedule"
|
||||
if (-not (Get-AzAutomationSchedule -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name $ScheduleName -ErrorAction SilentlyContinue)) {
|
||||
Remove-AzAutomationSchedule -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name $ScheduleName -ErrorAction SilentlyContinue -Force | Out-Null
|
||||
}
|
||||
if (-not (Get-AzAutomationSchedule -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Name $ScheduleName -ErrorAction SilentlyContinue)) {
|
||||
Write-Output "Creating schedule '$ScheduleName'..."
|
||||
# Set the schedule to start 5 minutes from now and expire in one year, with daily frequency.
|
||||
New-AzAutomationSchedule `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-Name $ScheduleName `
|
||||
-StartTime (Get-Date).AddDays(1)`
|
||||
-WeekInterval 1 `
|
||||
-DaysOfWeek @([System.DayOfWeek]::Monday..[System.DayOfWeek]::Sunday) `
|
||||
-TimeZone 'UTC' `
|
||||
-Description 'Default schedule for runbook' | Out-Null
|
||||
}
|
||||
|
||||
|
||||
# Link the schedule to the runbook, including the sample parameters.
|
||||
Write-Output "Assigning schedule '$ScheduleName' to runbook '$RunbookName' with sample parameters..."
|
||||
Register-AzAutomationScheduledRunbook `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-RunbookName $RunbookName `
|
||||
-ScheduleName $ScheduleName `
|
||||
-Parameters $RunbookArg | Out-Null
|
||||
|
||||
Start-AzAutomationRunbook `
|
||||
-ResourceGroupName $ResourceGroupName `
|
||||
-AutomationAccountName $AutomationAccountName `
|
||||
-Name $RunbookName `
|
||||
-Parameters $RunbookArg `
|
||||
-ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
Write-Output "Runbook '$RunbookName' has been imported and published successfully."
|
||||
Reference in New Issue
Block a user