wavefront-sdk 3.6.1 → 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +43 -2
- data/.travis.yml +0 -1
- data/HISTORY.md +33 -0
- data/README.md +4 -3
- data/lib/wavefront-sdk/account.rb +303 -0
- data/lib/wavefront-sdk/api_mixins/user.rb +20 -0
- data/lib/wavefront-sdk/core/api_caller.rb +50 -7
- data/lib/wavefront-sdk/core/exception.rb +6 -0
- data/lib/wavefront-sdk/core/response.rb +2 -1
- data/lib/wavefront-sdk/defs/version.rb +1 -3
- data/lib/wavefront-sdk/ingestionpolicy.rb +85 -0
- data/lib/wavefront-sdk/paginator/base.rb +21 -15
- data/lib/wavefront-sdk/query.rb +0 -1
- data/lib/wavefront-sdk/role.rb +128 -0
- data/lib/wavefront-sdk/spy.rb +126 -0
- data/lib/wavefront-sdk/stdlib/array.rb +1 -1
- data/lib/wavefront-sdk/stdlib/time.rb +13 -0
- data/lib/wavefront-sdk/unstable/README.md +4 -0
- data/lib/wavefront-sdk/unstable/chart.rb +90 -0
- data/lib/wavefront-sdk/unstable/unstable.rb +9 -0
- data/lib/wavefront-sdk/usage.rb +31 -0
- data/lib/wavefront-sdk/user.rb +41 -0
- data/lib/wavefront-sdk/usergroup.rb +17 -16
- data/lib/wavefront-sdk/validators.rb +65 -7
- data/lib/wavefront-sdk/write.rb +13 -3
- data/spec/.rubocop.yml +42 -1
- data/spec/spec_helper.rb +4 -0
- data/spec/support/minitest_assertions.rb +4 -4
- data/spec/wavefront-sdk/account_spec.rb +238 -0
- data/spec/wavefront-sdk/core/api_caller_spec.rb +43 -0
- data/spec/wavefront-sdk/ingestionpolicy_spec.rb +43 -0
- data/spec/wavefront-sdk/metric_helper_spec.rb +1 -1
- data/spec/wavefront-sdk/role_spec.rb +96 -0
- data/spec/wavefront-sdk/spy_spec.rb +113 -0
- data/spec/wavefront-sdk/unstable/chart_spec.rb +39 -0
- data/spec/wavefront-sdk/usage_spec.rb +33 -0
- data/spec/wavefront-sdk/user_spec.rb +20 -0
- data/spec/wavefront-sdk/usergroup_spec.rb +21 -11
- data/spec/wavefront-sdk/validators_spec.rb +52 -6
- data/wavefront-sdk.gemspec +4 -4
- metadata +30 -9
@@ -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,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,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
|
data/lib/wavefront-sdk/user.rb
CHANGED
@@ -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/
|
112
|
-
#
|
111
|
+
# POST /api/v2/usergroup/{id}/addRoles
|
112
|
+
# Add multiple roles to a specific user group
|
113
113
|
#
|
114
|
-
# @param
|
115
|
-
# @param
|
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
|
120
|
-
|
121
|
-
|
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/
|
125
|
-
#
|
124
|
+
# POST /api/v2/usergroup/{id}/removeRoles
|
125
|
+
# Remove multiple roles from a specific user group
|
126
126
|
#
|
127
|
-
# @param
|
128
|
-
# @param
|
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
|
133
|
-
|
134
|
-
|
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{
|
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
|
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
|
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
|