From 718acc01da33a4688e55e8a80a538baaaec93003 Mon Sep 17 00:00:00 2001 From: Jesper Fajers Date: Mon, 1 Sep 2025 14:25:32 +0000 Subject: [PATCH 1/2] Update --- .../functions/Get-AzOpsResourceDefinition.ps1 | 16 ++++++++++++++-- src/localized/en-us/Strings.psd1 | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 index 3591592f..19a05c8a 100644 --- a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 @@ -290,8 +290,10 @@ if (-not $SkipResource) { Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery' -LogStringValues $scopeObject.Name -Target $ScopeObject try { + # Skip resources with null or empty resource group + $query = "resources | where isnotempty(resourceGroup)" $SkipResourceType | ForEach-Object { $skipResourceTypes += ($(if($skipResourceTypes){","}) + "'" + $_ + "'") } - $query = "resources | where type !in~ ($skipResourceTypes)" + $query = $query + " and type !in~ ($skipResourceTypes)" if ($IncludeResourceType -ne "*") { $IncludeResourceType | ForEach-Object { $includeResourceTypes += ($(if($includeResourceTypes){","}) + "'" + $_ + "'") } $query = $query + " and type in~ ($includeResourceTypes)" @@ -309,6 +311,11 @@ if ($resourcesBase) { $resources = @() foreach ($resource in $resourcesBase) { + # Skip resources with null or empty resource group to prevent Export-AzResourceGroup errors + if ([string]::IsNullOrEmpty($resource.resourceGroup)) { + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.Processing.Resource.SkippingNoResourceGroup' -LogStringValues $resource.name, $resource.id -Target $resource + continue + } if ($resourceGroups | Where-Object { $_.name -eq $resource.resourceGroup -and $_.subscriptionId -eq $resource.subscriptionId }) { Write-AzOpsMessage -LogLevel Verbose -LogString 'Get-AzOpsResourceDefinition.Processing.Resource' -LogStringValues $resource.name, $resource.resourcegroup -Target $resource $resources += $resource @@ -347,6 +354,11 @@ $tempExportPath = [System.IO.Path]::GetTempPath() + (New-Guid).ToString() + '.json' try { & $azOps { + # Validate resource group name before calling Export-AzResourceGroup + if ([string]::IsNullOrEmpty($resource.resourceGroup)) { + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.Processing.ChildResource.SkippingNoResourceGroup' -LogStringValues $resource.name, $resource.id -Target $resource + return + } $exportParameters = @{ Resource = $resource.id ResourceGroupName = $resource.resourceGroup @@ -386,7 +398,7 @@ } catch { & $azOps { - Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.ChildResource.Warning' -LogStringValues $resource.resourceGroup, $_ -FunctionName "Get-AzOpsResourceDefinition" -ModuleName "AzOps" + Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.ChildResource.Warning' -LogStringValues $resource.resourceGroup, ($exportParameters | Out-String -NoNewline), $_ -FunctionName "Get-AzOpsResourceDefinition" -ModuleName "AzOps" } } if (Test-Path -Path $tempExportPath) { diff --git a/src/localized/en-us/Strings.psd1 b/src/localized/en-us/Strings.psd1 index f114db92..b5e71307 100644 --- a/src/localized/en-us/Strings.psd1 +++ b/src/localized/en-us/Strings.psd1 @@ -122,7 +122,7 @@ 'Get-AzOpsPolicySetDefinition.ManagementGroup' = 'Retrieving PolicySet Definition for ManagementGroup {0} ({1})' # $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup 'Get-AzOpsPolicySetDefinition.Subscription' = 'Retrieving PolicySet Definition for {0} Subscription objects' # $Subscription.count - 'Get-AzOpsResourceDefinition.ChildResource.Warning' = 'Failed to export childResources in [{0}]. Warning: [{1}]' # $resourceGroup.ResourceGroupName, $_ + 'Get-AzOpsResourceDefinition.ChildResource.Warning' = 'Failed to export childResources in [{0}] with parameters [{1}]. Warning: [{2}]' # $resource.resourceGroup, $exportParameters | Out-String -NoNewline, $_ 'Get-AzOpsResourceDefinition.Finished' = 'Finished processing scope [{0}]' # $scopeObject.Scope 'Get-AzOpsResourceDefinition.ManagementGroup.Processing' = 'Processing Management Group [{0}] ({1})' # $ScopeObject.ManagementGroupDisplayName, $ScopeObject.ManagementGroup 'Get-AzOpsResourceDefinition.Processing' = 'Processing resources at [{0}]' # $Scope @@ -134,10 +134,12 @@ 'Get-AzOpsResourceDefinition.Processing.Resource' = 'Processing resource [{0}] in resource Group [{1}]' # $resource.Name, $resourceGroup.ResourceGroupName 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery' = 'Searching for resources in [{0}]' # $scopeObject.Name 'Get-AzOpsResourceDefinition.Processing.Resource.Discovery.NotFound' = 'No resources found in [{0}]' # $scopeObject.Name - 'Get-AzOpsResourceDefinition.Processing.Resource.Warning' = 'Failed to get resources in {0}]. Consider excluding the resource causing the failure with [Core.SkipResourceType] setting' # $scopeObject.Name + 'Get-AzOpsResourceDefinition.Processing.Resource.SkippingNoResourceGroup' = 'Skipping resource [{0}] at [{1}], null or empty ResourceGroup property. Cannot export resources' # $resource.name, $resource.id + 'Get-AzOpsResourceDefinition.Processing.Resource.Warning' = 'Failed to get resources in [{0}]. Consider excluding the resource causing the failure with [Core.SkipResourceType] setting' # $scopeObject.Name 'Get-AzOpsResourceDefinition.SkippingResourceGroup' = 'SkipResourceGroup switch used, skipping resource Group discovery' # 'Get-AzOpsResourceDefinition.SkippingResources' = 'SkipResource switch used, skipping resource discovery.' # 'Get-AzOpsResourceDefinition.Processing.ChildResource' = 'Processing resource [{0}] in resource Group [{1}]' # $resource.Name, $resourceGroup.ResourceGroupName + 'Get-AzOpsResourceDefinition.Processing.ChildResource.SkippingNoResourceGroup' = 'Skipping resource [{0}] at [{1}], null or empty ResourceGroup property. Cannot export child resources' # $resource.name, $resource.id 'Get-AzOpsResourceDefinition.SkippingChildResources' = 'SkipChildResource switch used, skipping child resource discovery' # 'Get-AzOpsRoleAssignment.Assignment' = 'Found assignment {0} for role {1}' # $roleAssignment.id, $roleAssignment.properties.roleDefinitionId From 02ff365ea3a2c2a189f43519a2b2bd446c58c8d3 Mon Sep 17 00:00:00 2001 From: Jesper Fajers Date: Tue, 2 Sep 2025 11:03:39 +0000 Subject: [PATCH 2/2] Update --- src/internal/functions/Get-AzOpsResourceDefinition.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 index 19a05c8a..107409b4 100644 --- a/src/internal/functions/Get-AzOpsResourceDefinition.ps1 +++ b/src/internal/functions/Get-AzOpsResourceDefinition.ps1 @@ -356,7 +356,7 @@ & $azOps { # Validate resource group name before calling Export-AzResourceGroup if ([string]::IsNullOrEmpty($resource.resourceGroup)) { - Write-AzOpsMessage -LogLevel Warning -LogString 'Get-AzOpsResourceDefinition.Processing.ChildResource.SkippingNoResourceGroup' -LogStringValues $resource.name, $resource.id -Target $resource + Write-AzOpsMessage -LogLevel Debug -LogString 'Get-AzOpsResourceDefinition.Processing.ChildResource.SkippingNoResourceGroup' -LogStringValues $resource.name, $resource.id -Target $resource return } $exportParameters = @{