Public/ConvertTo-UTCMMonitorResource.ps1
|
function ConvertTo-UTCMMonitorResource { <# .SYNOPSIS Converts UTCM snapshot items into BaselineResources hashtables for New-UTCMMonitor. .DESCRIPTION Takes the normalized configurationItems produced by Get-UTCMSnapshot -IncludeItems (each having id / displayName / type / data) and emits hashtables in the shape expected by New-UTCMMonitor -BaselineResources: @{ displayName = '...'; resourceType = '...'; properties = @{ ... } } Accepts pipeline input of either: - The snapshot object itself (with a .configurationItems collection), or - Individual configurationItems. Optional filtering lets you narrow a full-tenant snapshot down to just the resources/properties you want monitored. .PARAMETER InputObject Pipeline input. Either a snapshot object returned by Get-UTCMSnapshot -IncludeItems, or one or more normalized configurationItems. .PARAMETER SnapshotId Alternative to piping: a snapshot GUID to fetch and convert in-line. Internally calls Get-UTCMSnapshot -IncludeItems. .PARAMETER ResourceType Optional resource-type allow-list (e.g. 'microsoft.exchange.sharedmailbox'). Items whose resourceType is not in this list are skipped. Case-insensitive. .PARAMETER Identity Optional id allow-list. Items whose id is not in this list are skipped. Case-insensitive exact match against the normalized item id. .PARAMETER IncludeProperty Optional property allow-list. When supplied, only these property names are kept in the resulting `properties` hashtable. Case-insensitive. .PARAMETER ExcludeProperty Optional property deny-list. Property names removed from the resulting `properties` hashtable. Applied after IncludeProperty. Case-insensitive. .PARAMETER DisplayNameTemplate Optional template for the per-resource displayName. Tokens: {displayName}, {id}, {type} Default: uses the item's displayName, falling back to id, then type. .OUTPUTS Hashtable. One hashtable per emitted resource, ready to pass to New-UTCMMonitor -BaselineResources. .EXAMPLE # Round-trip: snapshot -> monitor baseline $resources = Get-UTCMSnapshot -SnapshotId $id -IncludeItems | ConvertTo-UTCMMonitorResource -ResourceType microsoft.exchange.sharedmailbox New-UTCMMonitor -DisplayName 'Shared Mailbox Monitor' -BaselineResources $resources .EXAMPLE # Pull from a snapshot ID and trim properties ConvertTo-UTCMMonitorResource -SnapshotId $id ` -ResourceType microsoft.exchange.accepteddomain ` -IncludeProperty Identity,DomainType,Ensure | ForEach-Object { $_ } #> [CmdletBinding(DefaultParameterSetName = 'Pipeline')] [OutputType([hashtable])] param( [Parameter(ParameterSetName = 'Pipeline', ValueFromPipeline = $true, Mandatory = $true)] [object] $InputObject, [Parameter(ParameterSetName = 'BySnapshotId', Mandatory = $true)] [ValidateScript({ if (-not (Validate-Guid $_)) { throw "SnapshotId '$_' is not a valid GUID." } $true })] [string] $SnapshotId, [string[]] $ResourceType, [string[]] $Identity, [string[]] $IncludeProperty, [string[]] $ExcludeProperty, [string] $DisplayNameTemplate ) begin { # Build comparison sets once (case-insensitive) $typeSet = $null if ($ResourceType) { $typeSet = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($t in $ResourceType) { [void]$typeSet.Add($t) } } $idSet = $null if ($Identity) { $idSet = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($i in $Identity) { [void]$idSet.Add($i) } } $includeSet = $null if ($IncludeProperty) { $includeSet = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($p in $IncludeProperty) { [void]$includeSet.Add($p) } } $excludeSet = $null if ($ExcludeProperty) { $excludeSet = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($p in $ExcludeProperty) { [void]$excludeSet.Add($p) } } # Local helper: convert PSCustomObject / IDictionary / Hashtable -> hashtable, # optionally filtering property names by include/exclude sets. $toHashtable = { param($obj) if ($null -eq $obj) { return @{} } $result = @{} if ($obj -is [System.Collections.IDictionary]) { foreach ($key in $obj.Keys) { $name = [string]$key if ($includeSet -and -not $includeSet.Contains($name)) { continue } if ($excludeSet -and $excludeSet.Contains($name)) { continue } $result[$name] = $obj[$key] } return $result } # PSCustomObject / arbitrary object $props = $null try { $props = $obj.PSObject.Properties } catch { $props = $null } if ($null -eq $props) { return $result } foreach ($p in $props) { $name = $p.Name if ($includeSet -and -not $includeSet.Contains($name)) { continue } if ($excludeSet -and $excludeSet.Contains($name)) { continue } $result[$name] = $p.Value } return $result } # Local helper: yield baseline-resource hashtable for one item (or $null to skip). $convertItem = { param($item) if ($null -eq $item) { return $null } # Read fields defensively (snapshot items may be PSCustomObject or hashtable) $itemType = $null $itemId = $null $itemName = $null $itemData = $null if ($item -is [System.Collections.IDictionary]) { if ($item.Contains('type')) { $itemType = [string]$item['type'] } elseif ($item.Contains('resourceType')) { $itemType = [string]$item['resourceType'] } if ($item.Contains('id')) { $itemId = [string]$item['id'] } if ($item.Contains('displayName')) { $itemName = [string]$item['displayName'] } if ($item.Contains('data')) { $itemData = $item['data'] } elseif ($item.Contains('properties')) { $itemData = $item['properties'] } } else { $names = @() try { $names = $item.PSObject.Properties.Name } catch { $names = @() } if ($names -contains 'type' -and $item.type) { $itemType = [string]$item.type } elseif ($names -contains 'resourceType' -and $item.resourceType) { $itemType = [string]$item.resourceType } if ($names -contains 'id' -and $item.id) { $itemId = [string]$item.id } if ($names -contains 'displayName' -and $item.displayName) { $itemName = [string]$item.displayName } if ($names -contains 'data') { $itemData = $item.data } elseif ($names -contains 'properties') { $itemData = $item.properties } } if (-not $itemType) { return $null } if ($typeSet -and -not $typeSet.Contains($itemType)) { return $null } if ($idSet -and (-not $itemId -or -not $idSet.Contains($itemId))) { return $null } $propsHash = & $toHashtable $itemData if ($propsHash.Count -eq 0) { return $null } # Resolve displayName $resourceDisplayName = $null if ($DisplayNameTemplate) { $resourceDisplayName = $DisplayNameTemplate ` -replace '\{displayName\}', ([string]$itemName) ` -replace '\{id\}', ([string]$itemId) ` -replace '\{type\}', ([string]$itemType) } else { if ($itemName) { $resourceDisplayName = $itemName } elseif ($itemId) { $resourceDisplayName = $itemId } else { $resourceDisplayName = $itemType } } return @{ displayName = $resourceDisplayName resourceType = $itemType properties = $propsHash } } # If invoked with -SnapshotId, fetch items now and process them in begin {} if ($PSCmdlet.ParameterSetName -eq 'BySnapshotId') { if (-not (Get-Command -Name Get-UTCMSnapshot -ErrorAction SilentlyContinue)) { throw "Get-UTCMSnapshot is not available; cannot resolve -SnapshotId." } $snap = Get-UTCMSnapshot -SnapshotId $SnapshotId -IncludeItems $items = $null if ($snap -and ($snap.PSObject.Properties.Name -contains 'configurationItems')) { $items = $snap.configurationItems } if (-not $items) { Write-Verbose "Snapshot '$SnapshotId' returned no configurationItems." return } foreach ($it in $items) { $emit = & $convertItem $it if ($null -ne $emit) { $emit } } } } process { if ($PSCmdlet.ParameterSetName -ne 'Pipeline') { return } if ($null -eq $InputObject) { return } # If we were handed a snapshot object, unwrap its configurationItems. $hasConfigItems = $false try { $hasConfigItems = ($InputObject.PSObject.Properties.Name -contains 'configurationItems') } catch { $hasConfigItems = $false } if ($hasConfigItems -and $InputObject.configurationItems) { foreach ($it in $InputObject.configurationItems) { $emit = & $convertItem $it if ($null -ne $emit) { $emit } } return } # Otherwise treat as a single item $emit = & $convertItem $InputObject if ($null -ne $emit) { $emit } } } |