wavefront-sdk 3.3.2 → 3.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +42 -35
- data/README.md +5 -5
- data/lib/wavefront-sdk/alert.rb +2 -0
- data/lib/wavefront-sdk/core/api_caller.rb +6 -3
- data/lib/wavefront-sdk/defs/version.rb +2 -2
- data/lib/wavefront-sdk/derivedmetric.rb +7 -0
- data/lib/wavefront-sdk/externallink.rb +2 -2
- data/lib/wavefront-sdk/maintenancewindow.rb +6 -2
- data/lib/wavefront-sdk/notificant.rb +7 -0
- data/lib/wavefront-sdk/paginator/base.rb +8 -0
- data/lib/wavefront-sdk/search.rb +11 -2
- data/lib/wavefront-sdk/user.rb +39 -8
- data/lib/wavefront-sdk/webhook.rb +1 -1
- data/spec/constants.rb +30 -0
- data/spec/spec_helper.rb +12 -237
- data/spec/support/bad_mocket.rb +15 -0
- data/spec/support/hash.rb +9 -0
- data/spec/support/minitest_assertions.rb +110 -0
- data/spec/support/mocket.rb +19 -0
- data/spec/test_mixins/acl.rb +78 -0
- data/spec/test_mixins/general.rb +120 -0
- data/spec/test_mixins/tag.rb +55 -0
- data/spec/test_mixins/update_keys.rb +11 -0
- data/spec/wavefront-sdk/alert_spec.rb +88 -136
- data/spec/wavefront-sdk/apitoken_spec.rb +26 -13
- data/spec/wavefront-sdk/cloudintegration_spec.rb +42 -44
- data/spec/wavefront-sdk/dashboard_spec.rb +53 -72
- data/spec/wavefront-sdk/derivedmetric_spec.rb +23 -49
- data/spec/wavefront-sdk/distribution_spec.rb +14 -14
- data/spec/wavefront-sdk/event_spec.rb +39 -48
- data/spec/wavefront-sdk/externallink_spec.rb +19 -50
- data/spec/wavefront-sdk/integration_spec.rb +33 -38
- data/spec/wavefront-sdk/maintenancewindow_spec.rb +18 -33
- data/spec/wavefront-sdk/message_spec.rb +19 -4
- data/spec/wavefront-sdk/metric_spec.rb +13 -9
- data/spec/wavefront-sdk/notificant_spec.rb +16 -15
- data/spec/wavefront-sdk/proxy_spec.rb +20 -25
- data/spec/wavefront-sdk/query_spec.rb +50 -24
- data/spec/wavefront-sdk/report_spec.rb +3 -6
- data/spec/wavefront-sdk/resources/user_responses/add_user_groups.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/create.json +28 -0
- data/spec/wavefront-sdk/resources/user_responses/delete_multiple.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/describe.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/grant.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/list.json +1 -0
- data/spec/wavefront-sdk/savedsearch_spec.rb +41 -35
- data/spec/wavefront-sdk/search_spec.rb +35 -29
- data/spec/wavefront-sdk/settings_spec.rb +18 -12
- data/spec/wavefront-sdk/source_spec.rb +29 -32
- data/spec/wavefront-sdk/user_spec.rb +101 -74
- data/spec/wavefront-sdk/usergroup_spec.rb +56 -67
- data/spec/wavefront-sdk/webhook_spec.rb +22 -34
- data/spec/wavefront-sdk/write_spec.rb +2 -0
- data/spec/wavefront-sdk/writers/core_spec.rb +2 -0
- data/spec/wavefront-sdk/writers/summary_spec.rb +2 -0
- data/wavefront-sdk.gemspec +5 -5
- metadata +44 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a664693c583158575cad85b45877d407b0d319e1d6d540b2cc253d3d65907c0c
|
4
|
+
data.tar.gz: f0407b9b17cd69e79a7206c6224e749f3ad60027410d03e997fb5dd60aa1276c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff1bd8a1f5d9a7e57bf04d74ad42e9a168ca285e5eb58e4048089768f88ed44e88814744295bbc63541a27f945d99b246fa063f69f2e0495a1bf8bac9dbf28b9
|
7
|
+
data.tar.gz: f0f18d99096549065b6eaa1b1c410d62d011fdb81f1c07756076c0aaca6b6261621a0cd9403ab76d1e655dcab1ef44bdb9e3edbae23d8bade01ce02868a7ac42
|
data/HISTORY.md
CHANGED
@@ -1,35 +1,42 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## 3.3.
|
4
|
-
*
|
3
|
+
## 3.3.3 (2019-09-10)
|
4
|
+
* Fix slightly misleading verbose message when using recursive or
|
5
|
+
lazy calls
|
6
|
+
* Fix bug where `Alert#versions` would fault on a noop.
|
7
|
+
* Make `Search` work correctly with API classes which use cursors.
|
8
|
+
* Improve user response shim, and its tests.
|
5
9
|
|
6
|
-
## 3.3.
|
10
|
+
## 3.3.2 (2019-05-24)
|
11
|
+
* Don't report `moreItems` as true at the end of a recursive GET.
|
12
|
+
|
13
|
+
## 3.3.1 (2019-05-10)
|
7
14
|
* Better handling of query errors.
|
8
15
|
|
9
|
-
## 3.3.0 (09
|
16
|
+
## 3.3.0 (2019-05-09)
|
10
17
|
* Reflect the way the API ACL format has changed.
|
11
18
|
|
12
|
-
## 3.2.0 (01
|
19
|
+
## 3.2.0 (2019-05-01)
|
13
20
|
* Add support for new `apitoken` path.
|
14
21
|
* Add support for alert ACLs
|
15
22
|
* Tag and ACL methods have been broken out into mixins which are
|
16
23
|
automatically included by classes which support them
|
17
24
|
|
18
|
-
## 3.1.0 (23
|
25
|
+
## 3.1.0 (2019-04-23)
|
19
26
|
* When using `Wavefront::Write`, large numbers of points are written
|
20
27
|
in chunks, rather than all at once. The chunk size can be set by
|
21
28
|
the user when instantiating the class.
|
22
29
|
|
23
|
-
## 3.0.2 (06
|
30
|
+
## 3.0.2 (2019-04-06)
|
24
31
|
* Better handling of non-existent or malformed config files.
|
25
32
|
* Look for `~/.wavefront.conf` as well as `~/.wavefront`. Both these
|
26
33
|
fixes are related to finding out that other Wavefront tooling
|
27
34
|
creates `~/.wavefront` as a directory.
|
28
35
|
|
29
|
-
## 3.0.1 (05
|
36
|
+
## 3.0.1 (2019-04-05)
|
30
37
|
* User IDs do not have to be e-mail addresses.
|
31
38
|
|
32
|
-
## 3.0.0 (23
|
39
|
+
## 3.0.0 (2019-03-23)
|
33
40
|
* Drop support for Ruby 2.2. (Potentially breaking change.)
|
34
41
|
* Add `Wavefront::Settings` class to cover new `settings` API
|
35
42
|
endpoint.
|
@@ -39,14 +46,14 @@
|
|
39
46
|
* Add `sort_field` to `Wavefront::Search` options. Lets user select
|
40
47
|
the field on which to sort results.
|
41
48
|
|
42
|
-
## 2.5.1 (06
|
49
|
+
## 2.5.1 (2019-03-06)
|
43
50
|
* Fix messy handling of raw query errors.
|
44
51
|
|
45
|
-
## 2.5.0 (21
|
52
|
+
## 2.5.0 (2019-02-21)
|
46
53
|
* New `Wavefront::UserGroup` class, for new API `UserGroup` feature.
|
47
54
|
* Extended `Wavefront::User` to cover new API methods.
|
48
55
|
|
49
|
-
## 2.4.0 (28
|
56
|
+
## 2.4.0 (2019-01-28)
|
50
57
|
* New `Wavefront::MetricHelper` class creates and in-memory buffer
|
51
58
|
to which you can instantaneously add metrics, flushing it to
|
52
59
|
Wavefront when appropriate. All `Writer` types are supported.
|
@@ -60,16 +67,16 @@
|
|
60
67
|
* Improve `README` instructions on writing metrics.
|
61
68
|
* Support Ruby 2.6.
|
62
69
|
|
63
|
-
## 2.3.0 (06
|
70
|
+
## 2.3.0 (2019-01-06)
|
64
71
|
* When sending points via the API, send bundles of up to 100 points
|
65
72
|
with each `POST`, rather than a call per point.
|
66
73
|
|
67
|
-
## 2.2.1 (20
|
74
|
+
## 2.2.1 (2018-12-20)
|
68
75
|
* Fix typo in `Wavefront::Alert#affected_by_maintenance` method
|
69
76
|
name.
|
70
77
|
* Full `Wavefront::Alert` test coverage.
|
71
78
|
|
72
|
-
## 2.2.0 (15
|
79
|
+
## 2.2.0 (2018-12-15)
|
73
80
|
* New methods to cover new API paths.
|
74
81
|
* `Wavefront::Alert#install`,
|
75
82
|
* `Wavefront::Alert#uninstall`,
|
@@ -81,20 +88,20 @@
|
|
81
88
|
* `Wavefront::Integration#uninstall_all_alerts`
|
82
89
|
* `Wavefront::Integration#installed`
|
83
90
|
|
84
|
-
## 2.1.0 (25
|
91
|
+
## 2.1.0 (2018-11-25)
|
85
92
|
* New `unix` writer lets you write points to a local Unix datagram
|
86
93
|
socket.
|
87
94
|
|
88
|
-
## 2.0.3 (23
|
95
|
+
## 2.0.3 (2018-10-23)
|
89
96
|
* Remove unnecessarily strict argument check on `event#list`.
|
90
97
|
|
91
|
-
## 2.0.2 (22
|
98
|
+
## 2.0.2 (2018-10-22)
|
92
99
|
* Bugfix
|
93
100
|
|
94
|
-
## 2.0.1 (22
|
101
|
+
## 2.0.1 (2018-10-22)
|
95
102
|
* Bugfix on response types.
|
96
103
|
|
97
|
-
## 2.0.0 (20
|
104
|
+
## 2.0.0 (2018-10-20)
|
98
105
|
* Remove `#everything` method from all classes. (Breaking change.)
|
99
106
|
* Calling any method which takes the `limit` argument with `limit`
|
100
107
|
set to `:all` will automatically handle pagination, fetching all
|
@@ -137,36 +144,36 @@
|
|
137
144
|
* Make `Wavefront::User` return a response object containing an
|
138
145
|
`items` element, like every other class.
|
139
146
|
|
140
|
-
## 1.6.2 (22
|
147
|
+
## 1.6.2 (2018-08-22)
|
141
148
|
* Drop log priority of write class messages.
|
142
149
|
|
143
|
-
## 1.6.1 (22
|
150
|
+
## 1.6.1 (2018-08-22)
|
144
151
|
* Fix Ruby 2.2 bugs
|
145
152
|
* Improve unit test separation
|
146
153
|
* Allow updating of all external link parameters
|
147
154
|
|
148
|
-
## 1.6.0 (07
|
155
|
+
## 1.6.0 (2018-08-07)
|
149
156
|
* Improve validation of point tags.
|
150
157
|
* Break extensions to standard library out into their own files.
|
151
158
|
* Improve README.
|
152
159
|
|
153
|
-
## 1.5.0 (25
|
160
|
+
## 1.5.0 (2018-06-25)
|
154
161
|
* Add [derived
|
155
162
|
metric](https://docs.wavefront.com/derived_metrics.html) support.
|
156
163
|
* Add this changelog.
|
157
164
|
|
158
|
-
## 1.4.0 (10
|
165
|
+
## 1.4.0 (2018-04-10)
|
159
166
|
* Add support for [direct
|
160
167
|
ingestion](https://docs.wavefront.com/direct_ingestion.html).
|
161
168
|
|
162
|
-
## 1.3.2 (03
|
169
|
+
## 1.3.2 (2018-04-03)
|
163
170
|
* Fix regression in write class.
|
164
171
|
|
165
|
-
## 1.3.1 (03
|
172
|
+
## 1.3.1 (2018-04-03)
|
166
173
|
* Fix Ruby 2.2 support.
|
167
174
|
* Code tidy and linting improvements.
|
168
175
|
|
169
|
-
## 1.3.0 (29
|
176
|
+
## 1.3.0 (2018-03-29)
|
170
177
|
* Add support for delta metrics.
|
171
178
|
* Add automatic pagination support for long lists of objects.
|
172
179
|
Such lists can be treated as Ruby enumerables.
|
@@ -176,27 +183,27 @@
|
|
176
183
|
* Update dependencies.
|
177
184
|
* Support Ruby 2.5.
|
178
185
|
|
179
|
-
## 1.2.1 (12
|
186
|
+
## 1.2.1 (2017-10-12)
|
180
187
|
* Fix bug in relative time support.
|
181
188
|
* Fix Ruby 2.4 support.
|
182
189
|
|
183
|
-
## 1.2.0 (12
|
190
|
+
## 1.2.0 (2017-10-12)
|
184
191
|
* Support relative times through mixin methods.
|
185
192
|
|
186
|
-
## 1.1.0 (09
|
193
|
+
## 1.1.0 (2017-10-09)
|
187
194
|
* Add support for notificant (alert target) API path.
|
188
195
|
* Add support for integration API path.
|
189
196
|
* Support new source description set/delete API endpoint.
|
190
197
|
|
191
|
-
## 1.0.3 (20
|
198
|
+
## 1.0.3 (2017-09-20)
|
192
199
|
* Gracefully handle tags with `nil` values.
|
193
200
|
* Bump dependencies.
|
194
201
|
|
195
|
-
## 1.0.2 (04
|
202
|
+
## 1.0.2 (2017-08-04)
|
196
203
|
* Maintenance window bugfixes.
|
197
204
|
|
198
|
-
## 1.0.1 (31
|
205
|
+
## 1.0.1 (2017-07-31)
|
199
206
|
* Fix message ID validator.
|
200
207
|
|
201
|
-
## 1.0.0 (11
|
208
|
+
## 1.0.0 (2017-06-11)
|
202
209
|
First official release.
|
data/README.md
CHANGED
@@ -116,11 +116,6 @@ wf.list(99, :lazy).each { |alert| puts alert.name }
|
|
116
116
|
# ...
|
117
117
|
```
|
118
118
|
|
119
|
-
We can easily write queries. Let's retrieve a timeseries over the
|
120
|
-
last 10 minutes, with one minute bucket granularity. We will
|
121
|
-
describe the time as a Ruby object, but could also use an epoch
|
122
|
-
timestamp. The SDK happily converts between the two.
|
123
|
-
|
124
119
|
### Credentials
|
125
120
|
|
126
121
|
The SDK provides a helper class for extracting credentials from a
|
@@ -148,6 +143,11 @@ wf = Wavefront::Write.new(c.all)
|
|
148
143
|
|
149
144
|
### Queries
|
150
145
|
|
146
|
+
We can easily write queries. Let's retrieve a timeseries over the
|
147
|
+
last 10 minutes, with one minute bucket granularity. We will
|
148
|
+
describe the time as a Ruby object, but could also use an epoch
|
149
|
+
timestamp. The SDK happily converts between the two.
|
150
|
+
|
151
151
|
```ruby
|
152
152
|
require 'wavefront-sdk/query'
|
153
153
|
|
data/lib/wavefront-sdk/alert.rb
CHANGED
@@ -130,6 +130,8 @@ module Wavefront
|
|
130
130
|
# If we need to massage a raw response to fit what the
|
131
131
|
# Wavefront::Response class expects (I'm looking at you,
|
132
132
|
# 'User'), a class can provide a {#response_shim} method.
|
133
|
+
# @param resp [Faraday::Response]
|
134
|
+
# @return [String] body of response (JSON)
|
133
135
|
#
|
134
136
|
def respond(resp)
|
135
137
|
body = if calling_class.respond_to?(:response_shim)
|
@@ -146,6 +148,7 @@ module Wavefront
|
|
146
148
|
#
|
147
149
|
def verbosity(conn, method, *args)
|
148
150
|
return unless noop || verbose
|
151
|
+
|
149
152
|
log format('uri: %s %s', method.upcase, conn.url_prefix)
|
150
153
|
|
151
154
|
return unless args.last && !args.last.empty?
|
@@ -168,9 +171,6 @@ module Wavefront
|
|
168
171
|
# endpoint
|
169
172
|
#
|
170
173
|
def make_call(conn, method, *args)
|
171
|
-
verbosity(conn, method, *args)
|
172
|
-
return if noop
|
173
|
-
|
174
174
|
paginator = paginator_class(method).new(self, conn, method, *args)
|
175
175
|
|
176
176
|
case paginator.initial_limit
|
@@ -184,6 +184,9 @@ module Wavefront
|
|
184
184
|
end
|
185
185
|
|
186
186
|
def make_single_call(conn, method, *args)
|
187
|
+
verbosity(conn, method, *args)
|
188
|
+
return if noop
|
189
|
+
|
187
190
|
pp args if debug
|
188
191
|
|
189
192
|
resp = conn.public_send(method, *args)
|
@@ -10,8 +10,8 @@ module Wavefront
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def update_keys
|
13
|
-
%i[name template description metricFilterRegex
|
14
|
-
pointTagFilterRegexes]
|
13
|
+
%i[id name template description metricFilterRegex
|
14
|
+
sourceFilterRegex pointTagFilterRegexes]
|
15
15
|
end
|
16
16
|
|
17
17
|
# GET /api/v2/extlink
|
@@ -6,7 +6,7 @@ module Wavefront
|
|
6
6
|
#
|
7
7
|
class MaintenanceWindow < CoreApi
|
8
8
|
def update_keys
|
9
|
-
%i[reason title startTimeInSeconds endTimeInSeconds
|
9
|
+
%i[id reason title startTimeInSeconds endTimeInSeconds
|
10
10
|
relevantCustomerTags relevantHostTags relevantHostNames]
|
11
11
|
end
|
12
12
|
|
@@ -92,7 +92,11 @@ module Wavefront
|
|
92
92
|
def pending(hours = 24)
|
93
93
|
cutoff = Time.now.to_i + hours * 3600
|
94
94
|
|
95
|
-
windows_in_state(:pending)
|
95
|
+
ret = windows_in_state(:pending)
|
96
|
+
|
97
|
+
return if opts[:noop]
|
98
|
+
|
99
|
+
ret.tap do |r|
|
96
100
|
r.response.items.delete_if { |w| w.startTimeInSeconds > cutoff }
|
97
101
|
end
|
98
102
|
end
|
@@ -79,5 +79,12 @@ module Wavefront
|
|
79
79
|
wf_notificant_id?(id)
|
80
80
|
api.post(['test', id].uri_concat, nil)
|
81
81
|
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def update_keys
|
86
|
+
%i[id contentType method description title template triggers
|
87
|
+
recipient customHttpHeaders emailSubject isHtmlContent]
|
88
|
+
end
|
82
89
|
end
|
83
90
|
end
|
@@ -100,6 +100,10 @@ module Wavefront
|
|
100
100
|
def make_recursive_call
|
101
101
|
offset = 0
|
102
102
|
p_args = set_pagination(offset, page_size, args)
|
103
|
+
api_caller.verbosity(conn, method, *p_args)
|
104
|
+
|
105
|
+
return if api_caller.opts[:noop]
|
106
|
+
|
103
107
|
ret = api_caller.respond(conn.public_send(method, *p_args))
|
104
108
|
|
105
109
|
return ret unless ret.more_items?
|
@@ -138,6 +142,10 @@ module Wavefront
|
|
138
142
|
offset = 0
|
139
143
|
p_args = set_pagination(offset, page_size, args)
|
140
144
|
|
145
|
+
api_caller.verbosity(conn, method, *p_args)
|
146
|
+
|
147
|
+
return if api_caller.opts[:noop]
|
148
|
+
|
141
149
|
Enumerator.new do |y|
|
142
150
|
loop do
|
143
151
|
offset += page_size
|
data/lib/wavefront-sdk/search.rb
CHANGED
@@ -45,8 +45,7 @@ module Wavefront
|
|
45
45
|
# Build a query body
|
46
46
|
#
|
47
47
|
def body(query, options)
|
48
|
-
ret =
|
49
|
-
offset: options[:offset] || 0 }
|
48
|
+
ret = query_limits(options)
|
50
49
|
|
51
50
|
if query && !query.empty?
|
52
51
|
ret[:query] = [query].flatten.map do |q|
|
@@ -59,6 +58,16 @@ module Wavefront
|
|
59
58
|
ret
|
60
59
|
end
|
61
60
|
|
61
|
+
def query_limits(options)
|
62
|
+
{ limit: options[:limit] || 10 }.tap do |ret|
|
63
|
+
if options[:cursor]
|
64
|
+
ret[:cursor] = options[:cursor]
|
65
|
+
else
|
66
|
+
ret[:offset] = options[:offset] || 0
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
62
71
|
def sort_field(options, query)
|
63
72
|
field = options[:sort_field] || [query].flatten.first[:key]
|
64
73
|
|
data/lib/wavefront-sdk/user.rb
CHANGED
@@ -196,18 +196,38 @@ module Wavefront
|
|
196
196
|
# Fake a response which looks like we get from all the other
|
197
197
|
# paths. I'm expecting the user response model to be made
|
198
198
|
# consistent with others in the future.
|
199
|
+
# @return [String] of JSON
|
199
200
|
#
|
200
201
|
def response_shim(body, status)
|
201
|
-
|
202
|
+
body_obj = JSON.parse(body, symbolize_names: true)
|
202
203
|
|
203
|
-
|
204
|
+
if body_obj.is_a?(Hash) && body_obj.key?(:status)
|
205
|
+
if response_looks_right?(body_obj)
|
206
|
+
body
|
207
|
+
else
|
208
|
+
itemize_response(body_obj)
|
209
|
+
end
|
210
|
+
else
|
211
|
+
construct_response(body_obj, status)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def itemize_response(body_obj)
|
216
|
+
{ status: body_obj[:status],
|
217
|
+
response: { items: [body_obj[:response]].flatten } }.to_json
|
218
|
+
end
|
219
|
+
|
220
|
+
# Construct a response almost from scratch. Used for 'list', among others.
|
221
|
+
#
|
222
|
+
def construct_response(body_obj, status)
|
223
|
+
{ status: { result: status.to_s.start_with?('2') ? 'OK' : 'ERROR',
|
224
|
+
message: extract_api_message(status, body_obj),
|
225
|
+
code: status },
|
226
|
+
response: { items: [body_obj].flatten,
|
204
227
|
offset: 0,
|
205
|
-
limit:
|
206
|
-
totalItems:
|
207
|
-
|
208
|
-
status: { result: status == 200 ? 'OK' : 'ERROR',
|
209
|
-
message: extract_api_message(status, items),
|
210
|
-
code: status } }.to_json
|
228
|
+
limit: body_obj.size,
|
229
|
+
totalItems: body_obj.size,
|
230
|
+
moreItems: false } }.to_json
|
211
231
|
end
|
212
232
|
|
213
233
|
# the user API class does not support pagination. Be up-front
|
@@ -219,9 +239,20 @@ module Wavefront
|
|
219
239
|
|
220
240
|
private
|
221
241
|
|
242
|
+
def response_looks_right?(body_obj)
|
243
|
+
body_obj.key?(:response) &&
|
244
|
+
body_obj[:response].is_a?(Hash) &&
|
245
|
+
body_obj[:response].key?(:items) &&
|
246
|
+
body_obj[:response][:items].is_a?(Array)
|
247
|
+
end
|
248
|
+
|
222
249
|
def extract_api_message(status, items)
|
223
250
|
return '' if status < 300
|
224
251
|
items.fetch(:message, 'no message from API')
|
225
252
|
end
|
253
|
+
|
254
|
+
def update_keys
|
255
|
+
%i[identifier groups userGroups]
|
256
|
+
end
|
226
257
|
end
|
227
258
|
end
|