Private/Catalog.ps1
|
# The cmdlet catalog: VirtualMetric.Catalog.json, generated from sdk/cli/catalog.yaml (go run ./cmd/pwshgen). # The same catalog drives Cloud Shell in the console; the generic semantics of its kinds and transforms are # implemented by both runtimes identically (see Invoke-VMetricCatalogCmdlet). $script:VMetricCatalogSchemaVersion = 1 function Set-VMetricCatalogPath { # Points the module at another catalog file (tests), or back to the default with $null. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Sets module state for tests only.')] [CmdletBinding()] param( [AllowNull()] [AllowEmptyString()] [string] $Path ) $script:VMetricCatalogPath = $Path $script:VMetricCatalog = $null } function Get-VMetricCatalogPath { # The catalog to read: the one set by Set-VMetricCatalogPath, else the module folder's, else (in a source # checkout, before the generator has run) the tests' fixture. [CmdletBinding()] [OutputType([string])] param() if ($script:VMetricCatalogPath) { return $script:VMetricCatalogPath } $candidates = @( (Join-Path -Path $script:ModuleRoot -ChildPath 'VirtualMetric.Catalog.json') (Join-Path -Path $script:ModuleRoot -ChildPath '../tests/fixtures/VirtualMetric.Catalog.json') ) foreach ($candidate in $candidates) { if (Test-Path -LiteralPath $candidate -PathType Leaf) { return (Resolve-Path -LiteralPath $candidate).ProviderPath } } return $candidates[0] } function Get-VMetricCatalog { # The catalog, read once and indexed: Cmdlets and Types by name (ignoring case), and ResourceTypes, the # resource type (VirtualMetric/devices) of each output type (VirtualMetric.Device) an engine cmdlet writes. [CmdletBinding()] [OutputType([pscustomobject])] param() if ($script:VMetricCatalog) { return $script:VMetricCatalog } $path = Get-VMetricCatalogPath if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw (New-VMetricException -Message "The cmdlet catalog is missing ($path). Reinstall the VirtualMetric module." ` -Code 'CatalogNotFound' -Category ObjectNotFound -Terminating) } $raw = ConvertFrom-VMetricJson -Json ([System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)) $version = [int](Get-VMetricMember -InputObject $raw -Name 'version') if ($version -gt $script:VMetricCatalogSchemaVersion) { throw (New-VMetricException -Message "The cmdlet catalog is version $version; this module reads version $($script:VMetricCatalogSchemaVersion). Update the VirtualMetric module." ` -Code 'CatalogVersionUnsupported' -Category InvalidData -Terminating) } $cmdlets = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($entry in (ConvertTo-VMetricArray -InputObject (Get-VMetricMember -InputObject $raw -Name 'cmdlets'))) { $name = [string](Get-VMetricMember -InputObject $entry -Name 'name') if ($name) { $cmdlets[$name] = $entry } } $types = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase) $rawTypes = Get-VMetricMember -InputObject $raw -Name 'types' if ($rawTypes) { foreach ($property in $rawTypes.psobject.Properties) { $types[$property.Name] = $property.Value } } $resourceTypes = [System.Collections.Generic.Dictionary[string, string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($entry in $cmdlets.Values) { $output = [string](Get-VMetricMember -InputObject $entry -Name 'output') $resourceType = [string](Get-VMetricMember -InputObject $entry -Name 'resourceType') if ($output -and $resourceType -and -not $resourceTypes.ContainsKey($output)) { $resourceTypes[$output] = $resourceType } } $script:VMetricCatalog = [pscustomobject]@{ Path = $path Version = $version # The deployment property model version the engine kinds write resources in. ApiVersion = [string](Get-VMetricMember -InputObject $raw -Name 'apiVersion') Cmdlets = $cmdlets Types = $types ResourceTypes = $resourceTypes } $script:VMetricCatalog } function Get-VMetricCatalogCmdlet { [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] [string] $Name ) $catalog = Get-VMetricCatalog $entry = $null if (-not $catalog.Cmdlets.TryGetValue($Name, [ref] $entry)) { throw (New-VMetricException -Message "The cmdlet catalog has no entry for $Name. Update the VirtualMetric module." ` -Code 'CatalogEntryNotFound' -Category ObjectNotFound -Terminating) } $entry } function Get-VMetricCatalogType { # The catalog's description of an output type ($null when it has none). [CmdletBinding()] [OutputType([pscustomobject])] param( [AllowNull()] [AllowEmptyString()] [string] $Name ) if (-not $Name) { return $null } $catalog = Get-VMetricCatalog $type = $null if ($catalog.Types.TryGetValue($Name, [ref] $type)) { return $type } return $null } function Get-VMetricCatalogParameter { # The params of a catalog entry, as an array. [CmdletBinding()] [OutputType([object[]])] param( [Parameter(Mandatory)] [object] $Entry ) return , (ConvertTo-VMetricArray -InputObject (Get-VMetricMember -InputObject $Entry -Name 'params')) } function Find-VMetricReadCmdlet { # The get cmdlet that reads what an engine cmdlet writes: the same noun (Set-VMetricDevice -> # Get-VMetricDevice), else a get cmdlet with the same output type. [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] [object] $Entry ) $catalog = Get-VMetricCatalog $name = [string](Get-VMetricMember -InputObject $Entry -Name 'name') $noun = $name.Substring($name.IndexOf('-') + 1) $candidate = $null if ($catalog.Cmdlets.TryGetValue("Get-$noun", [ref] $candidate) -and (Get-VMetricMember -InputObject $candidate -Name 'kind') -eq 'get') { return $candidate } $output = [string](Get-VMetricMember -InputObject $Entry -Name 'output') if ($output) { foreach ($other in $catalog.Cmdlets.Values) { if ((Get-VMetricMember -InputObject $other -Name 'kind') -eq 'get' -and (Get-VMetricMember -InputObject $other -Name 'output') -eq $output -and (Get-VMetricMember -InputObject $other -Name 'item')) { return $other } } } return $null } function Get-VMetricNounText { # A cmdlet's noun as words for messages: Remove-VMetricPipelineChild -> "pipeline child". [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [string] $CmdletName ) $noun = $CmdletName.Substring($CmdletName.IndexOf('-') + 1) if ($noun.StartsWith('VMetric')) { $noun = $noun.Substring('VMetric'.Length) } $words = [regex]::Replace($noun, '(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])', ' ') return $words.ToLowerInvariant() } |