lex-service_now 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -49
- data/CLAUDE.md +107 -79
- data/README.md +140 -94
- data/lex-service_now.gemspec +1 -1
- data/lib/legion/extensions/service_now/access_control/runners/access_control.rb +54 -0
- data/lib/legion/extensions/service_now/account/runners/account.rb +4 -4
- data/lib/legion/extensions/service_now/aggregate/runners/aggregate.rb +1 -1
- data/lib/legion/extensions/service_now/approval/runners/approval.rb +5 -5
- data/lib/legion/extensions/service_now/asset/runners/asset.rb +6 -6
- data/lib/legion/extensions/service_now/attachment/runners/attachment.rb +4 -4
- data/lib/legion/extensions/service_now/audit/runners/audit.rb +3 -3
- data/lib/legion/extensions/service_now/business_rule/runners/business_rule.rb +5 -5
- data/lib/legion/extensions/service_now/calendar/runners/calendar.rb +60 -0
- data/lib/legion/extensions/service_now/catalog_task/runners/catalog_task.rb +51 -0
- data/lib/legion/extensions/service_now/catalog_variable/runners/catalog_variable.rb +5 -5
- data/lib/legion/extensions/service_now/change/runners/change.rb +18 -18
- data/lib/legion/extensions/service_now/ci_relationship/runners/ci_relationship.rb +52 -0
- data/lib/legion/extensions/service_now/client.rb +22 -0
- data/lib/legion/extensions/service_now/cmdb/instance/runners/instance.rb +7 -7
- data/lib/legion/extensions/service_now/cmdb/meta/runners/meta.rb +2 -2
- data/lib/legion/extensions/service_now/cmdb_health/runners/cmdb_health.rb +48 -0
- data/lib/legion/extensions/service_now/company/runners/company.rb +5 -5
- data/lib/legion/extensions/service_now/contract/runners/contract.rb +5 -5
- data/lib/legion/extensions/service_now/cost_center/runners/cost_center.rb +5 -5
- data/lib/legion/extensions/service_now/csm/runners/csm.rb +64 -0
- data/lib/legion/extensions/service_now/currency/runners/currency.rb +40 -0
- data/lib/legion/extensions/service_now/department/runners/department.rb +5 -5
- data/lib/legion/extensions/service_now/deprecation_log/runners/deprecation_log.rb +43 -0
- data/lib/legion/extensions/service_now/discovery/runners/discovery.rb +5 -5
- data/lib/legion/extensions/service_now/email_log/runners/email_log.rb +3 -3
- data/lib/legion/extensions/service_now/errors.rb +26 -0
- data/lib/legion/extensions/service_now/event/runners/event.rb +3 -3
- data/lib/legion/extensions/service_now/flow/runners/flow.rb +6 -6
- data/lib/legion/extensions/service_now/grc/runners/grc.rb +61 -0
- data/lib/legion/extensions/service_now/helpers/client.rb +55 -0
- data/lib/legion/extensions/service_now/helpers/pagination.rb +31 -0
- data/lib/legion/extensions/service_now/helpers/retry.rb +32 -0
- data/lib/legion/extensions/service_now/hr_case/runners/hr_case.rb +5 -5
- data/lib/legion/extensions/service_now/import_set/runners/import_set.rb +2 -2
- data/lib/legion/extensions/service_now/incident/runners/incident.rb +6 -6
- data/lib/legion/extensions/service_now/integration_hub/runners/integration_hub.rb +49 -0
- data/lib/legion/extensions/service_now/knowledge/runners/knowledge.rb +5 -5
- data/lib/legion/extensions/service_now/knowledge_base/runners/knowledge_base.rb +64 -0
- data/lib/legion/extensions/service_now/knowledge_feedback/runners/knowledge_feedback.rb +45 -0
- data/lib/legion/extensions/service_now/license/runners/license.rb +44 -0
- data/lib/legion/extensions/service_now/location/runners/location.rb +5 -5
- data/lib/legion/extensions/service_now/metric/runners/metric.rb +47 -0
- data/lib/legion/extensions/service_now/mid_server/runners/mid_server.rb +5 -5
- data/lib/legion/extensions/service_now/notification/runners/notification.rb +5 -5
- data/lib/legion/extensions/service_now/on_call/runners/on_call.rb +5 -5
- data/lib/legion/extensions/service_now/performance_analytics/runners/performance_analytics.rb +5 -5
- data/lib/legion/extensions/service_now/problem/runners/problem.rb +6 -6
- data/lib/legion/extensions/service_now/project/runners/project.rb +6 -6
- data/lib/legion/extensions/service_now/release/runners/release.rb +5 -5
- data/lib/legion/extensions/service_now/request/runners/request.rb +6 -6
- data/lib/legion/extensions/service_now/scheduled_job/runners/scheduled_job.rb +5 -5
- data/lib/legion/extensions/service_now/script_action/runners/script_action.rb +50 -0
- data/lib/legion/extensions/service_now/script_include/runners/script_include.rb +5 -5
- data/lib/legion/extensions/service_now/security_incident/runners/security_incident.rb +5 -5
- data/lib/legion/extensions/service_now/service_catalog/runners/service_catalog.rb +11 -11
- data/lib/legion/extensions/service_now/service_portal/runners/service_portal.rb +55 -0
- data/lib/legion/extensions/service_now/skills/approval_workflow.rb +5 -5
- data/lib/legion/extensions/service_now/skills/asset_management.rb +5 -5
- data/lib/legion/extensions/service_now/skills/change_request.rb +6 -6
- data/lib/legion/extensions/service_now/skills/cmdb_query.rb +5 -5
- data/lib/legion/extensions/service_now/skills/incident.rb +6 -6
- data/lib/legion/extensions/service_now/skills/knowledge.rb +5 -5
- data/lib/legion/extensions/service_now/skills/problem_management.rb +6 -6
- data/lib/legion/extensions/service_now/skills/request_fulfillment.rb +6 -6
- data/lib/legion/extensions/service_now/skills/security_incident_response.rb +6 -6
- data/lib/legion/extensions/service_now/skills/service_catalog.rb +6 -6
- data/lib/legion/extensions/service_now/sla/runners/sla.rb +5 -5
- data/lib/legion/extensions/service_now/survey/runners/survey.rb +5 -5
- data/lib/legion/extensions/service_now/system_property/runners/system_property.rb +6 -6
- data/lib/legion/extensions/service_now/table/runners/table.rb +7 -5
- data/lib/legion/extensions/service_now/tag/runners/tag.rb +61 -0
- data/lib/legion/extensions/service_now/task/runners/task.rb +5 -5
- data/lib/legion/extensions/service_now/ui_action/runners/ui_action.rb +53 -0
- data/lib/legion/extensions/service_now/ui_policy/runners/ui_policy.rb +51 -0
- data/lib/legion/extensions/service_now/update_set/runners/update_set.rb +6 -6
- data/lib/legion/extensions/service_now/user/runners/user.rb +7 -7
- data/lib/legion/extensions/service_now/user_group/runners/user_group.rb +9 -9
- data/lib/legion/extensions/service_now/vendor/runners/vendor.rb +60 -0
- data/lib/legion/extensions/service_now/version.rb +1 -1
- data/lib/legion/extensions/service_now/work_order/runners/work_order.rb +6 -6
- data/lib/legion/extensions/service_now/workflow/runners/workflow.rb +6 -6
- data/lib/legion/extensions/service_now.rb +23 -0
- metadata +26 -3
data/README.md
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
# lex-service_now
|
|
2
2
|
|
|
3
|
-
A LegionIO extension connecting Legion to ServiceNow via REST APIs. Covers
|
|
3
|
+
A LegionIO extension connecting Legion to ServiceNow via REST APIs. Covers **66 domains** and **345 methods** spanning ITSM, ITOM, ITAM, HR, Security, GRC, CSM, DevOps, and platform administration.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Add to your Gemfile:
|
|
8
|
-
|
|
9
7
|
```ruby
|
|
10
8
|
gem 'lex-service_now'
|
|
11
9
|
```
|
|
12
10
|
|
|
13
11
|
## Configuration
|
|
14
12
|
|
|
15
|
-
Set credentials via Legion settings (`~/.legionio/settings/service_now.json`):
|
|
16
|
-
|
|
17
13
|
```json
|
|
18
14
|
{
|
|
19
15
|
"service_now": {
|
|
@@ -24,154 +20,204 @@ Set credentials via Legion settings (`~/.legionio/settings/service_now.json`):
|
|
|
24
20
|
}
|
|
25
21
|
```
|
|
26
22
|
|
|
27
|
-
OAuth2 and Bearer token
|
|
23
|
+
OAuth2 and Bearer token are also supported — the most secure credentials provided win (OAuth2 > Bearer > Basic Auth).
|
|
28
24
|
|
|
29
25
|
## Usage
|
|
30
26
|
|
|
31
|
-
### Standalone Client
|
|
32
|
-
|
|
33
27
|
```ruby
|
|
34
|
-
require 'legion/extensions/service_now'
|
|
35
|
-
|
|
36
28
|
client = Legion::Extensions::ServiceNow::Client.new(
|
|
37
29
|
url: 'https://your-instance.service-now.com',
|
|
38
30
|
username: 'admin',
|
|
39
31
|
password: 'secret'
|
|
40
32
|
)
|
|
41
33
|
|
|
42
|
-
#
|
|
34
|
+
# ITSM
|
|
43
35
|
client.list_incidents(sysparm_query: 'state=1^priority=1', sysparm_limit: 10)
|
|
44
|
-
client.create_incident(short_description: 'Production
|
|
45
|
-
client.resolve_incident(sys_id: '
|
|
36
|
+
client.create_incident(short_description: 'Production down', urgency: '1', impact: '1')
|
|
37
|
+
client.resolve_incident(sys_id: 'abc', close_code: 'Solved (Permanently)', close_notes: 'Fixed')
|
|
46
38
|
|
|
47
|
-
# Change
|
|
48
|
-
client.create_normal(short_description: 'Deploy
|
|
49
|
-
client.get_change(id: 'CHG0012345')
|
|
39
|
+
# Change
|
|
40
|
+
client.create_normal(short_description: 'Deploy v2.0')
|
|
50
41
|
client.get_approvals(id: 'CHG0012345')
|
|
51
42
|
|
|
52
43
|
# CMDB
|
|
53
44
|
client.list_cis(class_name: 'cmdb_ci_server', sysparm_query: 'operational_status=1')
|
|
54
45
|
client.get_relationships(class_name: 'cmdb_ci_server', sys_id: 'srv001')
|
|
55
46
|
|
|
56
|
-
#
|
|
57
|
-
client.
|
|
58
|
-
client.
|
|
47
|
+
# Generic table escape hatch
|
|
48
|
+
client.table_list(table_name: 'u_custom_table', sysparm_query: 'active=true')
|
|
49
|
+
client.table_create(table_name: 'u_custom_table', name: 'New Record', u_field: 'value')
|
|
59
50
|
|
|
60
|
-
#
|
|
61
|
-
client.
|
|
62
|
-
client.list_group_members(group_sys_id: 'network_team_id')
|
|
51
|
+
# Pagination helper — automatically fetches all pages
|
|
52
|
+
all_incidents = client.paginate(:list_incidents, sysparm_query: 'state=1')
|
|
63
53
|
|
|
64
|
-
#
|
|
65
|
-
client.
|
|
54
|
+
# Retry helper — retries on rate limits and server errors
|
|
55
|
+
client.with_retry(max_retries: 3) { client.create_incident(short_description: 'Issue') }
|
|
56
|
+
|
|
57
|
+
# Error handling
|
|
58
|
+
begin
|
|
59
|
+
client.get_incident(sys_id: 'nonexistent')
|
|
60
|
+
rescue Legion::Extensions::ServiceNow::Errors::NotFoundError => e
|
|
61
|
+
puts "Not found: #{e.message} (status: #{e.status})"
|
|
62
|
+
end
|
|
66
63
|
```
|
|
67
64
|
|
|
68
|
-
## Supported Domains
|
|
65
|
+
## Supported Domains (66 total)
|
|
69
66
|
|
|
70
67
|
### ITSM
|
|
71
|
-
| Domain | Methods |
|
|
68
|
+
| Domain | Methods | Notes |
|
|
72
69
|
|--------|---------|-------|
|
|
73
|
-
| Change | 14 |
|
|
74
|
-
| Incident | 6 |
|
|
75
|
-
| Problem | 6 |
|
|
76
|
-
| Request/RITM | 6 |
|
|
77
|
-
| Approval | 5 |
|
|
78
|
-
| Task | 5 |
|
|
79
|
-
| SLA | 5 |
|
|
70
|
+
| Change | 14 | normal/emergency/standard + change_tasks/conflicts/approvals |
|
|
71
|
+
| Incident | 6 | CRUD + resolve |
|
|
72
|
+
| Problem | 6 | CRUD + close |
|
|
73
|
+
| Request/RITM | 6 | sc_request + sc_req_item |
|
|
74
|
+
| Approval | 5 | approve/reject + list_for_record |
|
|
75
|
+
| Task | 5 | CRUD + add_work_note |
|
|
76
|
+
| SLA | 5 | definitions + task SLAs |
|
|
77
|
+
| CatalogTask | 4 | sc_task list/get/update/close |
|
|
80
78
|
|
|
81
79
|
### CMDB & Discovery
|
|
82
|
-
| Domain | Methods |
|
|
80
|
+
| Domain | Methods | Notes |
|
|
83
81
|
|--------|---------|-------|
|
|
84
|
-
| CMDB Instance | 7 |
|
|
85
|
-
| CMDB Meta | 2 |
|
|
86
|
-
|
|
|
87
|
-
|
|
|
82
|
+
| CMDB Instance | 7 | CI CRUD + relationships |
|
|
83
|
+
| CMDB Meta | 2 | hierarchy + class metadata |
|
|
84
|
+
| CiRelationship | 5 | cmdb_rel_type + cmdb_rel_ci |
|
|
85
|
+
| CmdbHealth | 4 | duplicates, stale CIs, health dashboard |
|
|
86
|
+
| Discovery | 5 | schedules/logs/devices |
|
|
87
|
+
| MID Server | 5 | ecc_agent CRUD + capabilities |
|
|
88
88
|
|
|
89
89
|
### Service Catalog
|
|
90
|
-
| Domain | Methods |
|
|
90
|
+
| Domain | Methods | Notes |
|
|
91
91
|
|--------|---------|-------|
|
|
92
|
-
| Service Catalog | 11 |
|
|
93
|
-
| Catalog Variable | 5 |
|
|
92
|
+
| Service Catalog | 11 | catalogs/items/cart/order |
|
|
93
|
+
| Catalog Variable | 5 | item_option_new CRUD |
|
|
94
94
|
|
|
95
|
-
### Knowledge
|
|
96
|
-
| Domain | Methods |
|
|
95
|
+
### Knowledge
|
|
96
|
+
| Domain | Methods | Notes |
|
|
97
97
|
|--------|---------|-------|
|
|
98
|
-
| Knowledge | 5 |
|
|
99
|
-
|
|
|
98
|
+
| Knowledge | 5 | article CRUD |
|
|
99
|
+
| Knowledge Base | 6 | kb_knowledge_base CRUD + categories |
|
|
100
|
+
| Knowledge Feedback | 4 | feedback + views |
|
|
100
101
|
|
|
101
102
|
### User & Organization
|
|
102
|
-
| Domain | Methods |
|
|
103
|
+
| Domain | Methods | Notes |
|
|
103
104
|
|--------|---------|-------|
|
|
104
|
-
| User | 7 |
|
|
105
|
-
| UserGroup | 9 |
|
|
106
|
-
| Account | 4 |
|
|
107
|
-
| Location | 5 |
|
|
108
|
-
| Department | 5 |
|
|
109
|
-
| Company | 5 |
|
|
110
|
-
| Cost Center | 5 |
|
|
105
|
+
| User | 7 | CRUD + lookup_by_username/email |
|
|
106
|
+
| UserGroup | 9 | CRUD + member management |
|
|
107
|
+
| Account | 4 | account CRUD |
|
|
108
|
+
| Location | 5 | cmn_location CRUD |
|
|
109
|
+
| Department | 5 | cmn_department CRUD |
|
|
110
|
+
| Company | 5 | core_company CRUD |
|
|
111
|
+
| Cost Center | 5 | cmn_cost_center CRUD |
|
|
112
|
+
| Vendor | 5 | vendor-filtered company records |
|
|
111
113
|
|
|
112
114
|
### Asset & Contract Management
|
|
113
|
-
| Domain | Methods |
|
|
115
|
+
| Domain | Methods | Notes |
|
|
114
116
|
|--------|---------|-------|
|
|
115
|
-
| Asset | 6 |
|
|
116
|
-
| Contract | 5 |
|
|
117
|
+
| Asset | 6 | alm_asset CRUD + hardware |
|
|
118
|
+
| Contract | 5 | ast_contract CRUD |
|
|
119
|
+
| License | 4 | agreements + allocations + installed software |
|
|
117
120
|
|
|
118
|
-
### Security
|
|
119
|
-
| Domain | Methods |
|
|
121
|
+
### Security & Compliance
|
|
122
|
+
| Domain | Methods | Notes |
|
|
120
123
|
|--------|---------|-------|
|
|
121
|
-
| Security Incident | 5 |
|
|
124
|
+
| Security Incident | 5 | sn_si_incident CRUD |
|
|
125
|
+
| Access Control | 5 | sys_security_acl CRUD |
|
|
126
|
+
| GRC | 7 | risks + controls + audits + policies |
|
|
122
127
|
|
|
123
|
-
### HR
|
|
124
|
-
| Domain | Methods |
|
|
128
|
+
### HR & Customer Service
|
|
129
|
+
| Domain | Methods | Notes |
|
|
125
130
|
|--------|---------|-------|
|
|
126
|
-
| HR Case | 5 |
|
|
131
|
+
| HR Case | 5 | sn_hr_core_case CRUD |
|
|
132
|
+
| CSM | 6 | customer cases + contacts |
|
|
127
133
|
|
|
128
134
|
### Project & Release
|
|
129
|
-
| Domain | Methods |
|
|
135
|
+
| Domain | Methods | Notes |
|
|
130
136
|
|--------|---------|-------|
|
|
131
|
-
| Project | 6 |
|
|
132
|
-
| Release | 5 |
|
|
137
|
+
| Project | 6 | pm_project CRUD + tasks |
|
|
138
|
+
| Release | 5 | rm_release CRUD |
|
|
133
139
|
|
|
134
140
|
### Platform Administration
|
|
135
|
-
| Domain | Methods |
|
|
141
|
+
| Domain | Methods | Notes |
|
|
136
142
|
|--------|---------|-------|
|
|
137
|
-
| System Property | 6 |
|
|
138
|
-
| Update Set | 6 |
|
|
139
|
-
| Script Include | 5 |
|
|
140
|
-
| Business Rule | 5 |
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
|
143
|
+
| System Property | 6 | sys_properties CRUD |
|
|
144
|
+
| Update Set | 6 | CRUD + list changes |
|
|
145
|
+
| Script Include | 5 | sys_script_include CRUD |
|
|
146
|
+
| Business Rule | 5 | sys_script CRUD |
|
|
147
|
+
| Script Action | 5 | sysevent_script_action CRUD |
|
|
148
|
+
| Scheduled Job | 5 | sysauto_script CRUD |
|
|
149
|
+
| UI Policy | 5 | sys_ui_policy CRUD |
|
|
150
|
+
| UI Action | 5 | sys_ui_action CRUD |
|
|
151
|
+
| Workflow | 6 | wf_workflow + contexts |
|
|
152
|
+
| Flow/Subflow | 6 | sn_fd flows + execution |
|
|
153
|
+
| Audit | 3 | sys_audit + field changes |
|
|
154
|
+
| Deprecation Log | 4 | upgrade history + deprecations |
|
|
145
155
|
|
|
146
156
|
### ITOM & Monitoring
|
|
147
|
-
| Domain | Methods |
|
|
157
|
+
| Domain | Methods | Notes |
|
|
148
158
|
|--------|---------|-------|
|
|
149
|
-
| Event | 3 |
|
|
150
|
-
| Performance Analytics | 5 |
|
|
159
|
+
| Event | 3 | sysevent CRUD |
|
|
160
|
+
| Performance Analytics | 5 | widgets/scorecards/indicators |
|
|
161
|
+
| Metric | 4 | definitions + instances |
|
|
151
162
|
|
|
152
163
|
### Communications
|
|
153
|
-
| Domain | Methods |
|
|
164
|
+
| Domain | Methods | Notes |
|
|
154
165
|
|--------|---------|-------|
|
|
155
|
-
| Notification | 5 |
|
|
156
|
-
| Email Log | 3 |
|
|
166
|
+
| Notification | 5 | sysevent_email_action CRUD |
|
|
167
|
+
| Email Log | 3 | sys_email list/get/list_for_record |
|
|
157
168
|
|
|
158
169
|
### Field Service
|
|
159
|
-
| Domain | Methods |
|
|
170
|
+
| Domain | Methods | Notes |
|
|
171
|
+
|--------|---------|-------|
|
|
172
|
+
| Work Order | 6 | wm_order CRUD + tasks + close |
|
|
173
|
+
| On-Call | 5 | schedules + members + who_is_on_call |
|
|
174
|
+
|
|
175
|
+
### Platform Modules
|
|
176
|
+
| Domain | Methods | Notes |
|
|
160
177
|
|--------|---------|-------|
|
|
161
|
-
|
|
|
162
|
-
|
|
|
178
|
+
| Service Portal | 6 | portals/pages/widgets |
|
|
179
|
+
| Integration Hub | 5 | spokes/connections/credentials |
|
|
163
180
|
|
|
164
|
-
### Utilities
|
|
165
|
-
| Domain | Methods |
|
|
181
|
+
### Utilities & Reference
|
|
182
|
+
| Domain | Methods | Notes |
|
|
166
183
|
|--------|---------|-------|
|
|
167
|
-
| Table (generic) | 5 | Any table via
|
|
168
|
-
| Import Set | 2 |
|
|
169
|
-
| Aggregate | 1 |
|
|
170
|
-
| Attachment | 5 |
|
|
184
|
+
| Table (generic) | 5 | Any table via /api/now/table/{table} |
|
|
185
|
+
| Import Set | 2 | /api/now/import |
|
|
186
|
+
| Aggregate | 1 | count/sum/avg/min/max on any table |
|
|
187
|
+
| Attachment | 5 | upload/download files |
|
|
188
|
+
| Survey | 5 | assessments + instances + responses |
|
|
189
|
+
| Tag | 7 | label + label_entry CRUD |
|
|
190
|
+
| Currency | 3 | fx_currency + fx_rate |
|
|
191
|
+
| Calendar | 6 | cmn_schedule CRUD + entries |
|
|
192
|
+
|
|
193
|
+
## Helpers
|
|
194
|
+
|
|
195
|
+
### Pagination
|
|
196
|
+
```ruby
|
|
197
|
+
all_results = client.paginate(:list_incidents, sysparm_query: 'state=1')
|
|
198
|
+
```
|
|
199
|
+
Automatically iterates through all pages.
|
|
200
|
+
|
|
201
|
+
### Retry
|
|
202
|
+
```ruby
|
|
203
|
+
client.with_retry(max_retries: 3) { client.create_incident(...) }
|
|
204
|
+
```
|
|
205
|
+
Retries on `RateLimitError` (exponential backoff) and `ServerError`. Raises immediately on auth errors.
|
|
206
|
+
|
|
207
|
+
### Error Handling
|
|
208
|
+
```ruby
|
|
209
|
+
rescue Legion::Extensions::ServiceNow::Errors::AuthenticationError => e # 401
|
|
210
|
+
rescue Legion::Extensions::ServiceNow::Errors::AuthorizationError => e # 403
|
|
211
|
+
rescue Legion::Extensions::ServiceNow::Errors::NotFoundError => e # 404
|
|
212
|
+
rescue Legion::Extensions::ServiceNow::Errors::UnprocessableError => e # 422
|
|
213
|
+
rescue Legion::Extensions::ServiceNow::Errors::RateLimitError => e # 429
|
|
214
|
+
rescue Legion::Extensions::ServiceNow::Errors::ServerError => e # 5xx
|
|
215
|
+
rescue Legion::Extensions::ServiceNow::Errors::ServiceNowError => e # all others
|
|
216
|
+
```
|
|
171
217
|
|
|
172
|
-
## LLM Skills
|
|
218
|
+
## LLM Skills (10 total)
|
|
173
219
|
|
|
174
|
-
|
|
220
|
+
Registered automatically when `legion-llm` is available:
|
|
175
221
|
|
|
176
222
|
| Skill | Trigger Words |
|
|
177
223
|
|-------|--------------|
|
|
@@ -183,17 +229,17 @@ When `legion-llm` is available, 10 workflow skills are registered automatically:
|
|
|
183
229
|
| `servicenow:problem_management` | PRB, problem, root cause, RCA |
|
|
184
230
|
| `servicenow:request_fulfillment` | RITM, request item, fulfillment |
|
|
185
231
|
| `servicenow:approval_workflow` | approval, approve, reject |
|
|
186
|
-
| `servicenow:asset_management` | asset, hardware, inventory
|
|
232
|
+
| `servicenow:asset_management` | asset, hardware, inventory |
|
|
187
233
|
| `servicenow:security_incident_response` | SIR, security incident, breach |
|
|
188
234
|
|
|
189
235
|
## Development
|
|
190
236
|
|
|
191
237
|
```bash
|
|
192
238
|
bundle install
|
|
193
|
-
bundle exec rspec #
|
|
239
|
+
bundle exec rspec # 372 examples, 0 failures
|
|
194
240
|
bundle exec rubocop # 0 offenses
|
|
195
241
|
```
|
|
196
242
|
|
|
197
243
|
## License
|
|
198
244
|
|
|
199
|
-
MIT
|
|
245
|
+
MIT
|
data/lex-service_now.gemspec
CHANGED
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.email = ['matthewdiverson@gmail.com']
|
|
10
10
|
|
|
11
11
|
spec.summary = 'LEX::ServiceNow'
|
|
12
|
-
spec.description = 'Connects Legion to ServiceNow via
|
|
12
|
+
spec.description = 'Connects Legion to ServiceNow via 60+ REST API domains spanning ITSM, ITOM, ITAM, HR, Security, DevOps, and platform administration'
|
|
13
13
|
spec.homepage = 'https://github.com/LegionIO/lex-service_now'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
15
|
spec.required_ruby_version = '>= 3.4'
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module ServiceNow
|
|
6
|
+
module AccessControl
|
|
7
|
+
module Runners
|
|
8
|
+
module AccessControl
|
|
9
|
+
include Legion::Extensions::ServiceNow::Helpers::Client
|
|
10
|
+
|
|
11
|
+
def list_acls(sysparm_limit: 100, sysparm_offset: 0,
|
|
12
|
+
sysparm_query: nil, **)
|
|
13
|
+
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
14
|
+
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
15
|
+
resp = get('/api/now/table/sys_security_acl', params, **)
|
|
16
|
+
{ acls: resp.body['result'] }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_acl(sys_id:, **)
|
|
20
|
+
resp = get("/api/now/table/sys_security_acl/#{sys_id}", {}, **)
|
|
21
|
+
{ acl: resp.body['result'] }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_acl(name:, type:, operation:, active: true,
|
|
25
|
+
script: nil, condition: nil, **)
|
|
26
|
+
body = { name: name, type: type, operation: operation, active: active }
|
|
27
|
+
body[:script] = script if script
|
|
28
|
+
body[:condition] = condition if condition
|
|
29
|
+
resp = post('/api/now/table/sys_security_acl', body, **)
|
|
30
|
+
{ acl: resp.body['result'] }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update_acl(sys_id:, active: nil, script: nil, condition: nil, **)
|
|
34
|
+
body = {}
|
|
35
|
+
body[:active] = active unless active.nil?
|
|
36
|
+
body[:script] = script if script
|
|
37
|
+
body[:condition] = condition if condition
|
|
38
|
+
resp = patch("/api/now/table/sys_security_acl/#{sys_id}", body, **)
|
|
39
|
+
{ acl: resp.body['result'] }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def delete_acl(sys_id:, **)
|
|
43
|
+
resp = delete("/api/now/table/sys_security_acl/#{sys_id}", **)
|
|
44
|
+
{ deleted: resp.status == 204, sys_id: sys_id }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
48
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -11,12 +11,12 @@ module Legion
|
|
|
11
11
|
def list_accounts(sysparm_limit: 100, sysparm_offset: 0, sysparm_query: nil, **)
|
|
12
12
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
13
13
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
14
|
-
resp =
|
|
14
|
+
resp = get('/api/now/account', params, **)
|
|
15
15
|
{ accounts: resp.body['result'] }
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def get_account(sys_id:, **)
|
|
19
|
-
resp =
|
|
19
|
+
resp = get("/api/now/account/#{sys_id}", {}, **)
|
|
20
20
|
{ account: resp.body['result'] }
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -24,7 +24,7 @@ module Legion
|
|
|
24
24
|
body = { name: name }
|
|
25
25
|
body[:phone] = phone if phone
|
|
26
26
|
body[:email] = email if email
|
|
27
|
-
resp =
|
|
27
|
+
resp = post('/api/now/account', body, **)
|
|
28
28
|
{ account: resp.body['result'] }
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ module Legion
|
|
|
33
33
|
body[:name] = name if name
|
|
34
34
|
body[:phone] = phone if phone
|
|
35
35
|
body[:email] = email if email
|
|
36
|
-
resp =
|
|
36
|
+
resp = patch("/api/now/account/#{sys_id}", body, **)
|
|
37
37
|
{ account: resp.body['result'] }
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -21,7 +21,7 @@ module Legion
|
|
|
21
21
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
22
22
|
params[:sysparm_group_by] = sysparm_group_by if sysparm_group_by
|
|
23
23
|
params[:sysparm_having] = sysparm_having if sysparm_having
|
|
24
|
-
resp =
|
|
24
|
+
resp = get("/api/now/stats/#{table_name}", params, **)
|
|
25
25
|
{ stats: resp.body['result'] }
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -11,32 +11,32 @@ module Legion
|
|
|
11
11
|
def list_approvals(sysparm_limit: 100, sysparm_offset: 0, sysparm_query: nil, **)
|
|
12
12
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
13
13
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
14
|
-
resp =
|
|
14
|
+
resp = get('/api/now/table/sysapproval_approver', params, **)
|
|
15
15
|
{ approvals: resp.body['result'] }
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def get_approval(sys_id:, **)
|
|
19
|
-
resp =
|
|
19
|
+
resp = get("/api/now/table/sysapproval_approver/#{sys_id}", {}, **)
|
|
20
20
|
{ approval: resp.body['result'] }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def approve(sys_id:, comments: nil, **)
|
|
24
24
|
body = { state: 'approved' }
|
|
25
25
|
body[:comments] = comments if comments
|
|
26
|
-
resp =
|
|
26
|
+
resp = patch("/api/now/table/sysapproval_approver/#{sys_id}", body, **)
|
|
27
27
|
{ approval: resp.body['result'] }
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def reject(sys_id:, comments: nil, **)
|
|
31
31
|
body = { state: 'rejected' }
|
|
32
32
|
body[:comments] = comments if comments
|
|
33
|
-
resp =
|
|
33
|
+
resp = patch("/api/now/table/sysapproval_approver/#{sys_id}", body, **)
|
|
34
34
|
{ approval: resp.body['result'] }
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def list_approvals_for_record(document_id:, **)
|
|
38
38
|
params = { sysparm_query: "document_id=#{document_id}", sysparm_limit: 100 }
|
|
39
|
-
resp =
|
|
39
|
+
resp = get('/api/now/table/sysapproval_approver', params, **)
|
|
40
40
|
{ approvals: resp.body['result'] }
|
|
41
41
|
end
|
|
42
42
|
|
|
@@ -13,12 +13,12 @@ module Legion
|
|
|
13
13
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
14
14
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
15
15
|
params[:sysparm_fields] = sysparm_fields if sysparm_fields
|
|
16
|
-
resp =
|
|
16
|
+
resp = get('/api/now/table/alm_asset', params, **)
|
|
17
17
|
{ assets: resp.body['result'] }
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def get_asset(sys_id:, **)
|
|
21
|
-
resp =
|
|
21
|
+
resp = get("/api/now/table/alm_asset/#{sys_id}", {}, **)
|
|
22
22
|
{ asset: resp.body['result'] }
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ module Legion
|
|
|
28
28
|
body[:serial_number] = serial_number if serial_number
|
|
29
29
|
body[:assigned_to] = assigned_to if assigned_to
|
|
30
30
|
body[:state] = state if state
|
|
31
|
-
resp =
|
|
31
|
+
resp = post('/api/now/table/alm_asset', body, **)
|
|
32
32
|
{ asset: resp.body['result'] }
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -39,19 +39,19 @@ module Legion
|
|
|
39
39
|
body[:assigned_to] = assigned_to if assigned_to
|
|
40
40
|
body[:location] = location if location
|
|
41
41
|
body[:serial_number] = serial_number if serial_number
|
|
42
|
-
resp =
|
|
42
|
+
resp = patch("/api/now/table/alm_asset/#{sys_id}", body, **)
|
|
43
43
|
{ asset: resp.body['result'] }
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def delete_asset(sys_id:, **)
|
|
47
|
-
resp =
|
|
47
|
+
resp = delete("/api/now/table/alm_asset/#{sys_id}", **)
|
|
48
48
|
{ deleted: resp.status == 204, sys_id: sys_id }
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def list_hardware(sysparm_limit: 100, sysparm_offset: 0, sysparm_query: nil, **)
|
|
52
52
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
53
53
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
54
|
-
resp =
|
|
54
|
+
resp = get('/api/now/table/alm_hardware', params, **)
|
|
55
55
|
{ hardware: resp.body['result'] }
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -14,17 +14,17 @@ module Legion
|
|
|
14
14
|
sysparm_offset: 0, **)
|
|
15
15
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
16
16
|
params[:sysparm_query] = "table_name=#{table_name}^table_sys_id=#{table_sys_id}" if table_name && table_sys_id
|
|
17
|
-
resp =
|
|
17
|
+
resp = get('/api/now/attachment', params, **)
|
|
18
18
|
{ attachments: resp.body['result'] }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def get_attachment(sys_id:, **)
|
|
22
|
-
resp =
|
|
22
|
+
resp = get("/api/now/attachment/#{sys_id}", {}, **)
|
|
23
23
|
{ attachment: resp.body['result'] }
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def get_attachment_file(sys_id:, **)
|
|
27
|
-
resp =
|
|
27
|
+
resp = get("/api/now/attachment/#{sys_id}/file", {}, **)
|
|
28
28
|
{ content: resp.body, status: resp.status }
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -41,7 +41,7 @@ module Legion
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def delete_attachment(sys_id:, **)
|
|
44
|
-
resp =
|
|
44
|
+
resp = delete("/api/now/attachment/#{sys_id}", **)
|
|
45
45
|
{ deleted: resp.status == 204, sys_id: sys_id }
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -17,12 +17,12 @@ module Legion
|
|
|
17
17
|
elsif sysparm_query
|
|
18
18
|
params[:sysparm_query] = sysparm_query
|
|
19
19
|
end
|
|
20
|
-
resp =
|
|
20
|
+
resp = get('/api/now/table/sys_audit', params, **)
|
|
21
21
|
{ audit_records: resp.body['result'] }
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def get_audit_record(sys_id:, **)
|
|
25
|
-
resp =
|
|
25
|
+
resp = get("/api/now/table/sys_audit/#{sys_id}", {}, **)
|
|
26
26
|
{ audit_record: resp.body['result'] }
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -31,7 +31,7 @@ module Legion
|
|
|
31
31
|
query = "tablename=#{tablename}^documentkey=#{documentkey}"
|
|
32
32
|
query += "^fieldname=#{fieldname}" if fieldname
|
|
33
33
|
params = { sysparm_query: query, sysparm_limit: sysparm_limit }
|
|
34
|
-
resp =
|
|
34
|
+
resp = get('/api/now/table/sys_audit', params, **)
|
|
35
35
|
{ field_changes: resp.body['result'] }
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -12,12 +12,12 @@ module Legion
|
|
|
12
12
|
sysparm_query: nil, **)
|
|
13
13
|
params = { sysparm_limit: sysparm_limit, sysparm_offset: sysparm_offset }
|
|
14
14
|
params[:sysparm_query] = sysparm_query if sysparm_query
|
|
15
|
-
resp =
|
|
15
|
+
resp = get('/api/now/table/sys_script', params, **)
|
|
16
16
|
{ business_rules: resp.body['result'] }
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def get_business_rule(sys_id:, **)
|
|
20
|
-
resp =
|
|
20
|
+
resp = get("/api/now/table/sys_script/#{sys_id}", {}, **)
|
|
21
21
|
{ business_rule: resp.body['result'] }
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -34,7 +34,7 @@ module Legion
|
|
|
34
34
|
action_delete: action_delete,
|
|
35
35
|
active: active
|
|
36
36
|
}
|
|
37
|
-
resp =
|
|
37
|
+
resp = post('/api/now/table/sys_script', body, **)
|
|
38
38
|
{ business_rule: resp.body['result'] }
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -44,12 +44,12 @@ module Legion
|
|
|
44
44
|
body[:script] = script if script
|
|
45
45
|
body[:active] = active unless active.nil?
|
|
46
46
|
body[:name] = name if name
|
|
47
|
-
resp =
|
|
47
|
+
resp = patch("/api/now/table/sys_script/#{sys_id}", body, **)
|
|
48
48
|
{ business_rule: resp.body['result'] }
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def delete_business_rule(sys_id:, **)
|
|
52
|
-
resp =
|
|
52
|
+
resp = delete("/api/now/table/sys_script/#{sys_id}", **)
|
|
53
53
|
{ deleted: resp.status == 204, sys_id: sys_id }
|
|
54
54
|
end
|
|
55
55
|
|