wavefront-sdk 3.6.1 → 5.0.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +43 -2
  3. data/.travis.yml +0 -1
  4. data/HISTORY.md +33 -0
  5. data/README.md +4 -3
  6. data/lib/wavefront-sdk/account.rb +303 -0
  7. data/lib/wavefront-sdk/api_mixins/user.rb +20 -0
  8. data/lib/wavefront-sdk/core/api_caller.rb +50 -7
  9. data/lib/wavefront-sdk/core/exception.rb +6 -0
  10. data/lib/wavefront-sdk/core/response.rb +2 -1
  11. data/lib/wavefront-sdk/defs/version.rb +1 -3
  12. data/lib/wavefront-sdk/ingestionpolicy.rb +85 -0
  13. data/lib/wavefront-sdk/paginator/base.rb +21 -15
  14. data/lib/wavefront-sdk/query.rb +0 -1
  15. data/lib/wavefront-sdk/role.rb +128 -0
  16. data/lib/wavefront-sdk/spy.rb +126 -0
  17. data/lib/wavefront-sdk/stdlib/array.rb +1 -1
  18. data/lib/wavefront-sdk/stdlib/time.rb +13 -0
  19. data/lib/wavefront-sdk/unstable/README.md +4 -0
  20. data/lib/wavefront-sdk/unstable/chart.rb +90 -0
  21. data/lib/wavefront-sdk/unstable/unstable.rb +9 -0
  22. data/lib/wavefront-sdk/usage.rb +31 -0
  23. data/lib/wavefront-sdk/user.rb +41 -0
  24. data/lib/wavefront-sdk/usergroup.rb +17 -16
  25. data/lib/wavefront-sdk/validators.rb +65 -7
  26. data/lib/wavefront-sdk/write.rb +13 -3
  27. data/spec/.rubocop.yml +42 -1
  28. data/spec/spec_helper.rb +4 -0
  29. data/spec/support/minitest_assertions.rb +4 -4
  30. data/spec/wavefront-sdk/account_spec.rb +238 -0
  31. data/spec/wavefront-sdk/core/api_caller_spec.rb +43 -0
  32. data/spec/wavefront-sdk/ingestionpolicy_spec.rb +43 -0
  33. data/spec/wavefront-sdk/metric_helper_spec.rb +1 -1
  34. data/spec/wavefront-sdk/role_spec.rb +96 -0
  35. data/spec/wavefront-sdk/spy_spec.rb +113 -0
  36. data/spec/wavefront-sdk/unstable/chart_spec.rb +39 -0
  37. data/spec/wavefront-sdk/usage_spec.rb +33 -0
  38. data/spec/wavefront-sdk/user_spec.rb +20 -0
  39. data/spec/wavefront-sdk/usergroup_spec.rb +21 -11
  40. data/spec/wavefront-sdk/validators_spec.rb +52 -6
  41. data/wavefront-sdk.gemspec +4 -4
  42. metadata +30 -9
@@ -11,6 +11,6 @@ class Array
11
11
  # @return [String] a URI path
12
12
  #
13
13
  def uri_concat
14
- join('/').squeeze('/').sub(%r{\/$}, '').sub(%r{\/\?}, '?')
14
+ join('/').squeeze('/').sub(%r{/$}, '').sub(%r{/\?}, '?')
15
15
  end
16
16
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Extensions to the stdlib Time class
4
+ #
5
+ class Time
6
+ #
7
+ # The real hi-res time. See
8
+ # https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
9
+ #
10
+ def self.right_now
11
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ The classes in here use undocumented APIs. They are thus subject to
2
+ change or revocation at any time.
3
+
4
+ Use them at your own risk.
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../defs/constants'
4
+ require_relative '../core/api'
5
+
6
+ module Wavefront
7
+ module Unstable
8
+ #
9
+ # This is an unstable class. Please refer to README.md.
10
+ #
11
+ class Chart < CoreApi
12
+ def all_metrics
13
+ metrics_under('')
14
+ end
15
+
16
+ # Gets a list of metrics under the given path. This must be done via
17
+ # recursive calls to the API, so calls can take a while. If you ask for
18
+ # all your metrics, expect to be waiting some time.
19
+ #
20
+ # @return [Wavefront::Response]
21
+ #
22
+ # rubocop:disable Metrics/MethodLength
23
+ # rubocop:disable Metrics/AbcSize
24
+ def metrics_under(path, cursor = nil, limit = 100)
25
+ resp = api.get('metrics/all',
26
+ { trie: true, q: path, p: cursor, l: limit }.compact)
27
+
28
+ return resp unless resp.ok?
29
+
30
+ metrics = resp.response.items
31
+
32
+ metrics.each do |m|
33
+ if m.end_with?('.')
34
+ metrics += metrics_under(m).response.items
35
+ metrics.delete(m)
36
+ end
37
+ end
38
+
39
+ # resp.more_items? doesn't work: we don't get that from this API
40
+
41
+ if metrics.size == limit
42
+ metrics += metrics_under(path, metrics.last, limit).response.items
43
+ end
44
+
45
+ resp.response.items = metrics.sort
46
+ resp
47
+ end
48
+ # rubocop:enable Metrics/MethodLength
49
+ # rubocop:enable Metrics/AbcSize
50
+
51
+ def api_path
52
+ '/chart'
53
+ end
54
+
55
+ # We have to try to make the response we get from the API look
56
+ # like the one we get from the public API. To begin with, it's
57
+ # nothing like it.
58
+ #
59
+ # This method must be public because a #respond_to? looks for
60
+ # it.
61
+ #
62
+ def response_shim(resp, status)
63
+ { response: parse_response(resp),
64
+ status: { result: status == 200 ? 'OK' : 'ERROR',
65
+ message: extract_api_message(status, resp),
66
+ code: status } }.to_json
67
+ end
68
+
69
+ private
70
+
71
+ def parse_response(resp)
72
+ metrics = JSON.parse(resp, symbolize_names: true)[:metrics]
73
+
74
+ { items: metrics,
75
+ offset: 0,
76
+ limit: metrics.size,
77
+ totalItems: metrics.size,
78
+ moreItems: false }
79
+ rescue JSON::ParserError
80
+ nil
81
+ end
82
+
83
+ def extract_api_message(_status, resp)
84
+ resp.match(/^message='(.*)'/)[1]
85
+ rescue NoMethodError
86
+ ''
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wavefront
4
+ #
5
+ # Placeholder for unstable API classes
6
+ #
7
+ module Unstable
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/api'
4
+
5
+ module Wavefront
6
+ #
7
+ # View and manage Wavefront usage.
8
+ #
9
+ # Ingestion policy shares this API path, but has its own SDK class.
10
+ #
11
+ class Usage < CoreApi
12
+ # GET /api/v2/usage/exportcsv
13
+ # Export a CSV report
14
+ #
15
+ # @param t_start [Integer] start time in epoch seconds
16
+ # @param t_end [Integer] end time in epoch seconds, nil being "now".
17
+ # @return [Wavefront::Response]
18
+ #
19
+ def export_csv(t_start, t_end = nil)
20
+ wf_epoch?(t_start)
21
+ args = { startTime: t_start }
22
+
23
+ if t_end
24
+ wf_epoch?(t_end)
25
+ args[:endTime] = t_end
26
+ end
27
+
28
+ api.get('exportcsv', args)
29
+ end
30
+ end
31
+ end
@@ -4,16 +4,33 @@ require_relative 'core/api'
4
4
  require_relative 'api_mixins/user'
5
5
 
6
6
  module Wavefront
7
+ #
8
+ # In line with the API changes in the 2020-06 release of Wavefront, this
9
+ # class has been deprecated.
10
+ #
11
+ # Please use Wavefront::Account to manage users.
12
+ #
13
+ # https://docs.wavefront.com/2020.06.x_release_notes.html
7
14
  #
8
15
  # Manage and query Wavefront users
9
16
  #
10
17
  class User < CoreApi
11
18
  include Wavefront::Mixin::User
12
19
 
20
+ def deprecation_warning
21
+ logger.log('Wavefront::User is deprecated and will be removed from the ' \
22
+ 'next major release. Please use Wavefront::Account.', :warn)
23
+ end
24
+
25
+ def post_initialize(_creds, _opts)
26
+ deprecation_warning
27
+ end
28
+
13
29
  # GET /api/v2/user
14
30
  # Get all users.
15
31
  #
16
32
  def list
33
+ deprecation_warning
17
34
  api.get('')
18
35
  end
19
36
 
@@ -26,6 +43,7 @@ module Wavefront
26
43
  # @return [Wavefront::Response]
27
44
  #
28
45
  def create(body, send_email = false)
46
+ deprecation_warning
29
47
  raise ArgumentError unless body.is_a?(Hash)
30
48
 
31
49
  api.post("?sendEmail=#{send_email}", body, 'application/json')
@@ -38,6 +56,7 @@ module Wavefront
38
56
  # @return [Wavefront::Response]
39
57
  #
40
58
  def delete(id)
59
+ deprecation_warning
41
60
  wf_user_id?(id)
42
61
  api.delete(id)
43
62
  end
@@ -49,6 +68,7 @@ module Wavefront
49
68
  # @return [Wavefront::Response]
50
69
  #
51
70
  def describe(id)
71
+ deprecation_warning
52
72
  wf_user_id?(id)
53
73
  api.get(id)
54
74
  end
@@ -65,6 +85,7 @@ module Wavefront
65
85
  # @return [Wavefront::Response]
66
86
 
67
87
  def update(id, body, modify = true)
88
+ deprecation_warning
68
89
  wf_user_id?(id)
69
90
  raise ArgumentError unless body.is_a?(Hash)
70
91
 
@@ -82,6 +103,7 @@ module Wavefront
82
103
  # @return [Wavefront::Response]
83
104
  #
84
105
  def add_groups_to_user(id, group_list = [])
106
+ deprecation_warning
85
107
  wf_user_id?(id)
86
108
  validate_usergroup_list(group_list)
87
109
  api.post([id, 'addUserGroups'].uri_concat, group_list,
@@ -95,6 +117,7 @@ module Wavefront
95
117
  # @return [Wavefront::Response]
96
118
  #
97
119
  def remove_groups_from_user(id, group_list = [])
120
+ deprecation_warning
98
121
  wf_user_id?(id)
99
122
  validate_usergroup_list(group_list)
100
123
  api.post([id, 'removeUserGroups'].uri_concat, group_list,
@@ -116,6 +139,7 @@ module Wavefront
116
139
  # @return [Wavefront::Response]
117
140
  #
118
141
  def grant(id, pgroup)
142
+ deprecation_warning
119
143
  wf_user_id?(id)
120
144
  raise ArgumentError unless pgroup.is_a?(String)
121
145
 
@@ -133,6 +157,7 @@ module Wavefront
133
157
  # @return [Wavefront::Response]
134
158
  #
135
159
  def revoke(id, pgroup)
160
+ deprecation_warning
136
161
  wf_user_id?(id)
137
162
  raise ArgumentError unless pgroup.is_a?(String)
138
163
 
@@ -149,6 +174,7 @@ module Wavefront
149
174
  # @return [Wavefront::Response]
150
175
  #
151
176
  def delete_users(user_list)
177
+ deprecation_warning
152
178
  raise ArgumentError unless user_list.is_a?(Array)
153
179
 
154
180
  validate_user_list(user_list)
@@ -165,6 +191,7 @@ module Wavefront
165
191
  # @return [Wavefront::Response]
166
192
  #
167
193
  def grant_permission(permission, user_list)
194
+ deprecation_warning
168
195
  raise ArgumentError unless user_list.is_a?(Array)
169
196
 
170
197
  validate_user_list(user_list)
@@ -182,6 +209,7 @@ module Wavefront
182
209
  # @return [Wavefront::Response]
183
210
  #
184
211
  def revoke_permission(permission, user_list)
212
+ deprecation_warning
185
213
  raise ArgumentError unless user_list.is_a?(Array)
186
214
 
187
215
  validate_user_list(user_list)
@@ -196,6 +224,7 @@ module Wavefront
196
224
  # @return [Wavefront::Response]
197
225
  #
198
226
  def invite(body)
227
+ deprecation_warning
199
228
  raise ArgumentError unless body.is_a?(Array)
200
229
  raise ArgumentError unless body.first.is_a?(Hash)
201
230
 
@@ -208,10 +237,22 @@ module Wavefront
208
237
  # @return [Wavefront::Response]
209
238
  #
210
239
  def business_functions(id)
240
+ deprecation_warning
211
241
  wf_user_id?(id)
212
242
  api.get([id, 'businessFunctions'].uri_concat)
213
243
  end
214
244
 
245
+ # POST /api/v2/user/validateUsers
246
+ # Returns valid users and service accounts, also invalid identifiers from
247
+ # the given list
248
+ # @param id_list [Array[String]] list of user IDs
249
+ # @return [Wavefront::Response]
250
+ #
251
+ def validate_users(id_list)
252
+ deprecation_warning
253
+ api.post('validateUsers', id_list, 'application/json')
254
+ end
255
+
215
256
  # Fake a response which looks like we get from all the other
216
257
  # paths. I'm expecting the user response model to be made
217
258
  # consistent with others in the future.
@@ -108,30 +108,31 @@ module Wavefront
108
108
  'application/json')
109
109
  end
110
110
 
111
- # POST /api/v2/usergroup/grant/{permission}
112
- # Grants a single permission to user group(s)
111
+ # POST /api/v2/usergroup/{id}/addRoles
112
+ # Add multiple roles to a specific user group
113
113
  #
114
- # @param perm [String] permission to grant
115
- # @param group_list [Array[String]] list of groups who should
116
- # receive permission
114
+ # @param id [String] ID of the user group
115
+ # @param role_list [Array[String]] list of roles to add
117
116
  # @return [Wavefront::Response]
118
117
  #
119
- def grant(perm, group_list = [])
120
- validate_usergroup_list(group_list)
121
- api.post(['grant', perm].uri_concat, group_list, 'application/json')
118
+ def add_roles_to_group(id, role_list = [])
119
+ wf_usergroup_id?(id)
120
+ validate_role_list(role_list)
121
+ api.post([id, 'addRoles'].uri_concat, role_list, 'application/json')
122
122
  end
123
123
 
124
- # POST /api/v2/usergroup/revoke/{permission}
125
- # Revokes a single permission from user group(s)
124
+ # POST /api/v2/usergroup/{id}/removeRoles
125
+ # Remove multiple roles from a specific user group
126
126
  #
127
- # @param perm [String] permission to revoke
128
- # @param group_list [Array[String]] list of groups who should
129
- # lose permission
127
+ # @param id [String] ID of the user group
128
+ # @param user_list [Array[String]] list of roles to remove
130
129
  # @return [Wavefront::Response]
131
130
  #
132
- def revoke(perm, group_list = [])
133
- validate_usergroup_list(group_list)
134
- api.post(['revoke', perm].uri_concat, group_list, 'application/json')
131
+ def remove_roles_from_group(id, role_list = [])
132
+ wf_usergroup_id?(id)
133
+ validate_role_list(role_list)
134
+ api.post([id, 'removeRoles'].uri_concat, role_list,
135
+ 'application/json')
135
136
  end
136
137
  end
137
138
  end
@@ -48,8 +48,8 @@ module Wavefront
48
48
  #
49
49
  def wf_metric_name?(metric)
50
50
  if metric.is_a?(String) && metric.size < 1024 &&
51
- (metric.match(/^#{DELTA}?[\w\-\.]+$/) ||
52
- metric.match(%r{^\"#{DELTA}?[\w\-\.\/,]+\"$}))
51
+ (metric.match(/^#{DELTA}?[\w\-.]+$/) ||
52
+ metric.match(%r{^"#{DELTA}?[\w\-./,]+"$}))
53
53
  return true
54
54
  end
55
55
 
@@ -81,7 +81,7 @@ module Wavefront
81
81
  # commas in tags and descriptions. This might be too restrictive,
82
82
  # but if it is, this is the only place we need to change it.
83
83
  #
84
- if str.is_a?(String) && str.size < 1024 && str =~ /^[\-\w \.,]*$/
84
+ if str.is_a?(String) && str.size < 1024 && str =~ /^[\-\w .,]*$/
85
85
  return true
86
86
  end
87
87
 
@@ -139,7 +139,7 @@ module Wavefront
139
139
  #
140
140
  def wf_tag?(*tags)
141
141
  Array(*tags).each do |tag|
142
- unless tag.is_a?(String) && tag.size < 255 && tag =~ /^[\w:\-\.]+$/
142
+ unless tag.is_a?(String) && tag.size < 255 && tag =~ /^[\w:\-.]+$/
143
143
  raise Wavefront::Exception::InvalidTag, tag
144
144
  end
145
145
  end
@@ -196,7 +196,7 @@ module Wavefront
196
196
  #
197
197
  def wf_point_tag?(key, val)
198
198
  if key && val && (key.size + val.size < 254) &&
199
- key =~ /^[\w\-\.:]+$/ && val !~ /\\$/
199
+ key =~ /^[\w\-.:]+$/ && val !~ /\\$/
200
200
  return
201
201
  end
202
202
 
@@ -391,7 +391,7 @@ module Wavefront
391
391
  # is not valid
392
392
  #
393
393
  def wf_source_id?(source)
394
- if source.is_a?(String) && source.match(/^[\w\.\-]+$/) &&
394
+ if source.is_a?(String) && source.match(/^[\w.\-]+$/) &&
395
395
  source.size < 1024
396
396
  return true
397
397
  end
@@ -566,7 +566,65 @@ module Wavefront
566
566
  return true
567
567
  end
568
568
 
569
- raise Wavefront::Exception::InvalidPermission, id, id
569
+ raise Wavefront::Exception::InvalidPermission, id
570
+ end
571
+
572
+ # Ensure the given argument is a valid ingestion policy ID
573
+ # @param id [String]
574
+ # @raise Wavefront::Exception::InvalidIngestionPolicyId if the
575
+ # ID is not valid
576
+ #
577
+ def wf_ingestionpolicy_id?(id)
578
+ return true if id.is_a?(String) && id =~ /^[a-z0-9\-_]+-\d{13}$/
579
+
580
+ raise Wavefront::Exception::InvalidIngestionPolicyId, id
581
+ end
582
+
583
+ # Ensure the given argument is a valid User or SystemAccount ID.
584
+ # @param id [String]
585
+ # @raise Wavefront::Exception::InvalidAccountId if the
586
+ # ID is not valid
587
+ #
588
+ def wf_account_id?(id)
589
+ return true if wf_user_id?(id)
590
+ rescue Wavefront::Exception::InvalidUserId
591
+ begin
592
+ return true if wf_serviceaccount_id?(id)
593
+ rescue Wavefront::Exception::InvalidServiceAccountId
594
+ raise Wavefront::Exception::InvalidAccountId, id
595
+ end
596
+ end
597
+
598
+ # Ensure the given argument is a valid monitored cluster ID
599
+ # @param id [String]
600
+ # @raise Wavefront::Exception::InvalidMonitoredClusterId if the ID is not
601
+ # valid
602
+ #
603
+ def wf_monitoredcluster_id?(id)
604
+ return true if id.is_a?(String) && id.size < 256 && id =~ /^[a-z0-9\-_]+$/
605
+
606
+ raise Wavefront::Exception::InvalidMonitoredClusterId, id
607
+ end
608
+
609
+ # Ensure the given value is a valid sampling rate.
610
+ # @param rate [Float]
611
+ # @raise Wavefront::Exception::InvalidSamplingValue
612
+ #
613
+ def wf_sampling_value?(value)
614
+ return true if value.is_a?(Numeric) && value.between?(0, 0.05)
615
+
616
+ raise Wavefront::Exception::InvalidSamplingValue, value
617
+ end
618
+
619
+ # Ensure the given argument is a valid Wavefront role ID
620
+ # @param id [String] the role ID to validate
621
+ # @return true if the role ID is valid
622
+ # @raise Wavefront::Exception::InvalidRoleId if the role ID is not valid
623
+ #
624
+ def wf_role_id?(id)
625
+ return true if uuid?(id)
626
+
627
+ raise Wavefront::Exception::InvalidRoleId, id
570
628
  end
571
629
  end
572
630
  # rubocop:enable Metrics/ModuleLength