wavefront-sdk 4.0.0 → 5.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 578159c0ff0dac09b94caa4dac4e37f03436cb3e2b4cdda54886ce91b9ce4c9b
4
- data.tar.gz: 93eac0630e97d53e3b26d222fd09df61f8cd7966c62e39520dbf27525982cb1b
3
+ metadata.gz: 97f7ce778de07ac5c70631f69d24c84bf9aad453dcf68ee28518f85b6bca7e03
4
+ data.tar.gz: d8b9d202a25cb88c501ac0e4101245c9c582990401b400ef759e057986b67864
5
5
  SHA512:
6
- metadata.gz: e3f09ae6d818b0acc7e81e2e4da585c10a59efba18a4ab373679783d62b5a5ccc300e14435b7cbe8a0f2d64adec361e080c55f089732ffbb6c171f619524440e
7
- data.tar.gz: d558a6d0eafe0d09120317113758ee70807cae035a7e9677a22cf643e537103ff66d671e7e6a031151cd03572f6b62a78e9aa92a86a2fb052f0cb31ba92c4f17
6
+ metadata.gz: 182e6262ddc79f9f88d94505c9b1488dd5f69e19d7e3edfb854ab74378519c83bf60056b709572c21a994c3420802a022eb4a9679395cc7f195e592ca9725c9e
7
+ data.tar.gz: 8a0fb76bc633bff58dbb8957fef6bf18a41f2bcc11baf27465a2a8b267625511bb0817207975f58c32daf9c51d78b4016fd1f155f121e509dc3b30ef016f87f0
@@ -1,7 +1,48 @@
1
1
  ---
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
4
+ TargetRubyVersion: 2.4
5
5
 
6
6
  Metrics/ClassLength:
7
7
  Max: 150
8
+
9
+ # New cops
10
+ #
11
+ Lint/RaiseException:
12
+ Enabled: true
13
+ Lint/StructNewOverride:
14
+ Enabled: true
15
+ Style/ExponentialNotation:
16
+ Enabled: true
17
+ Style/HashEachMethods:
18
+ Enabled: true
19
+ Style/HashTransformKeys:
20
+ Enabled: true
21
+ Style/HashTransformValues:
22
+ Enabled: true
23
+ Layout/EmptyLinesAroundAttributeAccessor:
24
+ Enabled: true
25
+ Layout/SpaceAroundMethodCallOperator:
26
+ Enabled: true
27
+ Style/SlicingWithRange:
28
+ Enabled: true
29
+ Lint/DeprecatedOpenSSLConstant:
30
+ Enabled: true
31
+ Lint/MixedRegexpCaptureTypes:
32
+ Enabled: true
33
+ Style/RedundantRegexpCharacterClass:
34
+ Enabled: true
35
+ Style/RedundantRegexpEscape:
36
+ Enabled: true
37
+ Style/AccessorGrouping:
38
+ Enabled: true
39
+ Style/BisectedAttrAccessor:
40
+ Enabled: true
41
+ Style/RedundantAssignment:
42
+ Enabled: true
43
+ Style/RedundantFetchBlock:
44
+ Enabled: true
45
+
46
+ # Is nothing sacred?
47
+ Layout/LineLength:
48
+ Max: 80
data/HISTORY.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0 (2020-07-08)
4
+ * Remove `Wavefront::UserGroup#grant` and `Wavefront::UserGroup#revoke` as [the
5
+ API paths they used have been
6
+ removed](https://docs.wavefront.com/2020.06.x_release_notes.html#obsolete-and-deprecated-apis).
7
+ (Breaking change.)
8
+ * Remove `Wavefront::MonitoredCluster` class, as it has been removed from the
9
+ public API.
10
+ * Deprecate `Wavefront::User` class, as [the user API is now
11
+ deprecated](https://docs.wavefront.com/2020.06.x_release_notes.html#obsolete-and-deprecated-apis)
12
+ * Add `Wavefront::Role` class, for managing roles.
13
+ * Promote `Wavefront::Spy` class from unstable. It is now an official API.
14
+
3
15
  ## 4.0.0 (2020-02-17)
4
16
  * Drop support for Ruby 2.3. (Breaking change.)
5
17
  * Add `Wavefront::MonitoredCluster` class.
data/README.md CHANGED
@@ -100,10 +100,11 @@ when you ask for a list of objects.
100
100
 
101
101
  You can set an offset and a limit when you list, but setting the
102
102
  limit to the magic value `:all` will return all items, without you
103
- having to deal with pagination.
103
+ having to deal with pagination. When you do that, `offset` is repurposed as
104
+ the number of results fetched with each call to the API.
104
105
 
105
106
  Calling a method with the limit set to `:lazy` returns a lazy
106
- enumerable.
107
+ enumerable. Again, `offset` is the chunk size.
107
108
 
108
109
  ```ruby
109
110
  wf = Wavefront::Alert.new(creds.all)
@@ -44,6 +44,18 @@ module Wavefront
44
44
  api.get(id)
45
45
  end
46
46
 
47
+ # POST /api/v2/account/{id}/addRoles
48
+ # Add specific roles to the account (user or service account)
49
+ # @param id [String] ID of the account
50
+ # @param role_list [Array[String]] list of roles to add
51
+ # @return [Wavefront::Response]
52
+ #
53
+ def add_roles(id, role_list)
54
+ wf_account_id?(id)
55
+ validate_role_list(role_list)
56
+ api.post([id, 'addRoles'].uri_concat, role_list, 'application/json')
57
+ end
58
+
47
59
  # POST /api/v2/account/{id}/addUserGroups
48
60
  # Adds specific user groups to the account (user or service account)
49
61
  # @param id [String] ID of the account
@@ -68,10 +80,22 @@ module Wavefront
68
80
  api.get([id, 'businessFunctions'].uri_concat)
69
81
  end
70
82
 
83
+ # POST /api/v2/account/{id}/removeRoles
84
+ # Removes specific roles from the account (user or service account)
85
+ # @param id [String] ID of the account
86
+ # @param role_list [Array[String]] list of roles to remove
87
+ # @return [Wavefront::Response]
88
+ #
89
+ def remove_roles(id, role_list)
90
+ wf_account_id?(id)
91
+ validate_role_list(role_list)
92
+ api.post([id, 'removeRoles'].uri_concat, role_list, 'application/json')
93
+ end
94
+
71
95
  # POST /api/v2/account/{id}/removeUserGroups
72
96
  # Removes specific user groups from the account (user or service account)
73
97
  # @param id [String] ID of the account
74
- # @param group_list [Array[String]] list of groups to add
98
+ # @param group_list [Array[String]] list of groups to remove
75
99
  # @return [Wavefront::Response]
76
100
  #
77
101
  def remove_user_groups(id, group_list)
@@ -132,7 +156,8 @@ module Wavefront
132
156
  end
133
157
 
134
158
  # POST /api/v2/account/removeingestionpolicies
135
- # Removes ingestion policies from multiple accounts
159
+ # Removes ingestion policies from multiple accounts. The API path says
160
+ # "policies" but I've made the method name "policy" for consistency.
136
161
  # @param policy_id [String] ID of the ingestion policy
137
162
  # @param id_list [Array[String]] list of accounts to be put in policy
138
163
  # @return [Wavefront::Response]
@@ -140,7 +165,7 @@ module Wavefront
140
165
  def remove_ingestion_policy(policy_id, id_list)
141
166
  wf_ingestionpolicy_id?(policy_id)
142
167
  validate_account_list(id_list)
143
- api.post('removeingestionpolicy',
168
+ api.post('removeingestionpolicies',
144
169
  { ingestionPolicyId: policy_id,
145
170
  accounts: id_list },
146
171
  'application/json')
@@ -157,6 +182,78 @@ module Wavefront
157
182
  api.post('deleteAccounts', id_list, 'application/json')
158
183
  end
159
184
 
185
+ # GET /api/v2/account/user
186
+ # Get all user accounts
187
+ # @param offset [Int] user account at which the list begins
188
+ # @param limit [Int] the number of user accounts to return
189
+ # @return [Wavefront::Response]
190
+ #
191
+ def user_list(offset = 0, limit = 100)
192
+ api.get('user', offset: offset, limit: limit)
193
+ end
194
+
195
+ def user_create(body, send_email = false)
196
+ raise ArgumentError unless body.is_a?(Hash)
197
+
198
+ uri = send_email ? "?sendEmail=#{send_email}" : 'user'
199
+
200
+ api.post(uri, body, 'application/json')
201
+ end
202
+
203
+ # POST /api/v2/account/user
204
+ # Creates or updates a user account
205
+ # @param id [String] a Wavefront user ID
206
+ # @param body [Hash] key-value hash of the parameters you wish to change
207
+ # @param modify [true, false] if true, use {#describe()} to get a hash
208
+ # describing the existing object, and modify that with the new body. If
209
+ # false, pass the new body straight through.
210
+ # @return [Wavefront::Response]
211
+ def user_update(body, modify = true)
212
+ raise ArgumentError unless body.is_a?(Hash)
213
+
214
+ return api.post('user', body, 'application/json') unless modify
215
+
216
+ api.post('user',
217
+ hash_for_update(describe(id).response, body),
218
+ 'application/json')
219
+ end
220
+
221
+ # GET /api/v2/account/user/{id}
222
+ # Retrieves a user by identifier (email address)
223
+ # @param id [String] ID of the proxy
224
+ # @return [Wavefront::Response]
225
+ #
226
+ def user_describe(id)
227
+ wf_user_id?(id)
228
+ api.get(['user', id].uri_concat)
229
+ end
230
+
231
+ # POST /api/v2/account/user/invite
232
+ # Invite user accounts with given user groups and permissions.
233
+ # @param body [Array[Hash]] array of hashes, each hash describing a user.
234
+ # See API docs for more details. It is your responsibility to validate
235
+ # the data which describes each user.
236
+ # @return [Wavefront::Response]
237
+ #
238
+ def user_invite(body)
239
+ raise ArgumentError unless body.is_a?(Array)
240
+ raise ArgumentError unless body.first.is_a?(Hash)
241
+
242
+ api.post('user/invite', body, 'application/json')
243
+ end
244
+
245
+ # POST /api/v2/account/validateAccounts
246
+ # Returns valid accounts (users and service accounts), also invalid
247
+ # identifiers from the given list
248
+ # @param id_list [Array[String]] list of user IDs
249
+ # @return [Wavefront::Response]
250
+ #
251
+ def validate_accounts(id_list)
252
+ raise ArgumentError unless id_list.is_a?(Array)
253
+
254
+ api.post('validateAccounts', id_list, 'application/json')
255
+ end
256
+
160
257
  private
161
258
 
162
259
  # @param id [String] ID of the user
@@ -198,5 +295,9 @@ module Wavefront
198
295
  wf_permission?(permission)
199
296
  api.post(['revoke', permission].uri_concat, id_list, 'application/json')
200
297
  end
298
+
299
+ def update_keys
300
+ %i[identifier groups userGroups roles ingestionPolicyId]
301
+ end
201
302
  end
202
303
  end
@@ -35,6 +35,16 @@ module Wavefront
35
35
 
36
36
  list.each { |id| wf_account_id?(id) }
37
37
  end
38
+
39
+ # Validate a list of roles
40
+ # @param list [Array[String]] list of role IDs
41
+ # @raise Wavefront::Exception::InvalidRole
42
+ #
43
+ def validate_role_list(list)
44
+ raise ArgumentError unless list.is_a?(Array)
45
+
46
+ list.each { |id| wf_role_id?(id) }
47
+ end
38
48
  end
39
49
  end
40
50
  end
@@ -38,6 +38,7 @@ module Wavefront
38
38
  class InvalidPoint < RuntimeError; end
39
39
  class InvalidPrefixLength < RuntimeError; end
40
40
  class InvalidProxyId < RuntimeError; end
41
+ class InvalidRoleId < RuntimeError; end
41
42
  class InvalidRelativeTime < RuntimeError; end
42
43
  class InvalidSamplingValue < RuntimeError; end
43
44
  class InvalidSavedSearchEntity < RuntimeError; end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WF_SDK_VERSION = '4.0.0'
3
+ WF_SDK_VERSION = '5.0.0'
4
4
  WF_SDK_LOCATION = Pathname.new(__dir__).parent.parent.parent
@@ -5,23 +5,29 @@ require_relative '../defs/constants'
5
5
  module Wavefront
6
6
  module Paginator
7
7
  #
8
- # Automatically handle pagination. This is an abstract class
9
- # made concrete by an extension for each HTTP request type.
8
+ # Automatically handle pagination. This is an abstract class made concrete
9
+ # by an extension for each HTTP request type.
10
10
  #
11
- # This class and its children do slightly unpleasant things with
12
- # the HTTP request passed to us by the user, extracting and
13
- # changing values in the URI, query string, or POST/PUT body.
14
- # The POST class is particularly onerous.
11
+ # This class and its children do slightly unpleasant things with the HTTP
12
+ # request passed to us by the user, extracting and changing values in the
13
+ # URI, query string, or POST/PUT body. The POST class is particularly
14
+ # onerous.
15
15
  #
16
- # Automatic pagination works by letting the user override the
17
- # limit and offset values in API calls. Setting the limit to
18
- # :all iteratively calls the Wavefront API, returning all
19
- # requested objects an a standard Wavefront::Response wrapper;
20
- # setting limit to :lazy returns a lazy Enumerable. The number
21
- # of objects fetched in each API call, whether eager or lazy
22
- # defaults to PAGE_SIZE, but the user can override that value by
23
- # using the offset argument in conjunction with limit = :lazy |
24
- # :all.
16
+ # Automatic pagination works by letting the user override the limit and
17
+ # offset values in API calls.
18
+ #
19
+ # * Calling with limit = :all iteratively calls the Wavefront API,
20
+ # returning all requested objects in a standard Wavefront::Response
21
+ # wrapper.
22
+ #
23
+ # * Calling with limit = :lazy returns a lazy Enumerable.
24
+ #
25
+ # The number of objects fetched in each API call, eager or lazy, defaults
26
+ # to PAGE_SIZE, but the user can override that value by using the offset
27
+ # argument in conjunction with limit = :lazy | :all.
28
+ #
29
+ # So, for example, to fetch all objects in blocks of ten (which could
30
+ # require a lot of API calls) you would use { limit: :all, offset: 10 }
25
31
  #
26
32
  class Base
27
33
  attr_reader :api_caller, :conn, :method, :args, :page_size,
@@ -43,7 +43,6 @@ module Wavefront
43
43
  options[:s] = parse_time(t_start, true)
44
44
  options[:e] = parse_time(t_end, true) if t_end
45
45
 
46
- options.delete_if { |k, v| v == false && k != :i }
47
46
  api.get('api', options)
48
47
  end
49
48
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/api'
4
+ require_relative 'api_mixins/user'
5
+
6
+ module Wavefront
7
+ #
8
+ # Manage and query Wavefront roles
9
+ #
10
+ class Role < CoreApi
11
+ include Wavefront::Mixin::User
12
+
13
+ def update_keys
14
+ %i[id name description]
15
+ end
16
+
17
+ # GET /api/v2/role
18
+ # Get all roles for a customer
19
+ # @param offset [Int] alert at which the list begins
20
+ # @param limit [Int] the number of alerts to return
21
+ # @return [Wavefront::Response]
22
+ #
23
+ def list(offset = 0, limit = 100)
24
+ api.get('', offset: offset, limit: limit)
25
+ end
26
+
27
+ # POST /api/v2/role
28
+ # Create a specific role
29
+ # @param body [Hash] a hash of parameters describing the role. Please
30
+ # refer to the Wavefront Swagger docs for key:value information
31
+ # @return [Wavefront::Response]
32
+ #
33
+ def create(body)
34
+ raise ArgumentError unless body.is_a?(Hash)
35
+
36
+ api.post('', body, 'application/json')
37
+ end
38
+
39
+ # DELETE /api/v2/role/{id}
40
+ # Delete a specific role
41
+ # @param id [String] ID of the role
42
+ # @return [Wavefront::Response]
43
+ #
44
+ def delete(id)
45
+ wf_role_id?(id)
46
+ api.delete(id)
47
+ end
48
+
49
+ # GET /api/v2/role/{id}
50
+ # Get a specific role
51
+ # @param id [String] ID of the role
52
+ # @return [Wavefront::Response]
53
+ #
54
+ def describe(id)
55
+ wf_role_id?(id)
56
+ api.get(id)
57
+ end
58
+
59
+ # PUT /api/v2/role/{id}
60
+ # Update a specific role
61
+ # @param id [String] role ID
62
+ # @param body [Hash] key-value hash of the parameters you wish to change
63
+ # @param modify [true, false] if true, use {#describe()} to get a hash
64
+ # describing the existing object, and modify that with the new body. If
65
+ # false, pass the new body straight through.
66
+ # @return [Wavefront::Response]
67
+ #
68
+ def update(id, body, modify = true)
69
+ wf_role_id?(id)
70
+ raise ArgumentError unless body.is_a?(Hash)
71
+
72
+ return api.put(id, body, 'application/json') unless modify
73
+
74
+ api.put(id, hash_for_update(describe(id).response, body),
75
+ 'application/json')
76
+ end
77
+
78
+ # POST /api/v2/role/{id}/addAssignees
79
+ # Add multiple users and user groups to a specific role
80
+ # @param id [String] role ID
81
+ # @param assignees [Array[String]] list of roles or accounts to be added
82
+ # @return [Wavefront::Response]
83
+ #
84
+ def add_assignees(id, assignees)
85
+ wf_role_id?(id)
86
+ validate_user_list(assignees)
87
+ api.post([id, 'addAssignees'].uri_concat, assignees, 'application/json')
88
+ end
89
+
90
+ # POST /api/v2/role/{id}/removeAssignees
91
+ # Remove multiple users and user groups from a specific role
92
+ # @param id [String] role ID
93
+ # @param assignees [Array[String]] list of roles or accounts to be removed
94
+ # @return [Wavefront::Response]
95
+ #
96
+ def remove_assignees(id, assignees)
97
+ wf_role_id?(id)
98
+ validate_user_list(assignees)
99
+ api.post([id, 'removeAssignees'].uri_concat,
100
+ assignees,
101
+ 'application/json')
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'defs/constants'
4
+ require_relative 'core/api'
5
+
6
+ module Wavefront
7
+ #
8
+ # Spy on data going into Wavefront
9
+ #
10
+ class Spy < CoreApi
11
+ # GET /api/spy/points
12
+ # Gets new metric data points that are added to existing time series.
13
+ # @param sampling [Float] the amount of points to sample, from 0
14
+ # (none) to 1 (all)
15
+ # @param filter [Hash] with the following keys:
16
+ # :prefix [String] only list points whose metric name begins with this
17
+ # case-sensitive string
18
+ # :host [Array] only list points if source name begins with this
19
+ # case-sensitive string
20
+ # :tag_key [String,Array[String]] only list points with one or more of
21
+ # the given points tags
22
+ # @param options [Hash] with the following keys
23
+ # :timestamp [Boolean] prefix each block of streamed data with a
24
+ # timestamp
25
+ # :timeout [Integer] how many seconds to run the spy. After this time
26
+ # the method returns
27
+ # @raise Wavefront::Exception::InvalidSamplingValue
28
+ # @return [Nil]
29
+ #
30
+ def points(sampling = 0.01, filters = {}, options = {})
31
+ wf_sampling_value?(sampling)
32
+ api.get_stream('points', points_filter(sampling, filters), options)
33
+ end
34
+
35
+ # GET /api/spy/histograms
36
+ # Gets new histograms that are added to existing time series.
37
+ # @param sampling [Float] see #points
38
+ # @param filter [Hash] see #points
39
+ # @param options [Hash] see #points
40
+ # @raise Wavefront::Exception::InvalidSamplingValue
41
+ # @return [Nil]
42
+ #
43
+ def histograms(sampling = 0.01, filters = {}, options = {})
44
+ wf_sampling_value?(sampling)
45
+ api.get_stream('histograms',
46
+ histograms_filter(sampling, filters),
47
+ options)
48
+ end
49
+
50
+ # GET /api/spy/spans
51
+ # Gets new spans with existing source names and span tags.
52
+ # @param sampling [Float] see #points
53
+ # @param filter [Hash] see #points
54
+ # @param options [Hash] see #points
55
+ # @raise Wavefront::Exception::InvalidSamplingValue
56
+ # @return [Nil]
57
+ #
58
+ def spans(sampling = 0.01, filters = {}, options = {})
59
+ wf_sampling_value?(sampling)
60
+ api.get_stream('spans', spans_filter(sampling, filters), options)
61
+ end
62
+
63
+ # GET /api/spy/ids
64
+ # Gets newly allocated IDs that correspond to new metric names, source
65
+ # names, point tags, or span tags. A new ID generally indicates that a
66
+ # new time series has been introduced.
67
+ # @param sampling [Float] see #points
68
+ # @param filter [Hash] with keys:
69
+ # :prefix [String] only list assignments whose metric name begins with
70
+ # this case-sensitive string
71
+ # :type [String] one of METRIC, SPAN, HOST or STRING
72
+ # @param options [Hash] see #points
73
+ #
74
+ def ids(sampling = 0.01, filters = {}, options = {})
75
+ wf_sampling_value?(sampling)
76
+ api.get_stream('ids', ids_filter(sampling, filters), options)
77
+ end
78
+
79
+ def api_path
80
+ '/api/spy'
81
+ end
82
+
83
+ # We have to try to make the response we get from the API look
84
+ # like the one we get from the public API. To begin with, it's
85
+ # nothing like it.
86
+ #
87
+ # This method must be public because a #respond_to? looks for
88
+ # it.
89
+ #
90
+ def _response_shim(resp, status)
91
+ { response: parse_response(resp),
92
+ status: { result: status == 200 ? 'OK' : 'ERROR',
93
+ message: extract_api_message(status, resp),
94
+ code: status } }.to_json
95
+ end
96
+
97
+ private
98
+
99
+ def points_filter(sampling, filters)
100
+ { metric: filters.fetch(:prefix, nil),
101
+ host: filters.fetch(:host, nil),
102
+ sampling: sampling,
103
+ pointTagKey: filters.fetch(:tag_key, nil) }.compact
104
+ end
105
+
106
+ def histograms_filter(sampling, filters)
107
+ { histogram: filters.fetch(:prefix, nil),
108
+ host: filters.fetch(:host, nil),
109
+ sampling: sampling,
110
+ histogramTagKey: filters.fetch(:tag_key, nil) }.compact
111
+ end
112
+
113
+ def spans_filter(sampling, filters)
114
+ { name: filters.fetch(:prefix, nil),
115
+ host: filters.fetch(:host, nil),
116
+ sampling: sampling,
117
+ spanTagKey: filters.fetch(:tag_key, nil) }.compact
118
+ end
119
+
120
+ def ids_filter(sampling, filters)
121
+ { name: filters.fetch(:prefix, nil),
122
+ type: filters.fetch(:type, nil),
123
+ sampling: sampling }.compact
124
+ end
125
+ end
126
+ end