diff --git a/.azuredevops/modulePipelines/ms.network.networkwatchers.yml b/.azuredevops/modulePipelines/ms.network.networkwatchers.yml index bcefb379c3..93d889b368 100644 --- a/.azuredevops/modulePipelines/ms.network.networkwatchers.yml +++ b/.azuredevops/modulePipelines/ms.network.networkwatchers.yml @@ -4,7 +4,7 @@ parameters: - name: removeDeployment displayName: Remove deployed module type: boolean - default: false # Only one Network Watcher can exist in the same location. If removed, a default would be created in a dedicated RG + default: true - name: prerelease displayName: Publish prerelease module type: boolean diff --git a/.github/workflows/ms.network.networkwatchers.yml b/.github/workflows/ms.network.networkwatchers.yml index 860ed2bc51..748bd1b635 100644 --- a/.github/workflows/ms.network.networkwatchers.yml +++ b/.github/workflows/ms.network.networkwatchers.yml @@ -7,7 +7,7 @@ on: type: boolean description: 'Remove deployed module' required: false - default: false # Only one Network Watcher can exist in the same location. If removed, a default would be created in a dedicated RG + default: true prerelease: type: boolean description: 'Publish prerelease module' @@ -106,8 +106,7 @@ jobs: - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/deploy.bicep' - parameterFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' + templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' location: '${{ env.location }}' resourceGroupName: '${{ env.resourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' diff --git a/docs/wiki/The CI environment - Deployment validation.md b/docs/wiki/The CI environment - Deployment validation.md index fa741f7f82..98af677fa7 100644 --- a/docs/wiki/The CI environment - Deployment validation.md +++ b/docs/wiki/The CI environment - Deployment validation.md @@ -62,7 +62,9 @@ The removal process will delete all resources created by the deployment. The lis 1. Recursively fetching the list of resource IDs created in the deployment (identified via the deployment name used). 1. Ordering the list based on resource IDs segment count (ensures child resources are removed first. E.g., `storageAccount/blobServices` comes before `storageAccount` as it has one more segments delimited by `/`). -1. Filtering out resources used as dependencies for different modules from the list (e.g., the commonly used Log Analytics workspace). +1. Filtering out resources must remain even after the test concluded from the list. This contains, but is not limited to: + 1. Resources that are autogenerated by Azure and can cause issues if not controlled (e.g., the Network Watcher resource group that is autogenerated and shared by multiple module tests) + 1. Dependencies for different modules (e.g., the commonly used Log Analytics workspace). 1. Moving specific resource types to the top of the list (if a certain order is required). For example, `diagnosticSettings` need to be removed before the resource to which they are applied, even though they are no child-resources. After a resource is removed (this happens after each resource in the list), if defined, the script will perform a **post removal operation**. This can be used for those resource types that require post-processing, like purging a soft-deleted Key Vault. diff --git a/modules/Microsoft.Network/networkWatchers/.test/common/dependencies.bicep b/modules/Microsoft.Network/networkWatchers/.test/common/dependencies.bicep new file mode 100644 index 0000000000..92f94ce08c --- /dev/null +++ b/modules/Microsoft.Network/networkWatchers/.test/common/dependencies.bicep @@ -0,0 +1,142 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the first Network Security Group to create.') +param firstNetworkSecurityGroupName string + +@description('Required. The name of the second Network Security Group to create.') +param secondNetworkSecurityGroupName string + +@description('Required. The name of the Virtual Machine to create.') +param virtualMachineName string + +@description('Optional. The password to leverage for the VM login.') +@secure() +param password string = newGuid() + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + '10.0.0.0/24' + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: '10.0.0.0/24' + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource firstNetworkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-05-01' = { + name: firstNetworkSecurityGroupName + location: location +} + +resource secondNetworkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-05-01' = { + name: secondNetworkSecurityGroupName + location: location +} + +resource networkInterface 'Microsoft.Network/networkInterfaces@2022-05-01' = { + name: '${virtualMachineName}-nic' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig01' + properties: { + subnet: { + id: virtualNetwork.properties.subnets[0].id + } + } + } + ] + } +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-08-01' = { + name: virtualMachineName + location: location + properties: { + networkProfile: { + networkInterfaces: [ + { + id: networkInterface.id + properties: { + deleteOption: 'Delete' + primary: true + } + } + ] + } + storageProfile: { + imageReference: { + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' + version: 'latest' + } + osDisk: { + deleteOption: 'Delete' + createOption: 'FromImage' + } + } + hardwareProfile: { + vmSize: 'Standard_B1ms' + } + osProfile: { + adminUsername: '${virtualMachineName}cake' + adminPassword: password + computerName: virtualMachineName + linuxConfiguration: { + disablePasswordAuthentication: false + } + } + } +} + +resource extension 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: 'NetworkWatcherAgent' + parent: virtualMachine + location: location + properties: { + publisher: 'Microsoft.Azure.NetworkWatcher' + type: 'NetworkWatcherAgentLinux' + typeHandlerVersion: '1.4' + autoUpgradeMinorVersion: true + enableAutomaticUpgrade: false + settings: {} + protectedSettings: {} + suppressFailures: false + } +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Virtual Machine.') +output virtualMachineResourceId string = virtualMachine.id + +@description('The resource ID of the first created Network Security Group.') +output firstNetworkSecurityGroupResourceId string = firstNetworkSecurityGroup.id + +@description('The resource ID of the second created Network Security Group.') +output secondNetworkSecurityGroupResourceId string = secondNetworkSecurityGroup.id diff --git a/modules/Microsoft.Network/networkWatchers/.test/common/deploy.test.bicep b/modules/Microsoft.Network/networkWatchers/.test/common/deploy.test.bicep new file mode 100644 index 0000000000..732167b673 --- /dev/null +++ b/modules/Microsoft.Network/networkWatchers/.test/common/deploy.test.bicep @@ -0,0 +1,144 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'NetworkWatcherRG' // Note, this is the default NetworkWatcher resource group. Do not change. + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nnwcom' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module resourceGroupResources 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-paramNested' + params: { + managedIdentityName: 'dep-<>-msi-${serviceShort}' + firstNetworkSecurityGroupName: 'dep-<>-nsg-1-${serviceShort}' + secondNetworkSecurityGroupName: 'dep-<>-nsg-2-${serviceShort}' + virtualMachineName: 'dep-<>-vm-${serviceShort}' + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + location: location + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../.shared/dependencyConstructs/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep<>diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-<>-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-<>-evh-${serviceShort}' + eventHubNamespaceName: 'dep-<>-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // +#disable-next-line no-hardcoded-location // Disabled as the default RG & location are created in always one location, but each test has to deploy into a different one +var testLocation = 'westeurope' +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: 'NetworkWatcher_${testLocation}' + location: testLocation + connectionMonitors: [ + { + name: '<>-${serviceShort}-cm-001' + endpoints: [ + { + name: '<>-subnet-001(${resourceGroup.name})' + resourceId: resourceGroupResources.outputs.virtualMachineResourceId + type: 'AzureVM' + } + { + address: 'www.office.com' + name: 'Office Portal' + type: 'ExternalAddress' + } + ] + testConfigurations: [ + { + httpConfiguration: { + method: 'Get' + port: 80 + preferHTTPS: false + requestHeaders: [] + validStatusCodeRanges: [ + '200' + ] + } + name: 'HTTP Test' + protocol: 'Http' + successThreshold: { + checksFailedPercent: 5 + roundTripTimeMs: 100 + } + testFrequencySec: 30 + } + ] + testGroups: [ + { + destinations: [ + 'Office Portal' + ] + disable: false + name: 'TestHTTPBing' + sources: [ + '<>-subnet-001(${resourceGroup.name})' + ] + testConfigurations: [ + 'HTTP Test' + ] + } + ] + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + flowLogs: [ + { + enabled: false + storageId: diagnosticDependencies.outputs.storageAccountResourceId + targetResourceId: resourceGroupResources.outputs.firstNetworkSecurityGroupResourceId + } + { + formatVersion: 1 + name: '<>-${serviceShort}-fl-001' + retentionInDays: 8 + storageId: diagnosticDependencies.outputs.storageAccountResourceId + targetResourceId: resourceGroupResources.outputs.secondNetworkSecurityGroupResourceId + trafficAnalyticsInterval: 10 + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + principalType: 'ServicePrincipal' + } + ] + } +} diff --git a/modules/Microsoft.Network/networkWatchers/.test/min.parameters.json b/modules/Microsoft.Network/networkWatchers/.test/min.parameters.json deleted file mode 100644 index 78acbb0c7e..0000000000 --- a/modules/Microsoft.Network/networkWatchers/.test/min.parameters.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "location": { - "value": "northeurope" - } - } -} diff --git a/modules/Microsoft.Network/networkWatchers/.test/min/deploy.test.bicep b/modules/Microsoft.Network/networkWatchers/.test/min/deploy.test.bicep new file mode 100644 index 0000000000..d379595b66 --- /dev/null +++ b/modules/Microsoft.Network/networkWatchers/.test/min/deploy.test.bicep @@ -0,0 +1,39 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'NetworkWatcherRG' // Note, this is the default NetworkWatcher resource group. Do not change. + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nnwmin' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // +#disable-next-line no-hardcoded-location // Disabled as the default RG & location are created in always one location, but each test has to deploy into a different one +var testLocation = 'northeurope' +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + // Note: This value is not required and only set to enable testing + location: testLocation + } +} diff --git a/modules/Microsoft.Network/networkWatchers/.test/parameters.json b/modules/Microsoft.Network/networkWatchers/.test/parameters.json deleted file mode 100644 index 78a7e1f272..0000000000 --- a/modules/Microsoft.Network/networkWatchers/.test/parameters.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "adp-<>-az-nw-x-001" - }, - "flowLogs": { - "value": [ - { - "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", - "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "enabled": false - }, - { - "name": "adp-<>-az-nsg-x-apgw-flowlog", - "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw", - "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", - "formatVersion": 1, - "trafficAnalyticsInterval": 10, - "retentionInDays": 8 - } - ] - }, - "connectionMonitors": { - "value": [ - { - "name": "adp-<>-az-conn-mon-x-001", - "endpoints": [ - { - "name": "<>-az-subnet-x-001(validation-rg)", - "type": "AzureVM", - "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01" - }, - { - "name": "Office Portal", - "type": "ExternalAddress", - "address": "www.office.com" - } - ], - "testConfigurations": [ - { - "name": "HTTP Test", - "testFrequencySec": 30, - "protocol": "Http", - "httpConfiguration": { - "port": 80, - "method": "Get", - "requestHeaders": [], - "validStatusCodeRanges": [ - "200" - ], - "preferHTTPS": false - }, - "successThreshold": { - "checksFailedPercent": 5, - "roundTripTimeMs": 100 - } - } - ], - "testGroups": [ - { - "name": "TestHTTPBing", - "disable": false, - "testConfigurations": [ - "HTTP Test" - ], - "sources": [ - "<>-az-subnet-x-001(validation-rg)" - ], - "destinations": [ - "Office Portal" - ] - } - ], - "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" - } - ] - }, - "roleAssignments": { - "value": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - } - } -} diff --git a/modules/Microsoft.Network/networkWatchers/readme.md b/modules/Microsoft.Network/networkWatchers/readme.md index eaf55eb3d0..63303a7ad1 100644 --- a/modules/Microsoft.Network/networkWatchers/readme.md +++ b/modules/Microsoft.Network/networkWatchers/readme.md @@ -157,7 +157,7 @@ The following module usage examples are retrieved from the content of the files >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. -

Example 1: Min

+

Example 1: Common

@@ -165,51 +165,14 @@ The following module usage examples are retrieved from the content of the files ```bicep module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-NetworkWatchers' - params: { - location: 'northeurope' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "location": { - "value": "northeurope" - } - } -} -``` - -
-

- -

Example 2: Parameters

- -
- -via Bicep module - -```bicep -module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-NetworkWatchers' + name: '${uniqueString(deployment().name)}-test-nnwcom' params: { connectionMonitors: [ { endpoints: [ { - name: '<>-az-subnet-x-001(validation-rg)' - resourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01' + name: '<>-subnet-001(${resourceGroup.name})' + resourceId: '' type: 'AzureVM' } { @@ -218,7 +181,7 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { type: 'ExternalAddress' } ] - name: 'adp-<>-az-conn-mon-x-001' + name: '<>-nnwcom-cm-001' testConfigurations: [ { httpConfiguration: { @@ -247,38 +210,40 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { disable: false name: 'TestHTTPBing' sources: [ - '<>-az-subnet-x-001(validation-rg)' + '<>-subnet-001(${resourceGroup.name})' ] testConfigurations: [ 'HTTP Test' ] } ] - workspaceResourceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' + workspaceResourceId: '' } ] flowLogs: [ { enabled: false - storageId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - targetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001' + storageId: '' + targetResourceId: '' } { formatVersion: 1 - name: 'adp-<>-az-nsg-x-apgw-flowlog' + name: '<>-nnwcom-fl-001' retentionInDays: 8 - storageId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - targetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw' + storageId: '' + targetResourceId: '' trafficAnalyticsInterval: 10 - workspaceResourceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' + workspaceResourceId: '' } ] - name: 'adp-<>-az-nw-x-001' + location: '' + name: 'NetworkWatcher_${testLocation}' roleAssignments: [ { principalIds: [ - '<>' + '' ] + principalType: 'ServicePrincipal' roleDefinitionIdOrName: 'Reader' } ] @@ -303,8 +268,8 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { { "endpoints": [ { - "name": "<>-az-subnet-x-001(validation-rg)", - "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01", + "name": "<>-subnet-001(${resourceGroup.name})", + "resourceId": "", "type": "AzureVM" }, { @@ -313,7 +278,7 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { "type": "ExternalAddress" } ], - "name": "adp-<>-az-conn-mon-x-001", + "name": "<>-nnwcom-cm-001", "testConfigurations": [ { "httpConfiguration": { @@ -342,14 +307,14 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { "disable": false, "name": "TestHTTPBing", "sources": [ - "<>-az-subnet-x-001(validation-rg)" + "<>-subnet-001(${resourceGroup.name})" ], "testConfigurations": [ "HTTP Test" ] } ], - "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "workspaceResourceId": "" } ] }, @@ -357,29 +322,33 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { "value": [ { "enabled": false, - "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001" + "storageId": "", + "targetResourceId": "" }, { "formatVersion": 1, - "name": "adp-<>-az-nsg-x-apgw-flowlog", + "name": "<>-nnwcom-fl-001", "retentionInDays": 8, - "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw", + "storageId": "", + "targetResourceId": "", "trafficAnalyticsInterval": 10, - "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "workspaceResourceId": "" } ] }, + "location": { + "value": "" + }, "name": { - "value": "adp-<>-az-nw-x-001" + "value": "NetworkWatcher_${testLocation}" }, "roleAssignments": { "value": [ { "principalIds": [ - "<>" + "" ], + "principalType": "ServicePrincipal", "roleDefinitionIdOrName": "Reader" } ] @@ -390,3 +359,40 @@ module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = {

+ +

Example 2: Min

+ +
+ +via Bicep module + +```bicep +module networkWatchers './Microsoft.Network/networkWatchers/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-test-nnwmin' + params: { + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "value": "" + } + } +} +``` + +
+

diff --git a/utilities/pipelines/resourceRemoval/helper/Remove-Deployment.ps1 b/utilities/pipelines/resourceRemoval/helper/Remove-Deployment.ps1 index a5a371e803..0e5115f5d8 100644 --- a/utilities/pipelines/resourceRemoval/helper/Remove-Deployment.ps1 +++ b/utilities/pipelines/resourceRemoval/helper/Remove-Deployment.ps1 @@ -74,6 +74,8 @@ function Remove-Deployment { } process { + $azContext = Get-AzContext + # Prepare data # ============ $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $TemplateFilePath @@ -117,12 +119,16 @@ function Remove-Deployment { # =============================== $dependencyResourceNames = Get-DependencyResourceNameList - if ($resourcesToIgnore = $resourcesToRemove | Where-Object { (Split-Path $_.resourceId -Leaf) -in $dependencyResourceNames }) { + $resourceIdsToIgnore = @( + '/subscriptions/{0}/resourceGroups/NetworkWatcherRG' -f $azContext.Subscription.Id + ) + + if ($resourcesToIgnore = $resourcesToRemove | Where-Object { (Split-Path $_.resourceId -Leaf) -in $dependencyResourceNames -or $_.resourceId -in $resourceIdsToIgnore }) { Write-Verbose 'Resources excluded from removal:' -Verbose $resourcesToIgnore | ForEach-Object { Write-Verbose ('- Ignore [{0}]' -f $_.resourceId) -Verbose } } - [array] $resourcesToRemove = $resourcesToRemove | Where-Object { (Split-Path $_.resourceId -Leaf) -notin $dependencyResourceNames } + [array] $resourcesToRemove = $resourcesToRemove | Where-Object { (Split-Path $_.resourceId -Leaf) -notin $dependencyResourceNames -and $_.resourceId -notin $resourceIdsToIgnore } Write-Verbose ('Total number of deployments after filtering all dependency resources [{0}]' -f $resourcesToRemove.Count) -Verbose # Order resources