Skip to content

Commit 420d378

Browse files
authored
Merge pull request #151 from Snow-Shell/fix-149
Fix 149 and 150
2 parents 848d7bf + f8b7376 commit 420d378

7 files changed

+101
-37
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.0.1
2+
- Fix [#149](https://github.com/Snow-Shell/servicenow-powershell/issues/149), combination of `-Id` and `-IncludeCustomVariable` failing. Thanks @natescherer.
3+
- 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.
4+
- 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 :)
5+
16
## 3.0
27
- New functionality in `Get-ServiceNowRecord`
38
- Add `Id` property to easily retrieve a record by either number or sysid.

ServiceNow/Private/Invoke-ServiceNowRestMethod.ps1

+3-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ function Invoke-ServiceNowRestMethod {
149149

150150
$response = Invoke-WebRequest @params
151151

152+
Write-Debug ($response | ConvertTo-Json)
153+
152154
# TODO: this could use some work
153155
# checking for content is good, but at times we'll get content that's not valid
154156
# eg. html content when a dev instance is hibernating
@@ -193,7 +195,7 @@ function Invoke-ServiceNowRestMethod {
193195
$end = if ( $totalRecordCount -lt $setPoint ) {
194196
$totalRecordCount
195197
}
196-
else {
198+
else {
197199
$setPoint
198200
}
199201

ServiceNow/Public/Get-ServiceNowRecord.ps1

+59-29
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,15 @@
6868
.EXAMPLE
6969
Get-ServiceNowRecord -Table 'Catalog Task' -ParentId 'RITM0010001'
7070
Get tasks for the parent requested item
71-
71+
7272
.EXAMPLE
7373
Get-ServiceNowRecord -Table incident -Filter @('state', '-eq', '1') -Description 'powershell'
7474
Get incident records where state equals New or short description contains the word powershell
7575
76+
.EXAMPLE
77+
Get-ServiceNowRecord -Table incident -Filter @('assigned_to.name', '-like', 'greg')
78+
Get incident records where the assigned to user's name contains greg
79+
7680
.EXAMPLE
7781
$filter = @('state', '-eq', '1'),
7882
'-and',
@@ -102,7 +106,7 @@
102106
.EXAMPLE
103107
gsnr RITM0010001
104108
Get a specific record by number using the function alias
105-
109+
106110
.INPUTS
107111
None
108112
@@ -125,10 +129,26 @@ function Get-ServiceNowRecord {
125129

126130
[Parameter(ParameterSetName = 'Id', Mandatory, Position = 0)]
127131
[Parameter(ParameterSetName = 'Table')]
132+
[ValidateScript( {
133+
if ($_ -match '^[a-zA-Z0-9]{32}$' -or $_ -match '^([a-zA-Z]+)[0-9]+$') {
134+
$true
135+
}
136+
else {
137+
throw 'Id must be either a 32 character alphanumeric, ServiceNow sysid, or prefix/id, ServiceNow number.'
138+
}
139+
})]
128140
[Alias('sys_id', 'number')]
129141
[string] $Id,
130142

131143
[Parameter()]
144+
[ValidateScript( {
145+
if ($_ -match '^[a-zA-Z0-9]{32}$' -or $_ -match '^([a-zA-Z]+)[0-9]+$') {
146+
$true
147+
}
148+
else {
149+
throw 'ParentId must be either a 32 character alphanumeric, ServiceNow sysid, or prefix/id, ServiceNow number.'
150+
}
151+
})]
132152
[string] $ParentId,
133153

134154
[Parameter()]
@@ -161,7 +181,6 @@ function Get-ServiceNowRecord {
161181
)
162182

163183
$invokeParams = @{
164-
Table = $Table
165184
Filter = $Filter
166185
Property = $Property
167186
Sort = $Sort
@@ -173,22 +192,35 @@ function Get-ServiceNowRecord {
173192
ServiceNowSession = $ServiceNowSession
174193
}
175194

195+
if ( $Table ) {
196+
$thisTable = $script:ServiceNowTable | Where-Object { $_.Name.ToLower() -eq $Table.ToLower() -or $_.ClassName.ToLower() -eq $Table.ToLower() }
197+
if ( -not $thisTable ) {
198+
# we aren't aware of this table, create default config
199+
$thisTable = @{
200+
Name = $Table
201+
ClassName = $null
202+
Type = $null
203+
NumberPrefix = $null
204+
DescriptionField = $null
205+
}
206+
}
207+
}
208+
176209
if ( $Id ) {
177-
if ( $Id -match '[a-zA-Z0-9]{32}' ) {
178-
if ( $PSCmdlet.ParameterSetName -eq 'Id' ) {
210+
if ( $Id -match '^[a-zA-Z0-9]{32}$' ) {
211+
if ( -not $thisTable ) {
179212
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.'
180213
}
181214

182215
$idFilter = @('sys_id', '-eq', $Id)
183216
}
184217
else {
185-
if ( $PSCmdlet.ParameterSetName -eq 'Id' ) {
218+
if ( -not $thisTable ) {
186219
# get table name from prefix if only Id was provided
187-
$thisTable = $script:ServiceNowTable | Where-Object { $_.NumberPrefix -and $Id.ToLower().StartsWith($_.NumberPrefix) }
188-
if ( $thisTable ) {
189-
$invokeParams.Table = $thisTable.Name
190-
}
191-
else {
220+
$idPrefix = ($Id | Select-String -Pattern '^([a-zA-Z]+)([0-9]+$)').Matches.Groups[1].Value.ToLower()
221+
Write-Debug "Id prefix is $idPrefix"
222+
$thisTable = $script:ServiceNowTable | Where-Object { $_.NumberPrefix -and $idPrefix -eq $_.NumberPrefix }
223+
if ( -not $thisTable ) {
192224
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 ', '))
193225
}
194226
}
@@ -201,14 +233,14 @@ function Get-ServiceNowRecord {
201233
else {
202234
$invokeParams.Filter = $idFilter
203235
}
236+
204237
}
205-
else {
206-
# table name was provided, get the config entry if there is one
207-
$thisTable = $script:ServiceNowTable | Where-Object { $_.Name.ToLower() -eq $Table.ToLower() -or $_.ClassName.ToLower() -eq $Table.ToLower() }
208-
}
209-
238+
239+
# we have the table, update the params
240+
$invokeParams.Table = $thisTable.Name
241+
210242
if ( $ParentId ) {
211-
if ( $ParentId -match '[a-zA-Z0-9]{32}' ) {
243+
if ( $ParentId -match '^[a-zA-Z0-9]{32}$' ) {
212244
$parentIdFilter = @('parent.sys_id', '-eq', $ParentId)
213245
}
214246
else {
@@ -222,22 +254,19 @@ function Get-ServiceNowRecord {
222254
$invokeParams.Filter = $parentIdFilter
223255
}
224256
}
225-
257+
226258
if ( $Description ) {
227259
# determine the field we should compare for 'description' and add the filter
228-
if ( $thisTable ) {
229-
$nameFilter = @($thisTable.DescriptionField, '-like', $Description)
230-
}
231-
else {
232-
Write-Warning ('We do not have a description field for table ''{0}''; short_description will be used' -f $Table)
233-
$nameFilter = @('short_description', '-like', $Description)
260+
if ( -not $thisTable.DescriptionField ) {
261+
Write-Warning ('We do not have table ''{0}'' in the config; short_description will be used as the description field' -f $thisTable.Name)
262+
$thisTable.DescriptionField = 'short_description'
234263
}
235264

236265
if ( $invokeParams.Filter ) {
237-
$invokeParams.Filter = $invokeParams.Filter, 'and', $nameFilter
266+
$invokeParams.Filter = $invokeParams.Filter, 'and', @($thisTable.DescriptionField, '-like', $Description)
238267
}
239268
else {
240-
$invokeParams.Filter = $nameFilter
269+
$invokeParams.Filter = @($thisTable.DescriptionField, '-like', $Description)
241270
}
242271
}
243272

@@ -252,11 +281,12 @@ function Get-ServiceNowRecord {
252281
}
253282

254283
# should use Get-ServiceNowAttachment, but put this here for ease of access
255-
if ( $Table -eq 'attachment' ) {
284+
if ( $thisTable.Name -eq 'attachment' ) {
285+
Write-Warning 'For attachments, use Get-ServiceNowAttachment'
256286
$invokeParams.Remove('Table') | Out-Null
257287
$invokeParams.UriLeaf = '/attachment'
258288
}
259-
289+
260290
$result = Invoke-ServiceNowRestMethod @invokeParams
261291

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

274304
if ( $customVars ) {
275305
$customValueParams = @{
276-
Table = $Table
306+
Table = $thisTable.Name
277307
Filter = @('sys_id', '-eq', $record.sys_id)
278308
Property = $customVars.'sc_item_option.item_option_new.name' | ForEach-Object { "variables.$_" }
279309
}

ServiceNow/Public/New-ServiceNowSession.ps1

+23-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ function New-ServiceNowSession {
6868

6969
param(
7070
[Parameter(Mandatory)]
71-
[ValidateScript( { $_ | Test-ServiceNowURL })]
7271
[Alias('ServiceNowUrl')]
7372
[string] $Url,
7473

@@ -153,7 +152,7 @@ function New-ServiceNowSession {
153152

154153
$oldProgressPreference = $ProgressPreference
155154
$ProgressPreference = 'SilentlyContinue'
156-
155+
157156
$response = Invoke-WebRequest @params
158157

159158
# set the progress pref back now that done with invoke-webrequest
@@ -217,4 +216,26 @@ function New-ServiceNowSession {
217216
else {
218217
$Script:ServiceNowSession = $newSession
219218
}
219+
220+
Write-Verbose 'Getting table number prefixes'
221+
$defaultTable = $ServiceNowTable
222+
try {
223+
$numbers = Get-ServiceNowRecord -Table 'sys_number' -Property prefix, category -First 10000
224+
foreach ($number in $numbers) {
225+
if ( $number.prefix.ToLower() -notin $defaultTable.NumberPrefix ) {
226+
$ServiceNowTable.Add(
227+
[pscustomobject] @{
228+
"Name" = ($number.category.link | Select-String -Pattern '^.*\?name=(.*)$').matches.groups[1].Value
229+
"ClassName" = $number.category.display_value
230+
"Type" = $null
231+
"NumberPrefix" = $number.prefix.ToLower()
232+
"DescriptionField" = "short_description"
233+
}
234+
) | Out-Null
235+
}
236+
}
237+
}
238+
catch {
239+
Write-Verbose "Session created, but failed to populate ServiceNowTable. Prefixes beyond the default won't be available. $_"
240+
}
220241
}

ServiceNow/ServiceNow.psd1

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
RootModule = 'ServiceNow.psm1'
66

77
# Version number of this module.
8-
ModuleVersion = '3.0.0'
8+
ModuleVersion = '3.0.1'
99

1010
# ID used to uniquely identify this module
1111
GUID = 'b90d67da-f8d0-4406-ad74-89d169cd0633'

ServiceNow/ServiceNow.psm1

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ Write-Verbose $PSScriptRoot
55

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

1010
Export-ModuleMember -Variable ServiceNowOperator, ServiceNowTable
1111

1212
$tableArgCompleterSb = {
13-
$ServiceNowTable.ClassName | ForEach-Object {
14-
'''{0}''' -f $_
13+
$ServiceNowTable | ForEach-Object {
14+
if ( $_.ClassName ) {
15+
'''{0}''' -f $_.ClassName
16+
} else {
17+
'''{0}''' -f $_.Name
18+
}
1519
}
1620
}
1721

@@ -55,7 +59,7 @@ $aliases = @{
5559
'Remove-ServiceNowTableEntry' = 'Remove-ServiceNowRecord'
5660
'New-ServiceNowTableEntry' = 'New-ServiceNowRecord'
5761
'Update-ServiceNowTableEntry' = 'Update-ServiceNowRecord'
58-
'Update-ServiceNowNumber' = 'Update-ServiceNowRecord'
62+
'Update-ServiceNowNumber' = 'Update-ServiceNowRecord'
5963
'gsnr' = 'Get-ServiceNowRecord'
6064
}
6165
$aliases.GetEnumerator() | ForEach-Object {

ServiceNow/config/main.json

+2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
"Name": "sys_user",
3939
"ClassName": "User",
4040
"Type": "ServiceNow.UserAndUserGroup",
41+
"NumberPrefix": "",
4142
"DescriptionField": "name"
4243
},
4344
{
4445
"Name": "sys_user_group",
4546
"ClassName": "User Group",
4647
"Type": "ServiceNow.UserAndUserGroup",
48+
"NumberPrefix": "",
4749
"DescriptionField": "name"
4850
},
4951
{

0 commit comments

Comments
 (0)