Skip to content

Commit

Permalink
Merge pull request #151 from Snow-Shell/fix-149
Browse files Browse the repository at this point in the history
Fix 149 and 150
  • Loading branch information
gdbarron authored Aug 26, 2021
2 parents 848d7bf + f8b7376 commit 420d378
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 37 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 3.0.1
- Fix [#149](https://github.com/Snow-Shell/servicenow-powershell/issues/149), combination of `-Id` and `-IncludeCustomVariable` failing. Thanks @natescherer.
- Fix [#150](https://github.com/Snow-Shell/servicenow-powershell/issues/150), Test-ServiceNowURL does not account for URL with a - character. The validation wasn't providing much value so was removed.
- Getting info on all tables so we can be more intelligent/dynamic about prefixes. Querying the sys_number table and might require elevated rights. If rights aren't present, no failure will occur, this is just an added bonus for those with rights :)

## 3.0
- New functionality in `Get-ServiceNowRecord`
- Add `Id` property to easily retrieve a record by either number or sysid.
Expand Down
4 changes: 3 additions & 1 deletion ServiceNow/Private/Invoke-ServiceNowRestMethod.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ function Invoke-ServiceNowRestMethod {

$response = Invoke-WebRequest @params

Write-Debug ($response | ConvertTo-Json)

# TODO: this could use some work
# checking for content is good, but at times we'll get content that's not valid
# eg. html content when a dev instance is hibernating
Expand Down Expand Up @@ -193,7 +195,7 @@ function Invoke-ServiceNowRestMethod {
$end = if ( $totalRecordCount -lt $setPoint ) {
$totalRecordCount
}
else {
else {
$setPoint
}

Expand Down
88 changes: 59 additions & 29 deletions ServiceNow/Public/Get-ServiceNowRecord.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,15 @@
.EXAMPLE
Get-ServiceNowRecord -Table 'Catalog Task' -ParentId 'RITM0010001'
Get tasks for the parent requested item
.EXAMPLE
Get-ServiceNowRecord -Table incident -Filter @('state', '-eq', '1') -Description 'powershell'
Get incident records where state equals New or short description contains the word powershell
.EXAMPLE
Get-ServiceNowRecord -Table incident -Filter @('assigned_to.name', '-like', 'greg')
Get incident records where the assigned to user's name contains greg
.EXAMPLE
$filter = @('state', '-eq', '1'),
'-and',
Expand Down Expand Up @@ -102,7 +106,7 @@
.EXAMPLE
gsnr RITM0010001
Get a specific record by number using the function alias
.INPUTS
None
Expand All @@ -125,10 +129,26 @@ function Get-ServiceNowRecord {

[Parameter(ParameterSetName = 'Id', Mandatory, Position = 0)]
[Parameter(ParameterSetName = 'Table')]
[ValidateScript( {
if ($_ -match '^[a-zA-Z0-9]{32}$' -or $_ -match '^([a-zA-Z]+)[0-9]+$') {
$true
}
else {
throw 'Id must be either a 32 character alphanumeric, ServiceNow sysid, or prefix/id, ServiceNow number.'
}
})]
[Alias('sys_id', 'number')]
[string] $Id,

[Parameter()]
[ValidateScript( {
if ($_ -match '^[a-zA-Z0-9]{32}$' -or $_ -match '^([a-zA-Z]+)[0-9]+$') {
$true
}
else {
throw 'ParentId must be either a 32 character alphanumeric, ServiceNow sysid, or prefix/id, ServiceNow number.'
}
})]
[string] $ParentId,

[Parameter()]
Expand Down Expand Up @@ -161,7 +181,6 @@ function Get-ServiceNowRecord {
)

$invokeParams = @{
Table = $Table
Filter = $Filter
Property = $Property
Sort = $Sort
Expand All @@ -173,22 +192,35 @@ function Get-ServiceNowRecord {
ServiceNowSession = $ServiceNowSession
}

if ( $Table ) {
$thisTable = $script:ServiceNowTable | Where-Object { $_.Name.ToLower() -eq $Table.ToLower() -or $_.ClassName.ToLower() -eq $Table.ToLower() }
if ( -not $thisTable ) {
# we aren't aware of this table, create default config
$thisTable = @{
Name = $Table
ClassName = $null
Type = $null
NumberPrefix = $null
DescriptionField = $null
}
}
}

if ( $Id ) {
if ( $Id -match '[a-zA-Z0-9]{32}' ) {
if ( $PSCmdlet.ParameterSetName -eq 'Id' ) {
if ( $Id -match '^[a-zA-Z0-9]{32}$' ) {
if ( -not $thisTable ) {
throw 'Providing sys_id for -Id requires a value for -Table. Alternatively, provide an Id with a prefix, eg. INC1234567, and the table will be automatically determined.'
}

$idFilter = @('sys_id', '-eq', $Id)
}
else {
if ( $PSCmdlet.ParameterSetName -eq 'Id' ) {
if ( -not $thisTable ) {
# get table name from prefix if only Id was provided
$thisTable = $script:ServiceNowTable | Where-Object { $_.NumberPrefix -and $Id.ToLower().StartsWith($_.NumberPrefix) }
if ( $thisTable ) {
$invokeParams.Table = $thisTable.Name
}
else {
$idPrefix = ($Id | Select-String -Pattern '^([a-zA-Z]+)([0-9]+$)').Matches.Groups[1].Value.ToLower()
Write-Debug "Id prefix is $idPrefix"
$thisTable = $script:ServiceNowTable | Where-Object { $_.NumberPrefix -and $idPrefix -eq $_.NumberPrefix }
if ( -not $thisTable ) {
throw ('The prefix for Id ''{0}'' was not found and the appropriate table cannot be determined. Known prefixes are {1}. Please provide a value for -Table.' -f $Id, ($ServiceNowTable.NumberPrefix.Where( { $_ }) -join ', '))
}
}
Expand All @@ -201,14 +233,14 @@ function Get-ServiceNowRecord {
else {
$invokeParams.Filter = $idFilter
}

}
else {
# table name was provided, get the config entry if there is one
$thisTable = $script:ServiceNowTable | Where-Object { $_.Name.ToLower() -eq $Table.ToLower() -or $_.ClassName.ToLower() -eq $Table.ToLower() }
}


# we have the table, update the params
$invokeParams.Table = $thisTable.Name

if ( $ParentId ) {
if ( $ParentId -match '[a-zA-Z0-9]{32}' ) {
if ( $ParentId -match '^[a-zA-Z0-9]{32}$' ) {
$parentIdFilter = @('parent.sys_id', '-eq', $ParentId)
}
else {
Expand All @@ -222,22 +254,19 @@ function Get-ServiceNowRecord {
$invokeParams.Filter = $parentIdFilter
}
}

if ( $Description ) {
# determine the field we should compare for 'description' and add the filter
if ( $thisTable ) {
$nameFilter = @($thisTable.DescriptionField, '-like', $Description)
}
else {
Write-Warning ('We do not have a description field for table ''{0}''; short_description will be used' -f $Table)
$nameFilter = @('short_description', '-like', $Description)
if ( -not $thisTable.DescriptionField ) {
Write-Warning ('We do not have table ''{0}'' in the config; short_description will be used as the description field' -f $thisTable.Name)
$thisTable.DescriptionField = 'short_description'
}

if ( $invokeParams.Filter ) {
$invokeParams.Filter = $invokeParams.Filter, 'and', $nameFilter
$invokeParams.Filter = $invokeParams.Filter, 'and', @($thisTable.DescriptionField, '-like', $Description)
}
else {
$invokeParams.Filter = $nameFilter
$invokeParams.Filter = @($thisTable.DescriptionField, '-like', $Description)
}
}

Expand All @@ -252,11 +281,12 @@ function Get-ServiceNowRecord {
}

# should use Get-ServiceNowAttachment, but put this here for ease of access
if ( $Table -eq 'attachment' ) {
if ( $thisTable.Name -eq 'attachment' ) {
Write-Warning 'For attachments, use Get-ServiceNowAttachment'
$invokeParams.Remove('Table') | Out-Null
$invokeParams.UriLeaf = '/attachment'
}

$result = Invoke-ServiceNowRestMethod @invokeParams

if ( $result ) {
Expand All @@ -273,7 +303,7 @@ function Get-ServiceNowRecord {

if ( $customVars ) {
$customValueParams = @{
Table = $Table
Table = $thisTable.Name
Filter = @('sys_id', '-eq', $record.sys_id)
Property = $customVars.'sc_item_option.item_option_new.name' | ForEach-Object { "variables.$_" }
}
Expand Down
25 changes: 23 additions & 2 deletions ServiceNow/Public/New-ServiceNowSession.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ function New-ServiceNowSession {

param(
[Parameter(Mandatory)]
[ValidateScript( { $_ | Test-ServiceNowURL })]
[Alias('ServiceNowUrl')]
[string] $Url,

Expand Down Expand Up @@ -153,7 +152,7 @@ function New-ServiceNowSession {

$oldProgressPreference = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'

$response = Invoke-WebRequest @params

# set the progress pref back now that done with invoke-webrequest
Expand Down Expand Up @@ -217,4 +216,26 @@ function New-ServiceNowSession {
else {
$Script:ServiceNowSession = $newSession
}

Write-Verbose 'Getting table number prefixes'
$defaultTable = $ServiceNowTable
try {
$numbers = Get-ServiceNowRecord -Table 'sys_number' -Property prefix, category -First 10000
foreach ($number in $numbers) {
if ( $number.prefix.ToLower() -notin $defaultTable.NumberPrefix ) {
$ServiceNowTable.Add(
[pscustomobject] @{
"Name" = ($number.category.link | Select-String -Pattern '^.*\?name=(.*)$').matches.groups[1].Value
"ClassName" = $number.category.display_value
"Type" = $null
"NumberPrefix" = $number.prefix.ToLower()
"DescriptionField" = "short_description"
}
) | Out-Null
}
}
}
catch {
Write-Verbose "Session created, but failed to populate ServiceNowTable. Prefixes beyond the default won't be available. $_"
}
}
2 changes: 1 addition & 1 deletion ServiceNow/ServiceNow.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
RootModule = 'ServiceNow.psm1'

# Version number of this module.
ModuleVersion = '3.0.0'
ModuleVersion = '3.0.1'

# ID used to uniquely identify this module
GUID = 'b90d67da-f8d0-4406-ad74-89d169cd0633'
Expand Down
12 changes: 8 additions & 4 deletions ServiceNow/ServiceNow.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ Write-Verbose $PSScriptRoot

$config = ConvertFrom-Json (Get-Content "$PSScriptRoot\Config\main.json" -Raw)
$Script:ServiceNowOperator = $config.FilterOperators
$script:ServiceNowTable = $config.Tables
[System.Collections.ArrayList] $script:ServiceNowTable = $config.Tables

Export-ModuleMember -Variable ServiceNowOperator, ServiceNowTable

$tableArgCompleterSb = {
$ServiceNowTable.ClassName | ForEach-Object {
'''{0}''' -f $_
$ServiceNowTable | ForEach-Object {
if ( $_.ClassName ) {
'''{0}''' -f $_.ClassName
} else {
'''{0}''' -f $_.Name
}
}
}

Expand Down Expand Up @@ -55,7 +59,7 @@ $aliases = @{
'Remove-ServiceNowTableEntry' = 'Remove-ServiceNowRecord'
'New-ServiceNowTableEntry' = 'New-ServiceNowRecord'
'Update-ServiceNowTableEntry' = 'Update-ServiceNowRecord'
'Update-ServiceNowNumber' = 'Update-ServiceNowRecord'
'Update-ServiceNowNumber' = 'Update-ServiceNowRecord'
'gsnr' = 'Get-ServiceNowRecord'
}
$aliases.GetEnumerator() | ForEach-Object {
Expand Down
2 changes: 2 additions & 0 deletions ServiceNow/config/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@
"Name": "sys_user",
"ClassName": "User",
"Type": "ServiceNow.UserAndUserGroup",
"NumberPrefix": "",
"DescriptionField": "name"
},
{
"Name": "sys_user_group",
"ClassName": "User Group",
"Type": "ServiceNow.UserAndUserGroup",
"NumberPrefix": "",
"DescriptionField": "name"
},
{
Expand Down

0 comments on commit 420d378

Please sign in to comment.