Skip to content

Commit 4f1cafb

Browse files
authored
Merge pull request #1394 from anosov1960/PAYG-transition
Added a resource name parameter and increased KQL limit
2 parents fc2101d + d2b37a3 commit 4f1cafb

3 files changed

Lines changed: 411 additions & 165 deletions

File tree

samples/manage/azure-arc-enabled-sql-server/modify-license-type/modify-arc-sql-license-type.ps1

Lines changed: 109 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -88,42 +88,77 @@ param (
8888
[switch] $ReportOnly,
8989

9090
[Parameter (Mandatory= $false)]
91-
[switch] $UseManagedIdentity
92-
91+
[switch] $UseManagedIdentity,
92+
[Parameter (Mandatory= $false)]
93+
[int] $batchSize = 500
9394
)
9495

96+
$scriptStartTime = Get-Date
97+
Write-Output "Script execution started at: $($scriptStartTime.ToString('yyyy-MM-dd HH:mm:ss'))"
98+
99+
95100
function Connect-Azure {
96101
[CmdletBinding()]
97102
param(
98-
[Parameter (Mandatory= $true)]
99-
[string] $TenantId,
103+
[Parameter(Mandatory=$false)]
104+
[string] $TenantId = $null,
100105

101-
[Parameter (Mandatory= $false)]
102-
[switch]$UseManagedIdentity
106+
[Parameter(Mandatory=$false)]
107+
[switch] $UseManagedIdentity
103108
)
104109

105-
# 1) Detect environment
106-
$envType = "Local"
107-
if ($env:AZUREPS_HOST_ENVIRONMENT -and $env:AZUREPS_HOST_ENVIRONMENT -like 'cloud-shell*') {
108-
$envType = "CloudShell"
110+
# 1) Detect host environment
111+
$envType = 'Local'
112+
if ($env:AZUREPS_HOST_ENVIRONMENT -like 'cloud-shell*') {
113+
$envType = 'CloudShell'
109114
}
110-
elseif (($env:AZUREPS_HOST_ENVIRONMENT -and $env:AZUREPS_HOST_ENVIRONMENT -like 'AzureAutomation*') -or $PSPrivateMetadata.JobId) {
111-
$envType = "AzureAutomation"
112-
$UseManagedIdentity=$true
115+
elseif (($env:AZUREPS_HOST_ENVIRONMENT -like 'AzureAutomation*') -or $PSPrivateMetadata.JobId) {
116+
$envType = 'AzureAutomation'
117+
$UseManagedIdentity = $true
113118
}
114-
Write-Verbose "Environment detected: $envType"
119+
Write-Output "Environment detected: $envType"
115120

116121
# 2) Ensure Az.PowerShell context
117-
Write-Output "Not connected to Azure PowerShell. Running Connect-AzAccount..."
118-
if ($UseManagedIdentity -or $envType -eq 'AzureAutomation') {
119-
$ctx = Connect-AzAccount -Tenant $TenantId -Identity -ErrorAction Stop | Out-Null
122+
$currentCtx = Get-AzContext -ErrorAction SilentlyContinue
123+
if ($currentCtx -and $currentCtx.Account) {
124+
if ($TenantId) {
125+
if ($currentCtx.Tenant.Id -eq $TenantId) {
126+
Write-Output "Already in Az tenant $TenantId"
127+
}
128+
else {
129+
Write-Output "Switching Az context to tenant $TenantId without re-authentication"
130+
$newContext = Set-AzContext -Tenant $TenantId -ErrorAction SilentlyContinue
131+
if($null -eq $newContext -or $newContext.TenantId -ne $TenantId)
132+
{
133+
Connect-AzAccount -Tenant $TenantId | Out-Null
134+
}
135+
}
136+
}
137+
else {
138+
Write-Output "Using existing Az context: Tenant $($currentCtx.Tenant.Id)"
139+
}
120140
}
121141
else {
122-
$ctx = Connect-AzAccount -Tenant $TenantId -ErrorAction Stop | Out-Null
142+
Write-Output "Not connected to Az PowerShell—authenticating..."
143+
if ($UseManagedIdentity) {
144+
if ($TenantId) {
145+
Connect-AzAccount -Identity -Tenant $TenantId | Out-Null
146+
}
147+
else {
148+
Connect-AzAccount -Identity -ErrorAction Stop | Out-Null
149+
}
150+
}
151+
else {
152+
if ($TenantId) {
153+
Connect-AzAccount -Tenant $TenantId | Out-Null
154+
}
155+
else {
156+
Connect-AzAccount | Out-Null
157+
}
158+
}
159+
$ctx = Get-AzContext
160+
Write-Output "Connected to Az PowerShell as: $($ctx.Account) in tenant $($ctx.Tenant.Id)"
123161
}
124-
Write-Output "Connected to Azure PowerShell as: $($ctx.Account)"
125-
126-
127162
}
128163

129164

@@ -138,44 +173,33 @@ if($null -ne $ExclusionTags){
138173
}
139174
}
140175
}
176+
# Ensure connection with both PowerShell and CLI.
177+
if($UseManagedIdentity -or $envType -eq 'AzureAutomation') {
178+
if ($TenantId) {
179+
Connect-Azure -TenantId $TenantId -UseManagedIdentity $UseManagedIdentity
180+
} else {
181+
Connect-Azure -UseManagedIdentity $UseManagedIdentity
182+
}
183+
} else {
184+
if ($TenantId) {
185+
Connect-Azure -TenantId $TenantId
186+
} else {
187+
Connect-Azure
188+
}
189+
}
190+
191+
$context = Get-AzContext -ErrorAction SilentlyContinue
192+
Write-Output "Connected to Azure as: $($context.Account)"
141193

142194
if (-not $TenantId) {
143-
$TenantId = (Get-AzContext).Tenant.Id
195+
$TenantId = $context.Tenant.Id
144196
Write-Output "No TenantId provided. Using current context TenantId: $TenantId"
145197
} else {
146198
Write-Output "Using provided TenantId: $TenantId"
147199
}
148-
# Ensure connection with both PowerShell and CLI.
149-
if ($UseManagedIdentity) {
150-
Connect-Azure ($TenantId, $UseManagedIdentity)
151-
}else{
152-
Connect-Azure ($TenantId)
153-
}
154-
155-
# Ensure the required modules are imported
156200

157201

158-
# Ensure NuGet provider is available
159-
if (-not (Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue)) {
160-
Install-PackageProvider -Name NuGet -Force
161-
}
162-
163-
# Check if Az module is installed
164-
$installedModule = Get-InstalledModule -Name Az -ErrorAction SilentlyContinue
165-
166-
if (-not $installedModule) {
167-
Write-Host "Az module not found. Installing latest version..."
168-
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
169-
} else {
170-
# Get the latest version available in the PSGallery
171-
$latestVersion = (Find-Module -Name Az -Repository PSGallery).Version
172-
if ($installedModule.Version -lt $latestVersion) {
173-
Write-Host "Az module is outdated. Updating to latest version..."
174-
Update-Module -Name Az -Force
175-
} else {
176-
Write-Host "Az module is already up to date. No action needed."
177-
}
178-
}
202+
# Ensure the required modules are imported
179203

180204
try{
181205
Import-Module Az.Accounts
@@ -200,10 +224,10 @@ $modifiedResources = @()
200224
if ($SubId -like "*.csv") {
201225
$subscriptions = Import-Csv $SubId
202226
}elseif($SubId -ne "") {
203-
$subscriptions = Get-AzSubscription -SubscriptionId $SubId | Sort-Object TenantId
204-
227+
Write-Output "Passed Subscription $($SubId)"
228+
$subscriptions = Get-AzSubscription -SubscriptionId $SubId
205229
}else {
206-
$subscriptions = Get-AzSubscription | Where-Object { $_.TenantId -eq $tenantId }
230+
$subscriptions = Get-AzSubscription | Where-Object { $_.TenantId -eq $tenantId }
207231
}
208232

209233
# Handle MachineName input (single or CSV)
@@ -258,7 +282,7 @@ foreach ($sub in $subscriptions) {
258282

259283
$query += "
260284
| extend machineId = tolower(tostring(id))
261-
| project machineId, machineName = name
285+
| project machineId, machineName = tolower(name)
262286
| join kind= inner (
263287
resources
264288
| where subscriptionId =~ '$($sub.Id)'
@@ -269,27 +293,38 @@ foreach ($sub in $subscriptions) {
269293
| extend extensionName = name
270294
| extend extensionPublisher = properties.publisher
271295
| extend extensionType = properties.type
272-
| parse id with '/subscriptions/' subscriptionId '/resourceGroups/' resourceGroup '/providers/Microsoft.HybridCompute/machines/' machineName '/extensions/' extensionName
273-
) on `$left.machineName == `$right.machineName
296+
| parse id with '/subscriptions/' subscriptionId '/resourceGroups/' resourceGroup '/providers/Microsoft.HybridCompute/machines/' machineNameRaw '/extensions/' extensionName
297+
| extend machineName = tolower(machineNameRaw)
298+
) on `$left.machineName == `$right.machineName
274299
| project machineName, extensionName, resourceGroup, location, subscriptionId, extensionPublisher, extensionType
275-
"
300+
| order by machineName asc"
301+
302+
$skipToken = $null
276303

277-
#Write-Output $query
304+
Write-Output $query
278305

279-
$resources = Search-AzGraph -Query "$($query)"
280306
Write-Output "Found $($resources.Count) resource(s) to update"
281-
$count = $resources.Count
307+
$allResults = [System.Collections.Generic.List[PSObject]]::new()
308+
do{
309+
$resources = Search-AzGraph -Query "$($query)" -First $batchSize -SkipToken $skipToken
310+
$allResults.AddRange($resources)
311+
$skipToken = $resources.SkipToken
312+
}while($skipToken)
313+
314+
315+
$count = $allResults.Count
316+
282317

283318
while($count -gt 0) {
284319
$count-=1
285320
$setID = @{
286-
MachineName = $resources[$count].MachineName
287-
Name = $resources[$count].extensionName
288-
ResourceGroup = $resources[$count].resourceGroup
289-
Location = $resources[$count].location
290-
SubscriptionId = $resources[$count].subscriptionId
291-
Publisher = $resources[$count].extensionPublisher
292-
ExtensionType = $resources[$count].extensionType
321+
MachineName = $allResults[$count].MachineName
322+
Name = $allResults[$count].extensionName
323+
ResourceGroup = $allResults[$count].resourceGroup
324+
Location = $allResults[$count].location
325+
SubscriptionId = $allResults[$count].subscriptionId
326+
Publisher = $allResults[$count].extensionPublisher
327+
ExtensionType = $allResults[$count].extensionType
293328
}
294329

295330
write-Output " MachineName - $($setID.MachineName)"
@@ -407,6 +442,7 @@ foreach ($sub in $subscriptions) {
407442
Write-Output "ReportOnly mode enabled. Skipping modification for: $($setID.MachineName)"
408443
}
409444
}
445+
410446
}
411447
}
412448
}
@@ -421,3 +457,8 @@ if ($modifiedResources.Count -gt 0) {
421457
}
422458

423459
write-Output "Arc SQL Update Script completed"
460+
461+
$scriptEndTime = Get-Date
462+
$executionDuration = $scriptEndTime - $scriptStartTime
463+
Write-Output "Script execution ended at: $($scriptEndTime.ToString('yyyy-MM-dd HH:mm:ss'))"
464+
Write-Output "Total execution time: $($executionDuration.ToString('hh\:mm\:ss'))"

samples/manage/azure-hybrid-benefit/modify-license-type/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ The scripts is seamlessly integrated with Azure Authentication. It uses managed
5757

5858
| **Parameter**                                         | **Value**                                                                       | **Description** |
5959
|:--|:--|:--|
60-
|-SubId|`subscription_id` *or* a file_name|Optional: Subscription id or a .csv file with the list of subscriptions<sup>1</sup>. If not specified all subscriptions will be scanned|
61-
|-ResourceGroup |`resource_group_name`|Optional: Limits the scope to a specific resource group|
62-
|-LicenseType | `LicenseIncluded` (default) or `BasePrice` | Optional: Sets the license type to the specified value |
60+
|`-SubId`|`subscription_id` *or* a file_name|Optional: Subscription id or a .csv file with the list of subscriptions<sup>1</sup>. If not specified all subscriptions will be scanned|
61+
|`-ResourceGroup` |`resource_group_name`|Optional: Limits the scope to a specific resource group|
62+
|`-ResourceName` |`resource_name`|Optional: Limits the scope to resouyrces associated with this name. For SQL Server - updates all databases under the specified server. For SQL Managed Instance - updates the specified instance. For SQL VM - updates the specified VM |
63+
|`-LicenseType` | `LicenseIncluded` (default) or `BasePrice` | Optional: Sets the license type to the specified value |
6364
|`-ExclusionTags`| `{"name":"value","name":"value"}` |*Optional*. If specified, excludes the resources that have this tag assigned.|
6465
|`-TenantId`| `tenant_id` |*Optional*. If specified, uses this tenant id to log in. Otherwise, the current context is used.|
6566
|`-ReportOnly`| |*Optional*. If true, generates a csv file with the list of resources that are to be modified, but doesn't make the actual change.|

0 commit comments

Comments
 (0)