1+ #
2+ # This script provides a scaleable solution to uninstall Azure extension for SQL Server on a specific Arc-enabled server,
3+ # all Arc-enabled servers in a specific resource group, specific subscription, a list of subscriptions or the entire account.
4+ #
5+ # You can specfy a single subscription to scan, or provide subscriptions as a .CSV file with the list of IDs.
6+ # If not specified, all subscriptions your role has access to are scanned.
7+ #
8+ # The script accepts the following command line parameters:
9+ #
10+ # -SubId [subscription_id] | [csv_file_name] (Limit scope to specific subscriptions. Accepts a .csv file with the list of subscriptions.
11+ # If not specified all subscriptions will be scanned)
12+ # -ResourceGroup [resource_goup] (Limit scope to a specific resoure group)
13+ # -MachineName [machine_name] (Limit scope to a specific machine)
14+ # -All (Uninstall Azure extension on all Arc-enabled servers in all subscriptions you have cointributor access to).
15+ #
16+ #
17+
18+ param (
19+ [Parameter (Mandatory = $false )]
20+ [string ] $SubId ,
21+ [Parameter (Mandatory = $false )]
22+ [string ] $ResourceGroup ,
23+ [Parameter (Mandatory = $false )]
24+ [string ] $MachineName ,
25+ [Parameter (Mandatory = $false )]
26+ [boolean ] $All = $false
27+ )
28+
29+ function CheckModule ($m ) {
30+
31+ # This function ensures that the specified module is imported into the session
32+ # If module is already imported - do nothing
33+
34+ if (! (Get-Module | Where-Object {$_.Name -eq $m })) {
35+ # If module is not imported, but available on disk then import
36+ if (Get-Module - ListAvailable | Where-Object {$_.Name -eq $m }) {
37+ Import-Module $m
38+ }
39+ else {
40+
41+ # If module is not imported, not available on disk, but is in online gallery then install and import
42+ if (Find-Module - Name $m | Where-Object {$_.Name -eq $m }) {
43+ Install-Module - Name $m - Force - Verbose - Scope CurrentUser
44+ Import-Module $m
45+ }
46+ else {
47+
48+ # If module is not imported, not available and not in online gallery then abort
49+ write-host " Module $m not imported, not available and not in online gallery, exiting."
50+ EXIT 1
51+ }
52+ }
53+ }
54+ }
55+
56+ #
57+ # Suppress warnings
58+ #
59+ Update-AzConfig - DisplayBreakingChangeWarning $false
60+
61+ # Load required modules
62+ $requiredModules = @ (
63+ " Az.Accounts" ,
64+ " Az.ConnectedMachine" ,
65+ " Az.ResourceGraph"
66+ )
67+ $requiredModules | Foreach-Object {CheckModule $_ }
68+
69+ # Subscriptions to scan
70+
71+ if ($SubId -like " *.csv" ) {
72+ $subscriptions = Import-Csv $SubId
73+ }elseif ($SubId -ne $null ){
74+ $subscriptions = [PSCustomObject ]@ {SubscriptionId = $SubId } | Get-AzSubscription
75+ }elseif ($All ){
76+ $subscriptions = Get-AzSubscription
77+ }else {
78+ Write-Host ([Environment ]::NewLine + " -- Parameter missing --" )
79+ exit
80+ }
81+
82+ Write-Host ([Environment ]::NewLine + " -- Scanning subscriptions --" )
83+
84+ # Scan arc-enabled servers in each subscription
85+
86+ foreach ($sub in $subscriptions ){
87+
88+ if ($sub.State -ne " Enabled" ) {continue }
89+
90+ try {
91+ Set-AzContext - SubscriptionId $sub.Id
92+ }catch {
93+ write-host " [Environment]::NewLine + Invalid subscription: $ ( $sub.Id ) "
94+ {continue }
95+ }
96+
97+ $query = "
98+ resources
99+ | where type =~ 'microsoft.hybridcompute/machines/extensions'
100+ | extend extensionPublisher = tostring(properties.publisher), extensionType = tostring(properties.type), provisioningState = tostring(properties.provisioningState)
101+ | where extensionPublisher =~ 'Microsoft.AzureData'
102+ | where provisioningState =~ 'Succeeded'
103+ | parse id with * '/providers/Microsoft.HybridCompute/machines/' machineName '/extensions/' *
104+ | project machineName, extensionName = name, resourceGroup, location, subscriptionId, extensionPublisher, extensionType, properties
105+ "
106+
107+ if ($MachineName ) {$query += " | where machineName =~ '$ ( $MachineName ) '" }
108+ if ($ResourceGroup ) {$query += " | where resourceGroup =~ '$ ( $ResourceGroup ) '" }
109+
110+ $resources = Search-AzGraph - Query " $ ( $query ) | where subscriptionId =~ '$ ( $sub.Id ) '"
111+ foreach ($r in $resources ) {
112+
113+
114+
115+ $setID = @ {
116+ MachineName = $r.MachineName
117+ ResourceGroup = $r.resourceGroup
118+ Name = $r.extensionName
119+ }
120+
121+ Remove-AzConnectedMachineExtension @SetId - NoWait # | Out-Null
122+
123+ }
124+ }
125+
126+
0 commit comments