manifests/collectors/Hybrid/ArcServerOperationalData.psd1

#
# GENERATED by scripts/ConvertTo-ScoutCollectorDefinition.ps1 from Modules/Public/InventoryModules/Hybrid/ArcServerOperationalData.ps1 (AB#5660).
# Field expressions are copied verbatim from the original collector and evaluate in an
# equivalent scope -- see docs/design/decisions/declarative-collectors.md.
# Review before trusting; regenerate rather than hand-patch if the source collector changes.
#
@{
    ResourceTypes = @(
        'microsoft.hybridcompute/machines'
    )

    ResourceTypeMatching = 'Grouped'

    AdditionalFilter = $null

    FilterPreamble = ''

    RowLoopVariable = '1'

    Preamble = @'
$ResUCount = 1
            $sub1 = $SUB | Where-Object { $_.Id -eq $1.subscriptionId }
            $data = $1.PROPERTIES
            $Tags = if (![string]::IsNullOrEmpty($1.tags.psobject.properties)) { $1.tags.psobject.properties } else { '0' }
            $arcExtensions = @($Resources | Where-Object { $_.TYPE -eq 'microsoft.hybridcompute/machines/extensions' })
            $advisorRecs = @($Resources | Where-Object { $_.TYPE -eq 'microsoft.advisor/recommendations' })
            $backupItems = @($Resources | Where-Object { $_.TYPE -like 'microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems' })
 
            # ---- OS Details ----
            $osName = if ($data.osName) { $data.osName } else { if ($data.osSku) { $data.osSku } else { 'N/A' } }
            $osVersion = if ($data.osVersion) { $data.osVersion } else { 'N/A' }
            $osSku = if ($data.osSku) { $data.osSku } else { 'N/A' }
 
            # ---- Arc Agent Health ----
            $agentVersion = if ($data.agentVersion) { $data.agentVersion } else { 'N/A' }
            $connStatus = if ($data.status) { $data.status } else { 'N/A' }
            $lastHB = if ($data.lastStatusChange) { ([datetime]$data.lastStatusChange).ToString('yyyy-MM-dd HH:mm') } else { 'N/A' }
            $agentErrors = if ($data.errorDetails) { ($data.errorDetails | ForEach-Object { $_.message }) -join '; ' } else { 'None' }
 
            # ---- Extensions ----
            $machExts = $arcExtensions | Where-Object { $_.id -match "/machines/$($1.NAME)/extensions/" }
            $extCount = if ($machExts) { @($machExts).Count } else { 0 }
            $extNames = if ($machExts) { ($machExts | ForEach-Object { $_.PROPERTIES.type }) -join ', ' } else { 'None' }
            $hasAMA = if ($machExts -and ($machExts.PROPERTIES.publisher -contains 'Microsoft.Azure.Monitor')) { 'Yes' } else { 'No' }
 
            # ---- Backup ----
            $backupItem = $backupItems | Where-Object { $_.PROPERTIES.sourceResourceId -eq $1.id }
            $backupEnabled = if ($backupItem) { 'Yes' } else { 'No' }
            $lastBackup = if ($backupItem) { $backupItem.PROPERTIES.lastBackupTime } else { 'N/A' }
 
            # ---- Advisor ----
            $vmAdvisor = $advisorRecs | Where-Object { $_.PROPERTIES.resourceMetadata.resourceId -eq $1.id }
            $advisorCount = if ($vmAdvisor) { @($vmAdvisor).Count } else { 0 }
            $secAdvisor = if ($vmAdvisor) { @($vmAdvisor | Where-Object { $_.PROPERTIES.category -eq 'Security' }).Count } else { 0 }
 
            # The collect phase attaches the patch response to a typed envelope; this collector
            # remains pure in-memory shaping.
            $OperationalEnvelope = @($Resources | Where-Object { $_.TYPE -eq 'AZSC/Operational/ArcServerOperationalData' -and $_.id -eq $1.id }) | Select-Object -First 1
            $patchData = Get-AZSCSafeProperty -InputObject $OperationalEnvelope -Path 'properties.PatchAssessment'
            $pendingCritical = 'N/A'; $lastPatchTime = 'N/A'
            if ($patchData -and -not (Get-AZSCSafeProperty -InputObject $patchData -Path '__AZSCError')) {
                $pendingCritical = if (Get-AZSCSafeProperty -InputObject $patchData -Path 'availablePatchCountByClassification.critical') { Get-AZSCSafeProperty -InputObject $patchData -Path 'availablePatchCountByClassification.critical' } else { 0 }
                $PatchDate = Get-AZSCSafeProperty -InputObject $patchData -Path 'lastModifiedDateTime'
                $lastPatchTime = if ($PatchDate) { ([datetime]$PatchDate).ToString('yyyy-MM-dd') } else { 'N/A' }
            }
 
            # ---- Lifecycle tags ----
            $tagEnv = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.Environment'; if (-not $tagEnv) { $tagEnv = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.environment' }; if (-not $tagEnv) { $tagEnv = 'N/A' }
            $tagOwner = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.Owner'; if (-not $tagOwner) { $tagOwner = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.owner' }; if (-not $tagOwner) { $tagOwner = 'N/A' }
            $tagCostCenter = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.CostCenter'; if (-not $tagCostCenter) { $tagCostCenter = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.costcenter' }; if (-not $tagCostCenter) { $tagCostCenter = 'N/A' }
            $tagLocation = Get-AZSCSafeProperty -InputObject $1 -Path 'tags.PhysicalLocation'; if (-not $tagLocation) { $tagLocation = 'N/A' }
'@


    AdditionalRowLoops = @()

    TagLoop = @{
        Variable = 'Tag'
        Source = '$Tags'
        Preamble = ''
    }

    Fields = @(
        @{
            Name = 'ID'
            Expression = '$1.id'
        }
        @{
            Name = 'Subscription'
            Expression = '(Get-AZSCSafeProperty -InputObject $sub1 -Path ''name'')'
        }
        @{
            Name = 'Resource Group'
            Expression = '$1.RESOURCEGROUP'
        }
        @{
            Name = 'Machine Name'
            Expression = '$1.NAME'
        }
        @{
            Name = 'Location'
            Expression = '$1.LOCATION'
        }
        @{
            Name = 'Connection Status'
            Expression = '$connStatus'
        }
        @{
            Name = 'OS Name'
            Expression = '$osName'
        }
        @{
            Name = 'OS Version'
            Expression = '$osVersion'
        }
        @{
            Name = 'OS SKU'
            Expression = '$osSku'
        }
        @{
            Name = 'Arc Agent Version'
            Expression = '$agentVersion'
        }
        @{
            Name = 'Last Status Change'
            Expression = '$lastHB'
        }
        @{
            Name = 'Agent Errors'
            Expression = '$agentErrors'
        }
        @{
            Name = 'Extensions Count'
            Expression = '$extCount'
        }
        @{
            Name = 'Extensions Installed'
            Expression = '$extNames'
        }
        @{
            Name = 'Azure Monitor Agent'
            Expression = '$hasAMA'
        }
        @{
            Name = 'Backup Enabled'
            Expression = '$backupEnabled'
        }
        @{
            Name = 'Last Backup'
            Expression = '$lastBackup'
        }
        @{
            Name = 'Advisor Recs Total'
            Expression = '$advisorCount'
        }
        @{
            Name = 'Advisor Security Recs'
            Expression = '$secAdvisor'
        }
        @{
            Name = 'Pending Critical Patches'
            Expression = '$pendingCritical'
        }
        @{
            Name = 'Last Patch Assessment'
            Expression = '$lastPatchTime'
        }
        @{
            Name = 'Tag: Environment'
            Expression = '$tagEnv'
        }
        @{
            Name = 'Tag: Owner'
            Expression = '$tagOwner'
        }
        @{
            Name = 'Tag: Cost Center'
            Expression = '$tagCostCenter'
        }
        @{
            Name = 'Tag: Physical Location'
            Expression = '$tagLocation'
        }
        @{
            Name = 'Resource U'
            Expression = '$ResUCount'
        }
        @{
            Name = 'Tag Name'
            Expression = '[string]$Tag.Name'
        }
        @{
            Name = 'Tag Value'
            Expression = '[string]$Tag.Value'
        }
    )

    Export = @{
        WorksheetName = 'Arc Server Operational Data'
        TableNamePrefix = 'ArcSrvOperDataTable_'
        Columns = @(
            'Subscription'
            'Resource Group'
            'Machine Name'
            'Location'
            'Connection Status'
            'OS Name'
            'OS Version'
            'OS SKU'
            'Arc Agent Version'
            'Last Status Change'
            'Agent Errors'
            'Extensions Count'
            'Extensions Installed'
            'Azure Monitor Agent'
            'Backup Enabled'
            'Last Backup'
            'Advisor Recs Total'
            'Advisor Security Recs'
            'Pending Critical Patches'
            'Last Patch Assessment'
            'Tag: Environment'
            'Tag: Owner'
            'Tag: Cost Center'
            'Tag: Physical Location'
            'Resource U'
        )
        TagColumns = @(
            'Tag Name'
            'Tag Value'
        )
        TagColumnsBefore = $null
        NumberFormat = '0'
        ConditionalText = @(
            'New-ConditionalText -ConditionalType ContainsText ''Disconnected'' -ConditionalTextColor ([System.Drawing.Color]::White) -BackgroundColor ([System.Drawing.Color]::Red)'
            'New-ConditionalText -ConditionalType ContainsText ''Connected'' -ConditionalTextColor ([System.Drawing.Color]::FromArgb(0,176,80)) -BackgroundColor ([System.Drawing.Color]::White)'
            'New-ConditionalText -ConditionalType ContainsText ''No'' -ConditionalTextColor ([System.Drawing.Color]::FromArgb(255,165,0)) -BackgroundColor ([System.Drawing.Color]::White)'
        )
    }

    SourceCollector = 'Modules/Public/InventoryModules/Hybrid/ArcServerOperationalData.ps1'
}