Public/Admin.ps1
|
function Get-SnowRecord { <# .SYNOPSIS Gets ServiceNow records from a table. .DESCRIPTION Returns each result as a PSCustomObject with a Snowplow.Record.<table> type name. By default, at most 100 records are returned; use -All to page through every match. .EXAMPLE Get-SnowRecord -Table incident -Query 'active=true' -Fields number,short_description -Limit 25 .EXAMPLE Get-SnowRecord -Table cmdb_ci -All | Where-Object name -like '*server*' #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory, Position = 0)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete) & (Get-Module Snowplow) { param($word) Get-SnowCompletionValue -Kind Table -Word $word } $wordToComplete })] [ValidatePattern('^[a-z0-9_]+$')][string]$Table, [string]$Query, [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) & (Get-Module Snowplow) { param($table, $word) Get-SnowCompletionValue -Kind Field -Table $table -Word $word } $fakeBoundParameters.Table $wordToComplete })] [string[]]$Fields, [ValidateRange(1, 10000)][int]$Limit = 100, [switch]$All, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $request = @{ Table = $Table Query = $Query Fields = $Fields PageSize = [Math]::Min($Limit, 1000) Backend = $Backend } if (-not $All) { $request.First = $Limit } $records = Invoke-SnowBackendRequest @request foreach ($record in $records) { if ($record -is [System.Collections.IDictionary]) { $record = [pscustomobject]$record } if ($record -is [pscustomobject]) { $record.PSTypeNames.Insert(0, "Snowplow.Record.$Table") } $record } } function New-SnowRecord { <# .SYNOPSIS Creates a record in a ServiceNow table. .EXAMPLE New-SnowRecord -Table incident -Values @{ short_description = 'Printer offline' } #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([pscustomobject])] param( [Parameter(Mandatory, Position = 0)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete) & (Get-Module Snowplow) { param($word) Get-SnowCompletionValue -Kind Table -Word $word } $wordToComplete })] [ValidatePattern('^[a-z0-9_]+$')][string]$Table, [Parameter(Mandatory, Position = 1)][System.Collections.IDictionary]$Values, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $previousConfirmPreference = $ConfirmPreference try { $session = Get-SnowSession if ($session.Environment -eq 'Prod') { if ($session.ReadOnly) { throw [System.InvalidOperationException]::new("Writes are disabled for Prod profile '$($session.Profile)'. Reconnect with -AllowWrite to enable writes.") } $ConfirmPreference = 'Low' } if ($PSCmdlet.ShouldProcess($Table, 'Create record')) { $record = Invoke-SnowBackendRequest -Table $Table -Method POST -Body $Values -Backend $Backend if ($record -is [pscustomobject]) { $record.PSTypeNames.Insert(0, "Snowplow.Record.$Table") } $record } } finally { $ConfirmPreference = $previousConfirmPreference } } function Set-SnowRecord { <# .SYNOPSIS Updates a ServiceNow record. .EXAMPLE Set-SnowRecord -Table incident -SysId $id -Values @{ priority = '2' } #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([pscustomobject])] param( [Parameter(Mandatory, Position = 0)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete) & (Get-Module Snowplow) { param($word) Get-SnowCompletionValue -Kind Table -Word $word } $wordToComplete })] [ValidatePattern('^[a-z0-9_]+$')][string]$Table, [Parameter(Mandatory, Position = 1)][ValidatePattern('^[0-9a-fA-F]{32}$')][string]$SysId, [Parameter(Mandatory, Position = 2)][System.Collections.IDictionary]$Values, [switch]$Replace, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $method = if ($Replace) { 'PUT' } else { 'PATCH' } $previousConfirmPreference = $ConfirmPreference try { $session = Get-SnowSession if ($session.Environment -eq 'Prod') { if ($session.ReadOnly) { throw [System.InvalidOperationException]::new("Writes are disabled for Prod profile '$($session.Profile)'. Reconnect with -AllowWrite to enable writes.") } $ConfirmPreference = 'Low' } if ($PSCmdlet.ShouldProcess("$Table/$SysId", 'Update record')) { $record = Invoke-SnowBackendRequest -Table $Table -SysId $SysId -Method $method -Body $Values -Backend $Backend if ($record -is [pscustomobject]) { $record.PSTypeNames.Insert(0, "Snowplow.Record.$Table") } $record } } finally { $ConfirmPreference = $previousConfirmPreference } } function Remove-SnowRecord { <# .SYNOPSIS Deletes a ServiceNow record. .EXAMPLE Remove-SnowRecord -Table incident -SysId $id -WhatIf #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param( [Parameter(Mandatory, Position = 0)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete) & (Get-Module Snowplow) { param($word) Get-SnowCompletionValue -Kind Table -Word $word } $wordToComplete })] [ValidatePattern('^[a-z0-9_]+$')][string]$Table, [Parameter(Mandatory, Position = 1)][ValidatePattern('^[0-9a-fA-F]{32}$')][string]$SysId, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $previousConfirmPreference = $ConfirmPreference try { $session = Get-SnowSession if ($session.Environment -eq 'Prod') { if ($session.ReadOnly) { throw [System.InvalidOperationException]::new("Writes are disabled for Prod profile '$($session.Profile)'. Reconnect with -AllowWrite to enable writes.") } $ConfirmPreference = 'Low' } if ($PSCmdlet.ShouldProcess("$Table/$SysId", 'Delete record')) { $null = Invoke-SnowBackendRequest -Table $Table -SysId $SysId -Method DELETE -Backend $Backend } } finally { $ConfirmPreference = $previousConfirmPreference } } function Get-SnowTable { <# .SYNOPSIS Lists ServiceNow tables and their labels. .EXAMPLE Get-SnowTable -Query 'nameSTARTSWITHcmdb' #> [CmdletBinding()] [OutputType([pscustomobject])] param( [string]$Query, [ValidateRange(1, 10000)][int]$Limit = 1000, [switch]$All, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $request = @{ Table = 'sys_db_object' Query = $Query Fields = @('sys_id', 'name', 'label', 'super_class') PageSize = [Math]::Min($Limit, 1000) Backend = $Backend } if (-not $All) { $request.First = $Limit } $tables = @(Invoke-SnowBackendRequest @request) if (-not $Query -and $All) { $script:SnowSchemaCache.Tables = $tables } $tables } function Get-SnowDictionary { <# .SYNOPSIS Gets field definitions from the ServiceNow dictionary. .EXAMPLE Get-SnowDictionary -Table incident .EXAMPLE Get-SnowDictionary -Table incident -Element priority #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete) & (Get-Module Snowplow) { param($word) Get-SnowCompletionValue -Kind Table -Word $word } $wordToComplete })] [ValidatePattern('^[a-z0-9_]+$')][string]$Table, [string]$Element, [ValidateRange(1, 10000)][int]$Limit = 1000, [switch]$All, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $query = "name=$Table" if ($Element) { $query += "^element=$Element" } $request = @{ Table = 'sys_dictionary' Query = $query Fields = @('name', 'element', 'column_label', 'internal_type', 'reference', 'mandatory', 'read_only') PageSize = [Math]::Min($Limit, 1000) Backend = $Backend } if (-not $All) { $request.First = $Limit } $fields = @(Invoke-SnowBackendRequest @request) if (-not $Element -and $All) { $script:SnowSchemaCache.Fields[$Table] = $fields } $fields } function Get-SnowCI { <# .SYNOPSIS Gets configuration items from the CMDB. .EXAMPLE Get-SnowCI -Query 'install_status=1' -Limit 50 #> [CmdletBinding()] [OutputType([pscustomobject])] param( [string]$Query, [string[]]$Fields, [ValidateRange(1, 10000)][int]$Limit = 100, [switch]$All, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $request = @{ Table = 'cmdb_ci'; Query = $Query; Fields = $Fields; Limit = $Limit; All = $All } if ($Backend) { $request.Backend = $Backend } Get-SnowRecord @request } function Get-SnowCIRelationship { <# .SYNOPSIS Gets CMDB configuration item relationships. .EXAMPLE Get-SnowCIRelationship -Query 'parent=<sys_id>' -Limit 50 #> [CmdletBinding()] [OutputType([pscustomobject])] param( [string]$Query, [string[]]$Fields, [ValidateRange(1, 10000)][int]$Limit = 100, [switch]$All, [ValidateSet('Rest', 'Sdk', 'Auto')][string]$Backend ) $request = @{ Table = 'cmdb_rel_ci'; Query = $Query; Fields = $Fields; Limit = $Limit; All = $All } if ($Backend) { $request.Backend = $Backend } Get-SnowRecord @request } function Export-SnowRecord { <# .SYNOPSIS Exports records as CSV or JSON. .EXAMPLE Get-SnowRecord -Table incident -Limit 20 | Export-SnowRecord -Format Csv -Path incidents.csv .EXAMPLE Get-SnowCI -Limit 10 | Export-SnowRecord -Format Json #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)][psobject]$InputObject, [ValidateSet('Csv', 'Json')][string]$Format = 'Json', [string]$Path ) begin { $items = [System.Collections.Generic.List[object]]::new() } process { $items.Add($InputObject) } end { $text = if ($Format -eq 'Csv') { (@($items) | ConvertTo-Csv -NoTypeInformation) -join [Environment]::NewLine } else { ConvertTo-Json -InputObject @($items) -Depth 100 } if ($Path) { Set-Content -LiteralPath $Path -Value $text -Encoding utf8NoBOM } else { $text } } } function Compare-SnowRecord { <# .SYNOPSIS Compares two record objects and returns the differing properties. .DESCRIPTION Records can be collected from either the same instance or separate instances. .EXAMPLE Compare-SnowRecord -Reference $devRecord -Difference $prodRecord .EXAMPLE $left = Get-SnowRecord -Table incident -Query "number=INC001" $right = Get-SnowRecord -Table incident -Backend Rest -Query "number=INC001" Compare-SnowRecord -Reference $left -Difference $right #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)][psobject]$Reference, [Parameter(Mandatory)][psobject]$Difference, [string[]]$Property ) $names = if ($Property) { $Property } else { @($Reference.PSObject.Properties.Name) + @($Difference.PSObject.Properties.Name) | Sort-Object -Unique } foreach ($name in $names) { $leftProperty = $Reference.PSObject.Properties[$name] $rightProperty = $Difference.PSObject.Properties[$name] $left = if ($leftProperty) { $leftProperty.Value } else { $null } $right = if ($rightProperty) { $rightProperty.Value } else { $null } if (-not $leftProperty -or -not $rightProperty -or (ConvertTo-Json -InputObject $left -Depth 50 -Compress) -cne (ConvertTo-Json -InputObject $right -Depth 50 -Compress)) { [pscustomobject]@{ Property = $name; Reference = $left; Difference = $right } } } } |