Skip to content

Commit 31f6d21

Browse files
authored
Merge pull request #133 from Snow-Shell/05112021
#19
2 parents bf12c5c + c08085b commit 31f6d21

20 files changed

+215
-173
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v2.3
2+
- Add paging support to all `Get-` functions. Use `-First`, `-Skip`, and `-IncludeTotalCount` parameters. In support of this, api calls have been changed from Invoke-RestMethod to Invoke-WebRequest.
3+
- Additional pipline support added for Table and SysId parameters to pipe `Get-` functions to `Update-` and `Remove-`.
4+
- ***Breaking change:*** deprecate `-Limit` parameter. The warning regarding deprecation went out over 2 years ago and now that paging has been implemented, it's a good time for this cleanup. Use `-First` instead.
5+
- 'TableEntry' renamed to 'Record' for `New-`, `Update-`, and `Remove-` functions. Aliases added.
6+
17
## v2.2
28
- Add advanced filtering and sorting. Initially implemented with `New-ServiceNowQuery` and `Get-ServiceNowRecord`. Filter with many different comparison operators as well as 'and', 'or', and 'group'ing. Sort ascending or descending against multiple fields. Comparison operators are the same as PowerShell for ease of use. Please use the GitHub Discussions section to provide feedback, thoughts, etc.
39
- Add `Get-ServiceNowRecord`. This function implements the new advanced filtering and sorting. As long as you know your table name, this can replace all other Get functions.

ServiceNow/Private/Invoke-ServiceNowRestMethod.ps1

+103-74
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
function Invoke-ServiceNowRestMethod {
2-
<#
3-
.SYNOPSIS
4-
Retrieves records for the specified table
5-
.DESCRIPTION
6-
The Get-ServiceNowTable function retrieves records for the specified table
7-
.INPUTS
8-
None
9-
.OUTPUTS
10-
System.Management.Automation.PSCustomObject
11-
.LINK
12-
Service-Now Kingston REST Table API: https://docs.servicenow.com/bundle/kingston-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html
13-
Service-Now Table API FAQ: https://hi.service-now.com/kb_view.do?sysparm_article=KB0534905
1+
<#
2+
.SYNOPSIS
3+
Retrieves records for the specified table
4+
.DESCRIPTION
5+
The Get-ServiceNowTable function retrieves records for the specified table
6+
.INPUTS
7+
None
8+
.OUTPUTS
9+
System.Management.Automation.PSCustomObject
10+
.LINK
11+
Service-Now Kingston REST Table API: https://docs.servicenow.com/bundle/kingston-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html
12+
Service-Now Table API FAQ: https://hi.service-now.com/kb_view.do?sysparm_article=KB0534905
1413
#>
14+
function Invoke-ServiceNowRestMethod {
1515

1616
[OutputType([System.Management.Automation.PSCustomObject])]
1717
[CmdletBinding(SupportsPaging)]
@@ -51,10 +51,6 @@ function Invoke-ServiceNowRestMethod {
5151
[Parameter()]
5252
[string] $Query,
5353

54-
# Maximum number of records to return
55-
[Parameter()]
56-
[int] $Limit,
57-
5854
# Fields to return
5955
[Parameter()]
6056
[Alias('Fields')]
@@ -102,64 +98,48 @@ function Invoke-ServiceNowRestMethod {
10298
if ( $SysId ) {
10399
$params.Uri += "/$SysId"
104100
}
105-
} else {
101+
}
102+
else {
106103
$params.Uri += $UriLeaf
107104
}
108105

109106
if ( $Method -eq 'Get') {
110107
$Body = @{
111108
'sysparm_display_value' = $DisplayValues
109+
'sysparm_query' = (New-ServiceNowQuery -Filter $Filter -Sort $Sort)
110+
'sysparm_limit' = 10
112111
}
113112

114113
# Handle paging parameters
115-
# If -Limit was provided, write a warning message, but prioritize it over -First.
116114
# The value of -First defaults to [uint64]::MaxValue if not specified.
117115
# If no paging information was provided, default to the legacy behavior, which was to return 10 records.
118116

119-
if ($PSBoundParameters.ContainsKey('Limit')) {
120-
Write-Warning "The -Limit parameter is deprecated, and may be removed in a future release. Use the -First parameter instead."
121-
$Body['sysparm_limit'] = $Limit
122-
} elseif ($PSCmdlet.PagingParameters.First -ne [uint64]::MaxValue) {
117+
if ($PSCmdlet.PagingParameters.First -ne [uint64]::MaxValue) {
123118
$Body['sysparm_limit'] = $PSCmdlet.PagingParameters.First
124-
} else {
125-
$Body['sysparm_limit'] = 10
126119
}
120+
# else {
121+
# $Body['sysparm_limit'] = 10
122+
# }
127123

128124
if ($PSCmdlet.PagingParameters.Skip) {
129125
$Body['sysparm_offset'] = $PSCmdlet.PagingParameters.Skip
130126
}
131127

132-
if ($PSCmdlet.PagingParameters.IncludeTotalCount) {
133-
# Accuracy is a double between 0.0 and 1.0 representing an estimated percentage accuracy.
134-
# 0.0 means we have no idea and 1.0 means the number is exact.
135-
136-
# ServiceNow does return this information in the X-Total-Count response header,
137-
# but we're currently using Invoke-RestMethod to perform the API call, and Invoke-RestMethod
138-
# does not provide the response headers, so we can't capture this info.
139-
140-
# To properly support this parameter, we'd need to fall back on Invoke-WebRequest, read the
141-
# X-Total-Count header of the response, and update this parameter after performing the API
142-
# call.
143-
144-
# Reference:
145-
# https://developer.servicenow.com/app.do#!/rest_api_doc?v=jakarta&id=r_TableAPI-GET
146-
147-
[double] $accuracy = 0.0
148-
$PSCmdlet.PagingParameters.NewTotalCount($PSCmdlet.PagingParameters.First, $accuracy)
149-
}
150-
151-
# Populate the query
152128
if ($Query) {
153129
$Body.sysparm_query = $Query
154-
} else {
155-
$body.sysparm_query = (New-ServiceNowQuery -Filter $Filter -Sort $Sort)
156130
}
157131

158132
if ($Properties) {
159133
$Body.sysparm_fields = ($Properties -join ',').ToLower()
160134
}
161135
}
162136

137+
# Populate the query
138+
# else {
139+
# $body['sysparm_query'] = (New-ServiceNowQuery -Filter $Filter -Sort $Sort)
140+
# }
141+
142+
163143
if ( $Values ) {
164144
$Body = $Values | ConvertTo-Json
165145

@@ -173,44 +153,94 @@ function Invoke-ServiceNowRestMethod {
173153

174154
Write-Verbose ($params | ConvertTo-Json)
175155

176-
$response = Invoke-RestMethod @params
156+
# hide invoke-webrequest progress
157+
$oldProgressPreference = $ProgressPreference
158+
$ProgressPreference = 'SilentlyContinue'
159+
160+
$response = Invoke-WebRequest @params
161+
162+
$content = $response.content | ConvertFrom-Json
163+
if ( $content.PSobject.Properties.Name -contains "result" ) {
164+
$records = @($content | Select-Object -ExpandProperty result)
165+
}
166+
else {
167+
$records = @($content)
168+
}
169+
170+
# if option to get all records was provided, loop and get them all
171+
if ( $PSCmdlet.PagingParameters.IncludeTotalCount.IsPresent ) {
172+
173+
$totalRecordCount = [int]$response.Headers.'X-Total-Count'
174+
Write-Verbose "Total number of records found was $totalRecordCount"
175+
Write-Warning "Getting $($totalRecordCount - $PSCmdlet.PagingParameters.Skip) records, this could take a while..."
176+
177+
$setPoint = $params.body.sysparm_offset + $params.body.sysparm_limit
178+
179+
while ($totalRecordCount -gt $setPoint) {
180+
181+
# up the offset so we get the next set of records
182+
$params.body.sysparm_offset += $params.body.sysparm_limit
183+
$setPoint = $params.body.sysparm_offset + $params.body.sysparm_limit
184+
185+
$end = if ( $totalRecordCount -lt $setPoint ) {
186+
$totalRecordCount
187+
}
188+
else {
189+
$setPoint
190+
}
191+
192+
Write-Verbose ('getting {0}-{1} of {2}' -f ($params.body.sysparm_offset + 1), $end, $totalRecordCount)
193+
$response = Invoke-WebRequest @params -Verbose:$false
194+
195+
$content = $response.content | ConvertFrom-Json
196+
if ( $content.PSobject.Properties.Name -contains "result" ) {
197+
$records += $content | Select-Object -ExpandProperty result
198+
}
199+
else {
200+
$records += $content
201+
}
202+
}
203+
204+
if ( $totalRecordCount -ne ($records.count + $PSCmdlet.PagingParameters.Skip) ) {
205+
Write-Error ('The expected number of records was not received. This can occur if your -First value, how many records retrieved at once, is too large. Lower this value and try again. Received: {0}, expected: {1}' -f $records.count, ($totalRecordCount - $PSCmdlet.PagingParameters.Skip))
206+
}
207+
}
208+
209+
# set the progress pref back now that done with invoke-webrequest
210+
$ProgressPreference = $oldProgressPreference
177211

178212
switch ($Method) {
179213
'Get' {
180-
if ( $response.PSobject.Properties.Name -contains "result" ) {
181-
182-
$result = $response | Select-Object -ExpandProperty result
183-
$ConvertToDateField = @('closed_at', 'expected_start', 'follow_up', 'opened_at', 'sys_created_on', 'sys_updated_on', 'work_end', 'work_start')
184-
ForEach ($SNResult in $Result) {
185-
ForEach ($Property in $ConvertToDateField) {
186-
If (-not [string]::IsNullOrEmpty($SNResult.$Property)) {
214+
$ConvertToDateField = @('closed_at', 'expected_start', 'follow_up', 'opened_at', 'sys_created_on', 'sys_updated_on', 'work_end', 'work_start')
215+
ForEach ($SNResult in $records) {
216+
ForEach ($Property in $ConvertToDateField) {
217+
If (-not [string]::IsNullOrEmpty($SNResult.$Property)) {
218+
Try {
219+
# Extract the default Date/Time formatting from the local computer's "Culture" settings, and then create the format to use when parsing the date/time from Service-Now
220+
$CultureDateTimeFormat = (Get-Culture).DateTimeFormat
221+
$DateFormat = $CultureDateTimeFormat.ShortDatePattern
222+
$TimeFormat = $CultureDateTimeFormat.LongTimePattern
223+
$DateTimeFormat = "$DateFormat $TimeFormat"
224+
$SNResult.$Property = [DateTime]::ParseExact($($SNResult.$Property), $DateTimeFormat, [System.Globalization.DateTimeFormatInfo]::InvariantInfo, [System.Globalization.DateTimeStyles]::None)
225+
}
226+
Catch {
187227
Try {
188-
# Extract the default Date/Time formatting from the local computer's "Culture" settings, and then create the format to use when parsing the date/time from Service-Now
189-
$CultureDateTimeFormat = (Get-Culture).DateTimeFormat
190-
$DateFormat = $CultureDateTimeFormat.ShortDatePattern
191-
$TimeFormat = $CultureDateTimeFormat.LongTimePattern
192-
$DateTimeFormat = "$DateFormat $TimeFormat"
228+
# Universal Format
229+
$DateTimeFormat = 'yyyy-MM-dd HH:mm:ss'
193230
$SNResult.$Property = [DateTime]::ParseExact($($SNResult.$Property), $DateTimeFormat, [System.Globalization.DateTimeFormatInfo]::InvariantInfo, [System.Globalization.DateTimeStyles]::None)
194-
} Catch {
195-
Try {
196-
# Universal Format
197-
$DateTimeFormat = 'yyyy-MM-dd HH:mm:ss'
198-
$SNResult.$Property = [DateTime]::ParseExact($($SNResult.$Property), $DateTimeFormat, [System.Globalization.DateTimeFormatInfo]::InvariantInfo, [System.Globalization.DateTimeStyles]::None)
199-
} Catch {
200-
# If the local culture and universal formats both fail keep the property as a string (Do nothing)
201-
$null = 'Silencing a PSSA alert with this line'
202-
}
231+
}
232+
Catch {
233+
# If the local culture and universal formats both fail keep the property as a string (Do nothing)
234+
$null = 'Silencing a PSSA alert with this line'
203235
}
204236
}
205237
}
206238
}
207-
} else {
208-
$response
209239
}
210240
}
211241

212242
{ $_ -in 'Post', 'Patch' } {
213-
$result = $response | Select-Object -ExpandProperty result
243+
$records = $content | Select-Object -ExpandProperty result
214244
}
215245

216246
'Delete' {
@@ -222,6 +252,5 @@ function Invoke-ServiceNowRestMethod {
222252
}
223253
}
224254

225-
$result
226-
# Invoke-RestMethod -Uri $Uri -Credential $Credential -Body $Body -ContentType "application/json" | Select-Object -ExpandProperty Result
255+
$records
227256
}

ServiceNow/Public/Get-ServiceNowChangeRequest.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowChangeRequest {
1111
[ValidateSet('Desc', 'Asc')]
1212
[string] $OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int] $Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowConfigurationItem.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowConfigurationItem {
1111
[ValidateSet('Desc', 'Asc')]
1212
[string]$OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int]$Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowIncident.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowIncident {
1111
[ValidateSet('Desc', 'Asc')]
1212
[string]$OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int]$Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowRecord.ps1

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
.DESCRIPTION
66
Retrieve records from any table with the option to filter, sort, and choose fields.
77
Given you know the table name, you shouldn't need any other 'Get-' function.
8+
Paging is supported with -First, -Skip, and -IncludeTotalCount.
89
910
.PARAMETER Table
1011
Name of the table to be queried, by either table name or class name
@@ -58,6 +59,10 @@
5859
Get-ServiceNowRecord -Table 'change request' -Filter @('opened_at', '-ge', 'javascript:gs.daysAgoEnd(30)')
5960
Get change requests opened in the last 30 days. Use class name as opposed to table name.
6061
62+
.EXAMPLE
63+
Get-ServiceNowRecord -Table 'change request' -First 100 -IncludeTotalCount
64+
Get all change requests, paging 100 at a time.
65+
6166
.INPUTS
6267
None
6368
@@ -74,7 +79,6 @@ function Get-ServiceNowRecord {
7479

7580
Param (
7681
[parameter(Mandatory)]
77-
[ValidateNotNullOrEmpty()]
7882
[Alias('sys_class_name')]
7983
[string] $Table,
8084

ServiceNow/Public/Get-ServiceNowRequest.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowRequest {
1111
[ValidateSet('Desc', 'Asc')]
1212
[string]$OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int]$Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowRequestedItem.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ function Get-ServiceNowRequestedItem {
2727
[ValidateSet('Desc', 'Asc')]
2828
[string]$OrderDirection = 'Desc',
2929

30-
# Maximum number of records to return
31-
[parameter()]
32-
[int]$Limit,
33-
3430
# Fields to return
3531
[Parameter()]
3632
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowTable.ps1

-9
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ function Get-ServiceNowTable {
2525
[Parameter()]
2626
[string] $Query,
2727

28-
# Maximum number of records to return
29-
[Parameter()]
30-
[int] $Limit,
31-
3228
# Fields to return
3329
[Parameter()]
3430
[Alias('Fields')]
@@ -70,11 +66,6 @@ function Get-ServiceNowTable {
7066
ServiceNowSession = $ServiceNowSession
7167
}
7268

73-
# # Only add the Limit parameter if it was explicitly provided
74-
if ($PSBoundParameters.ContainsKey('Limit')) {
75-
$getServiceNowTableSplat.Add('Limit', $Limit)
76-
}
77-
7869
# # Add all provided paging parameters
7970
($PSCmdlet.PagingParameters | Get-Member -MemberType Property).Name | ForEach-Object {
8071
$getServiceNowTableSplat.Add($_, $PSCmdlet.PagingParameters.$_)

ServiceNow/Public/Get-ServiceNowTableEntry.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ function Get-ServiceNowTableEntry {
3434
[ValidateSet('Desc', 'Asc')]
3535
[string] $OrderDirection = 'Desc',
3636

37-
# Maximum number of records to return
38-
[parameter()]
39-
[int] $Limit,
40-
4137
# Fields to return
4238
[Parameter()]
4339
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowUser.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowUser{
1111
[ValidateSet('Desc', 'Asc')]
1212
[string]$OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int]$Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

ServiceNow/Public/Get-ServiceNowUserGroup.ps1

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ function Get-ServiceNowUserGroup{
1111
[ValidateSet('Desc', 'Asc')]
1212
[string]$OrderDirection = 'Desc',
1313

14-
# Maximum number of records to return
15-
[Parameter()]
16-
[int]$Limit,
17-
1814
# Fields to return
1915
[Parameter()]
2016
[Alias('Fields')]

0 commit comments

Comments
 (0)