Skip to content

Commit b19aab3

Browse files
authored
Merge pull request #137 from Snow-Shell/new-ci
Create new CI and table name tab ahead
2 parents 70d7709 + a1a58e4 commit b19aab3

12 files changed

+216
-24
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 2.4
2+
- Add `New-ServiceNowConfigurationItem`, [#109](https://github.com/Snow-Shell/servicenow-powershell/issues/109)
3+
- Add grouping operators -and and -group as well as comparison operators -startwith and -endswith to `Get-ServiceNowRecord -Filter` to keep with the -operator standard
4+
- Add tab ahead/completion for the `-Table` property in `Get-ServiceNowRecord`. This will allow you to cycle through the different tables the module is aware of. The values are the 'common' names, not table names so it's easier to understand for beginners. You can also provide any other table name ad hoc.
5+
- Add Change Task to formatter and tab ahead
6+
- Fix null index error when executing `New-ServiceNowQuery` without providing a value for `-Sort`
7+
- Fix [#136](https://github.com/Snow-Shell/servicenow-powershell/issues/136) to account for PS v7.x Invoke-WebRequest headers all being arrays
8+
19
## 2.3.2
210
- Added ability to pipe to `Add-ServiceNowAttachment` and `Get-ServiceNowAttachmentDetail`. For example, `New-ServiceNowIncident @params -PassThru | Add-ServiceNowAttachment -File MyFile.txt`. This will create an incident and add an attachment in one step.
311

RELEASE.md

Whitespace-only changes.

ServiceNow/Private/Invoke-ServiceNowRestMethod.ps1

+10-2
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,16 @@ function Invoke-ServiceNowRestMethod {
167167
$records = @($content)
168168
}
169169

170-
$totalRecordCount = [int]$response.Headers.'X-Total-Count'
171-
Write-Verbose "Total number of records for this query: $totalRecordCount"
170+
$totalRecordCount = 0
171+
if ( $response.Headers.'X-Total-Count' ) {
172+
if ($PSVersionTable.PSVersion.Major -lt 6) {
173+
$totalRecordCount = [int]$response.Headers.'X-Total-Count'
174+
}
175+
else {
176+
$totalRecordCount = [int]($response.Headers.'X-Total-Count'[0])
177+
}
178+
Write-Verbose "Total number of records for this query: $totalRecordCount"
179+
}
172180

173181
# if option to get all records was provided, loop and get them all
174182
if ( $PSCmdlet.PagingParameters.IncludeTotalCount.IsPresent ) {

ServiceNow/Public/Get-ServiceNowRecord.ps1

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
Paging is supported with -First, -Skip, and -IncludeTotalCount.
99
1010
.PARAMETER Table
11-
Name of the table to be queried, by either table name or class name
11+
Name of the table to be queried, by either table name or class name. Use tab completion for list of known tables.
12+
You can also provide any table name ad hoc.
1213
1314
.PARAMETER Properties
1415
Limit the fields returned to this list
@@ -43,9 +44,9 @@
4344
4445
.EXAMPLE
4546
$filter = @('state', '-eq', '1'),
46-
'and',
47+
'-and',
4748
@('short_description','-like', 'powershell'),
48-
'group',
49+
'-group',
4950
@('state', '-eq', '2')
5051
PS > Get-ServiceNowRecord -Table incident -Filter $filter
5152
Get incident records where state equals New and short description contains the word powershell or state equals In Progress.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<#
2+
.SYNOPSIS
3+
Create a new configuration item
4+
5+
.DESCRIPTION
6+
Create a new configuration item. You can create a specific class ci or root cmdb_ci.
7+
8+
.PARAMETER Name
9+
Name of the ci
10+
11+
.PARAMETER Class
12+
Specify the class of the CI, eg. cmdb_ci_server. If not specified, cmdb_ci will be used.
13+
14+
.PARAMETER Description
15+
Description for the CI
16+
17+
.PARAMETER OperationalStatus
18+
Operational status value of the CI. Note, this is the numerical value, not display value. Eg. Use '1', not 'Operational'.
19+
20+
.PARAMETER CustomField
21+
Key/value pairs for fields not available as a function parameter, eg. @{'ip_address'='1.2.3.4'}
22+
23+
.PARAMETER PassThru
24+
Return the newly created CI
25+
26+
.PARAMETER Connection
27+
Azure Automation Connection object containing username, password, and URL for the ServiceNow instance
28+
29+
.PARAMETER ServiceNowSession
30+
ServiceNow session created by New-ServiceNowSession. Will default to script-level variable $ServiceNowSession.
31+
32+
.EXAMPLE
33+
New-ServiceNowConfigurationItem -Name 'MyServer' -Class cmdb_ci_server
34+
Create a new CI
35+
36+
.EXAMPLE
37+
New-ServiceNowConfigurationItem -Name 'MyServer' -Class cmdb_ci_server -PassThru
38+
Create a new CI and return the newly created object to the pipeline
39+
#>
40+
function New-ServiceNowConfigurationItem {
41+
42+
[CmdletBinding(DefaultParameterSetName = 'Session', SupportsShouldProcess)]
43+
44+
Param(
45+
46+
[parameter(Mandatory)]
47+
[string] $Name,
48+
49+
[parameter()]
50+
[string] $Class,
51+
52+
[parameter()]
53+
[string] $Description,
54+
55+
[parameter()]
56+
[string] $OperationalStatus,
57+
58+
# custom fields as hashtable
59+
[parameter()]
60+
[hashtable] $CustomField,
61+
62+
[Parameter()]
63+
[switch] $PassThru,
64+
65+
#Azure Automation Connection object containing username, password, and URL for the ServiceNow instance
66+
[Parameter(ParameterSetName = 'UseConnectionObject', Mandatory)]
67+
[ValidateNotNullOrEmpty()]
68+
[Hashtable] $Connection,
69+
70+
[Parameter(ParameterSetName = 'Session')]
71+
[ValidateNotNullOrEmpty()]
72+
[hashtable] $ServiceNowSession = $script:ServiceNowSession
73+
)
74+
75+
begin {}
76+
77+
process {
78+
# Create a hash table of any defined parameters (not CustomFields) that have values
79+
$definedParams = @{
80+
'Name' = 'name'
81+
'Class' = 'sys_class_name'
82+
'Description' = 'description'
83+
'OperationalStatus' = 'operational_status'
84+
}
85+
$tableEntryValues = @{}
86+
foreach ($key in $PSBoundParameters.Keys) {
87+
if ($definedParams.$key) {
88+
$tableEntryValues.Add($definedParams.$key, $PSBoundParameters.$key)
89+
}
90+
}
91+
92+
# Add CustomFields hash pairs to the Table Entry Values hash table
93+
$dupes = ForEach ($Key in $CustomField.Keys) {
94+
If ($TableEntryValues.ContainsKey($Key)) {
95+
# Capture the duplicate key name
96+
$Key
97+
}
98+
Else {
99+
# Add the unique entry to the table entry values hash table
100+
$TableEntryValues.Add($Key, $CustomField[$Key])
101+
}
102+
}
103+
104+
# Throw an error if duplicate fields were provided
105+
If ($dupes) {
106+
throw ('You are attempting to redefine a value, ''{0}'', with $CustomFields that is already set' -f ($dupes -join ","))
107+
}
108+
109+
# Table Entry Splat
110+
$params = @{
111+
Table = 'cmdb_ci'
112+
Values = $TableEntryValues
113+
PassThru = $true
114+
}
115+
116+
if ($ServiceNowSession) {
117+
$params.ServiceNowSession = $ServiceNowSession
118+
}
119+
else {
120+
$params.Connection = $Connection
121+
}
122+
123+
If ( $PSCmdlet.ShouldProcess($Name, 'Create new configuration item') ) {
124+
$response = New-ServiceNowRecord @params
125+
If ($PassThru.IsPresent) {
126+
$response.PSObject.TypeNames.Insert(0, "ServiceNow.ConfigurationItem")
127+
$response
128+
}
129+
}
130+
}
131+
}

ServiceNow/Public/New-ServiceNowIncident.ps1

+8-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Generate an Incident by "Splatting" all fields used in the 1st example plus some
2020
Category "Office"
2121
Subcategory "Outlook"
2222
ConfigurationItem UserPC1
23-
CustomFields = @{u_custom1 = "Custom Field Entry"
23+
CustomField = @{u_custom1 = "Custom Field Entry"
2424
u_another_custom = "Related Test"}
2525
}
2626
New-ServiceNowIncident @Params
@@ -66,7 +66,8 @@ function New-ServiceNowIncident {
6666

6767
# custom fields as hashtable
6868
[parameter()]
69-
[hashtable] $CustomFields,
69+
[Alias('CustomFields')]
70+
[hashtable] $CustomField,
7071

7172
# Credential used to authenticate to ServiceNow
7273
[Parameter(ParameterSetName = 'SpecifyConnectionFields', Mandatory)]
@@ -95,7 +96,7 @@ function New-ServiceNowIncident {
9596
begin {}
9697

9798
process {
98-
# Create a hash table of any defined parameters (not CustomFields) that have values
99+
# Create a hash table of any defined parameters (not CustomField) that have values
99100
$DefinedIncidentParameters = @('AssignmentGroup', 'Caller', 'Category', 'Comment', 'ConfigurationItem', 'Description', 'ShortDescription', 'Subcategory')
100101
$TableEntryValues = @{}
101102
ForEach ($Parameter in $DefinedIncidentParameters) {
@@ -115,12 +116,12 @@ function New-ServiceNowIncident {
115116
}
116117
}
117118

118-
# Add CustomFields hash pairs to the Table Entry Values hash table
119-
If ($null -ne $PSBoundParameters.CustomFields) {
120-
$DuplicateTableEntryValues = ForEach ($Key in $CustomFields.Keys) {
119+
# Add CustomField hash pairs to the Table Entry Values hash table
120+
If ($null -ne $PSBoundParameters.CustomField) {
121+
$DuplicateTableEntryValues = ForEach ($Key in $CustomField.Keys) {
121122
If (($TableEntryValues.ContainsKey($Key) -eq $False)) {
122123
# Add the unique entry to the table entry values hash table
123-
$TableEntryValues.Add($Key, $CustomFields[$Key])
124+
$TableEntryValues.Add($Key, $CustomField[$Key])
124125
}
125126
Else {
126127
# Capture the duplicate key name

ServiceNow/Public/New-ServiceNowQuery.ps1

+12-8
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ function New-ServiceNowQuery {
125125
# should be a join
126126

127127
switch ($thisFilter[0]) {
128-
'and' {
128+
{ $_ -in 'and', '-and' } {
129129
'^'
130130
}
131131

132-
'or' {
132+
{ $_ -in 'or', '-or' } {
133133
'^OR'
134134
}
135135

136-
'group' {
136+
{ $_ -in 'group', '-group' } {
137137
'^NQ'
138138
}
139139

@@ -185,10 +185,13 @@ function New-ServiceNowQuery {
185185
}
186186

187187
$orderList = $Sort
188-
# see if we're working with 1 array or multidimensional array
189-
# we want multidimensional so convert if not
190-
if ($Sort[0].GetType().Name -eq 'String') {
191-
$orderList = @(, $Sort)
188+
189+
if ( $Sort ) {
190+
# see if we're working with 1 array or multidimensional array
191+
# we want multidimensional so convert if not
192+
if ($Sort[0].GetType().Name -eq 'String') {
193+
$orderList = @(, $Sort)
194+
}
192195
}
193196

194197
$query += for ($i = 0; $i -lt $orderList.Count; $i++) {
@@ -234,7 +237,8 @@ function New-ServiceNowQuery {
234237

235238
$query -join ''
236239

237-
} else {
240+
}
241+
else {
238242
# Basic parameter set
239243

240244
# Create StringBuilder

ServiceNow/Public/New-ServiceNowRecord.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
If provided, the new record will be returned
2222
2323
.EXAMPLE
24-
New-ServiceNowTableEntry -Table incident -Values @{'Caller'='me';'short_description'='my issue'}
24+
New-ServiceNowRecord -Table incident -Values @{'Caller'='me';'short_description'='my issue'}
2525
Create a new record in the incident table
2626
2727
.INPUTS

ServiceNow/ServiceNow.format.ps1xml

+15-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,15 @@
199199
<TableHeaders>
200200
<TableColumnHeader>
201201
<Label>name</Label>
202-
<Width>60</Width>
202+
<Width>30</Width>
203+
</TableColumnHeader>
204+
<TableColumnHeader>
205+
<Label>sys_id</Label>
206+
<Width>32</Width>
207+
</TableColumnHeader>
208+
<TableColumnHeader>
209+
<Label>sys_class_name</Label>
210+
<Width>30</Width>
203211
</TableColumnHeader>
204212
<TableColumnHeader>
205213
<Label>category</Label>
@@ -216,6 +224,12 @@
216224
<TableColumnItem>
217225
<PropertyName>name</PropertyName>
218226
</TableColumnItem>
227+
<TableColumnItem>
228+
<PropertyName>sys_id</PropertyName>
229+
</TableColumnItem>
230+
<TableColumnItem>
231+
<PropertyName>sys_class_name</PropertyName>
232+
</TableColumnItem>
219233
<TableColumnItem>
220234
<PropertyName>category</PropertyName>
221235
</TableColumnItem>

ServiceNow/ServiceNow.psd1

+2-2
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 = '2.3.2'
8+
ModuleVersion = '2.4'
99

1010
# ID used to uniquely identify this module
1111
GUID = 'b90d67da-f8d0-4406-ad74-89d169cd0633'
@@ -59,7 +59,7 @@ FormatsToProcess = @('ServiceNow.format.ps1xml')
5959
NestedModules = @()
6060

6161
# Functions to export from this module
62-
FunctionsToExport = @('Get-ServiceNowRecord','New-ServiceNowSession','Add-ServiceNowAttachment','Get-ServiceNowAttachment','Get-ServiceNowAttachmentDetail','Get-ServiceNowChangeRequest','Get-ServiceNowConfigurationItem','Get-ServiceNowIncident','Get-ServiceNowRequest','Get-ServiceNowRequestedItem','Get-ServiceNowTable','Get-ServiceNowTableEntry','Get-ServiceNowUser','Get-ServiceNowUserGroup','New-ServiceNowChangeRequest','New-ServiceNowIncident','New-ServiceNowQuery','New-ServiceNowRecord','Remove-ServiceNowAttachment','Remove-ServiceNowAuth','Remove-ServiceNowRecord','Set-ServiceNowAuth','Test-ServiceNowAuthIsSet','Update-ServiceNowChangeRequest','Update-ServiceNowIncident','Update-ServiceNowNumber','Update-ServiceNowRequestItem','Update-ServiceNowRecord')
62+
FunctionsToExport = @('New-ServiceNowConfigurationItem','Get-ServiceNowRecord','New-ServiceNowSession','Add-ServiceNowAttachment','Get-ServiceNowAttachment','Get-ServiceNowAttachmentDetail','Get-ServiceNowChangeRequest','Get-ServiceNowConfigurationItem','Get-ServiceNowIncident','Get-ServiceNowRequest','Get-ServiceNowRequestedItem','Get-ServiceNowTable','Get-ServiceNowTableEntry','Get-ServiceNowUser','Get-ServiceNowUserGroup','New-ServiceNowChangeRequest','New-ServiceNowIncident','New-ServiceNowQuery','New-ServiceNowRecord','Remove-ServiceNowAttachment','Remove-ServiceNowAuth','Remove-ServiceNowRecord','Set-ServiceNowAuth','Test-ServiceNowAuthIsSet','Update-ServiceNowChangeRequest','Update-ServiceNowIncident','Update-ServiceNowNumber','Update-ServiceNowRequestItem','Update-ServiceNowRecord')
6363

6464
# Variables to export from this module
6565
VariablesToExport = 'ServiceNowSession', 'ServiceNowOperator', 'ServiceNowTable'

ServiceNow/ServiceNow.psm1

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ $script:ServiceNowTable = $config.Tables
99

1010
Export-ModuleMember -Variable ServiceNowOperator, ServiceNowTable
1111

12+
$tableArgCompleterSb = {
13+
$ServiceNowTable.ClassName | ForEach-Object {
14+
'''{0}''' -f $_
15+
}
16+
}
17+
18+
Register-ArgumentCompleter -CommandName 'Get-ServiceNowRecord' -ParameterName 'Table' -ScriptBlock $tableArgCompleterSb
19+
1220
Write-Verbose 'Import everything in sub folders folder'
1321
foreach ($Folder in @('Private', 'Public')) {
1422
$Root = Join-Path -Path $PSScriptRoot -ChildPath $Folder

ServiceNow/config/main.json

+17
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
"Name": "sc_task",
4040
"ClassName": "Catalog Task",
4141
"Type": "ServiceNow.CatalogTask"
42+
},
43+
{
44+
"Name": "change_task",
45+
"ClassName": "Change Task",
46+
"Type": "ServiceNow.ChangeTask"
4247
}
4348
],
4449
"FilterOperators": [
@@ -132,11 +137,23 @@
132137
"Description": "field starts with the value",
133138
"RequiresValue": true
134139
},
140+
{
141+
"Name": "-startswith",
142+
"QueryOperator": "STARTSWITH",
143+
"Description": "field starts with the value",
144+
"RequiresValue": true
145+
},
135146
{
136147
"Name": ".endswith",
137148
"QueryOperator": "%",
138149
"Description": "field ends with the value",
139150
"RequiresValue": true
151+
},
152+
{
153+
"Name": "-endswith",
154+
"QueryOperator": "%",
155+
"Description": "field ends with the value",
156+
"RequiresValue": true
140157
}
141158
]
142159
}

0 commit comments

Comments
 (0)