wavefront-sdk 3.7.0 → 5.1.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +43 -2
  3. data/.travis.yml +0 -1
  4. data/HISTORY.md +32 -0
  5. data/README.md +4 -3
  6. data/lib/wavefront-sdk/account.rb +104 -3
  7. data/lib/wavefront-sdk/api_mixins/user.rb +10 -0
  8. data/lib/wavefront-sdk/cloudintegration.rb +27 -0
  9. data/lib/wavefront-sdk/core/api_caller.rb +50 -7
  10. data/lib/wavefront-sdk/core/exception.rb +5 -0
  11. data/lib/wavefront-sdk/defs/version.rb +1 -3
  12. data/lib/wavefront-sdk/paginator/base.rb +21 -15
  13. data/lib/wavefront-sdk/query.rb +0 -1
  14. data/lib/wavefront-sdk/role.rb +128 -0
  15. data/lib/wavefront-sdk/spy.rb +126 -0
  16. data/lib/wavefront-sdk/stdlib/array.rb +1 -1
  17. data/lib/wavefront-sdk/stdlib/time.rb +13 -0
  18. data/lib/wavefront-sdk/unstable/README.md +4 -0
  19. data/lib/wavefront-sdk/unstable/chart.rb +90 -0
  20. data/lib/wavefront-sdk/unstable/unstable.rb +9 -0
  21. data/lib/wavefront-sdk/user.rb +31 -0
  22. data/lib/wavefront-sdk/usergroup.rb +17 -16
  23. data/lib/wavefront-sdk/validators.rb +52 -7
  24. data/lib/wavefront-sdk/write.rb +13 -3
  25. data/spec/.rubocop.yml +41 -0
  26. data/spec/spec_helper.rb +4 -0
  27. data/spec/support/minitest_assertions.rb +4 -4
  28. data/spec/wavefront-sdk/account_spec.rb +107 -1
  29. data/spec/wavefront-sdk/cloudintegration_spec.rb +38 -0
  30. data/spec/wavefront-sdk/core/api_caller_spec.rb +43 -0
  31. data/spec/wavefront-sdk/metric_helper_spec.rb +1 -1
  32. data/spec/wavefront-sdk/role_spec.rb +96 -0
  33. data/spec/wavefront-sdk/spy_spec.rb +113 -0
  34. data/spec/wavefront-sdk/unstable/chart_spec.rb +39 -0
  35. data/spec/wavefront-sdk/user_spec.rb +8 -0
  36. data/spec/wavefront-sdk/usergroup_spec.rb +21 -11
  37. data/spec/wavefront-sdk/validators_spec.rb +31 -0
  38. data/wavefront-sdk.gemspec +4 -4
  39. metadata +24 -13
@@ -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,7 @@ 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
570
  end
571
571
 
572
572
  # Ensure the given argument is a valid ingestion policy ID
@@ -594,6 +594,51 @@ module Wavefront
594
594
  raise Wavefront::Exception::InvalidAccountId, id
595
595
  end
596
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
628
+ end
629
+
630
+ # Ensure the given argument is a valid AWS external ID, used in the AWS
631
+ # cloud integration.
632
+ # @param id [String] the external ID to validate
633
+ # @return true if the external ID is valid
634
+ # @raise Wavefront::Exception::InvalidAwsExternalId if the external ID is
635
+ # not valid
636
+ #
637
+ def wf_aws_external_id?(id)
638
+ return true if id.is_a?(String) && id =~ /^[a-z0-9A-Z]{16}$/
639
+
640
+ raise Wavefront::Exception::InvalidAwsExternalId, id
641
+ end
597
642
  end
598
643
  # rubocop:enable Metrics/ModuleLength
599
644
  end
@@ -107,12 +107,14 @@ module Wavefront
107
107
  end
108
108
 
109
109
  # Compound the responses of all chunked writes into one. It will
110
- # be 'ok' only if *everything* passed.
110
+ # be 'ok' only if *everything* passed. Returns 400 as the HTTP code on
111
+ # error, regardless of what actual errors occurred.
111
112
  # @param responses [Array[Wavefront::Response]]
112
113
  # @return Wavefront::Response
113
114
  #
114
115
  def composite_response(responses)
115
- result = responses.all?(&:ok?) ? 'OK' : 'ERROR'
116
+ result, code = response_results(responses)
117
+
116
118
  summary = { sent: 0, rejected: 0, unsent: 0 }
117
119
 
118
120
  %i[sent rejected unsent].each do |k|
@@ -120,11 +122,19 @@ module Wavefront
120
122
  end
121
123
 
122
124
  Wavefront::Response.new(
123
- { status: { result: result, message: nil, code: nil },
125
+ { status: { result: result, message: nil, code: code },
124
126
  response: summary.to_h }.to_json, nil
125
127
  )
126
128
  end
127
129
 
130
+ def response_results(responses)
131
+ if responses.all?(&:ok?)
132
+ ['OK', 200]
133
+ else
134
+ ['ERROR', 400]
135
+ end
136
+ end
137
+
128
138
  def manage_conn
129
139
  opts[:noauto] ? false : true
130
140
  end
@@ -11,3 +11,44 @@ Metrics/ClassLength:
11
11
  # Configuration parameters: CountComments, ExcludedMethods.
12
12
  Metrics/MethodLength:
13
13
  Max: 39
14
+
15
+ # New cops
16
+ #
17
+ Lint/RaiseException:
18
+ Enabled: true
19
+ Lint/StructNewOverride:
20
+ Enabled: true
21
+ Style/ExponentialNotation:
22
+ Enabled: true
23
+ Style/HashEachMethods:
24
+ Enabled: true
25
+ Style/HashTransformKeys:
26
+ Enabled: true
27
+ Style/HashTransformValues:
28
+ Enabled: true
29
+ Layout/EmptyLinesAroundAttributeAccessor:
30
+ Enabled: true
31
+ Layout/SpaceAroundMethodCallOperator:
32
+ Enabled: true
33
+ Style/SlicingWithRange:
34
+ Enabled: true
35
+ Lint/DeprecatedOpenSSLConstant:
36
+ Enabled: true
37
+ Lint/MixedRegexpCaptureTypes:
38
+ Enabled: true
39
+ Style/RedundantRegexpCharacterClass:
40
+ Enabled: true
41
+ Style/RedundantRegexpEscape:
42
+ Enabled: true
43
+ Style/AccessorGrouping:
44
+ Enabled: true
45
+ Style/BisectedAttrAccessor:
46
+ Enabled: true
47
+ Style/RedundantAssignment:
48
+ Enabled: true
49
+ Style/RedundantFetchBlock:
50
+ Enabled: true
51
+
52
+ # Is nothing sacred?
53
+ Layout/LineLength:
54
+ Max: 80
@@ -23,6 +23,10 @@ class WavefrontTestBase < MiniTest::Test
23
23
  "../lib/wavefront-sdk/#{class_basename.downcase}"
24
24
  end
25
25
 
26
+ def dummy_response
27
+ DUMMY_RESPONSE
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def setup
@@ -20,7 +20,7 @@ module Minitest
20
20
  headers = DEFAULT_HEADERS
21
21
  stub_request(:get, uri(api_path))
22
22
  .with(headers: headers)
23
- .to_return(body: DUMMY_RESPONSE, status: 200)
23
+ .to_return(body: dummy_response, status: 200)
24
24
  yield block
25
25
  assert_requested(:get, uri(api_path), headers: headers)
26
26
  WebMock.reset!
@@ -39,7 +39,7 @@ module Minitest
39
39
  payload = 'null' if payload.nil?
40
40
  stub_request(:post, uri(api_path))
41
41
  .with(body: payload, headers: headers)
42
- .to_return(body: DUMMY_RESPONSE, status: 200)
42
+ .to_return(body: dummy_response, status: 200)
43
43
  yield block
44
44
  assert_requested(:post, uri(api_path), headers: headers)
45
45
  WebMock.reset!
@@ -58,7 +58,7 @@ module Minitest
58
58
  payload = 'null' if payload.nil?
59
59
  stub_request(:put, uri(api_path))
60
60
  .with(body: payload, headers: headers)
61
- .to_return(body: DUMMY_RESPONSE, status: 200)
61
+ .to_return(body: dummy_response, status: 200)
62
62
  yield block
63
63
  assert_requested(:put, uri(api_path), headers: headers)
64
64
  WebMock.reset!
@@ -72,7 +72,7 @@ module Minitest
72
72
  headers = DEFAULT_HEADERS
73
73
  stub_request(:delete, uri(api_path))
74
74
  .with(headers: headers)
75
- .to_return(body: DUMMY_RESPONSE, status: 200)
75
+ .to_return(body: dummy_response, status: 200)
76
76
  yield block
77
77
  assert_requested(:delete, uri(api_path), headers: headers)
78
78
  WebMock.reset!
@@ -11,6 +11,18 @@ class WavefrontAccountTest < WavefrontTestBase
11
11
  include WavefrontTest::Delete
12
12
  include WavefrontTest::Describe
13
13
 
14
+ def test_add_roles
15
+ assert_posts("/api/v2/account/#{id}/addRoles", roles.to_json) do
16
+ wf.add_roles(id, roles)
17
+ end
18
+
19
+ assert_invalid_id { wf.add_roles(invalid_id, roles) }
20
+
21
+ assert_raises(Wavefront::Exception::InvalidRoleId) do
22
+ wf.add_roles(id, invalid_role)
23
+ end
24
+ end
25
+
14
26
  def test_add_user_groups
15
27
  assert_posts("/api/v2/account/#{id}/addUserGroups", groups.to_json) do
16
28
  wf.add_user_groups(id, groups)
@@ -37,6 +49,22 @@ class WavefrontAccountTest < WavefrontTestBase
37
49
  assert_posts("/api/v2/account/grant/#{permission}", id_list.to_json) do
38
50
  wf.grant(id_list, permission)
39
51
  end
52
+
53
+ assert_raises(Wavefront::Exception::InvalidRoleId) do
54
+ wf.remove_roles(id, invalid_role)
55
+ end
56
+ end
57
+
58
+ def test_remove_roles
59
+ assert_posts("/api/v2/account/#{id}/removeRoles", roles.to_json) do
60
+ wf.remove_roles(id, roles)
61
+ end
62
+
63
+ assert_invalid_id { wf.remove_roles(invalid_id, roles) }
64
+
65
+ assert_raises(Wavefront::Exception::InvalidRoleId) do
66
+ wf.remove_roles(id, invalid_role)
67
+ end
40
68
  end
41
69
 
42
70
  def test_remove_user_groups
@@ -45,12 +73,22 @@ class WavefrontAccountTest < WavefrontTestBase
45
73
  end
46
74
 
47
75
  assert_invalid_id { wf.remove_user_groups(invalid_id, groups) }
76
+
77
+ assert_raises(Wavefront::Exception::InvalidUserGroupId) do
78
+ wf.remove_user_groups(id, invalid_group)
79
+ end
48
80
  end
49
81
 
50
82
  def test_revoke_from_single_user
51
83
  assert_posts("/api/v2/account/#{id}/revoke/#{permission}") do
52
84
  wf.revoke(id, permission)
53
85
  end
86
+
87
+ assert_invalid_id { wf.revoke(invalid_id, permission) }
88
+
89
+ assert_raises(Wavefront::Exception::InvalidPermission) do
90
+ wf.revoke(id, invalid_permission)
91
+ end
54
92
  end
55
93
 
56
94
  def test_revoke_from_multiple_users
@@ -82,7 +120,7 @@ class WavefrontAccountTest < WavefrontTestBase
82
120
  end
83
121
 
84
122
  def test_remove_ingestion_policy
85
- assert_posts('/api/v2/account/removeingestionpolicy',
123
+ assert_posts('/api/v2/account/removeingestionpolicies',
86
124
  { ingestionPolicyId: policy_id,
87
125
  accounts: id_list }.to_json) do
88
126
  wf.remove_ingestion_policy(policy_id, id_list)
@@ -95,6 +133,52 @@ class WavefrontAccountTest < WavefrontTestBase
95
133
  assert_invalid_id { wf.add_ingestion_policy(policy_id, [invalid_id]) }
96
134
  end
97
135
 
136
+ def test_user_list
137
+ assert_gets('/api/v2/account/user?offset=0&limit=100') do
138
+ wf.user_list
139
+ end
140
+
141
+ assert_gets('/api/v2/account/user?offset=10&limit=50') do
142
+ wf.user_list(10, 50)
143
+ end
144
+ end
145
+
146
+ def test_user_describe
147
+ assert_gets("/api/v2/account/user/#{id}") { wf.user_describe(id) }
148
+
149
+ assert_raises(Wavefront::Exception::InvalidUserId) do
150
+ wf.user_describe(invalid_id)
151
+ end
152
+
153
+ assert_raises(ArgumentError) { wf.user_describe }
154
+ end
155
+
156
+ def test_user_create
157
+ assert_posts('/api/v2/account/user', payload.to_json) do
158
+ wf.user_create(payload)
159
+ end
160
+
161
+ assert_raises(ArgumentError) { wf.user_create }
162
+ assert_raises(ArgumentError) { wf.user_create('test') }
163
+ end
164
+
165
+ def test_user_invite
166
+ assert_posts('/api/v2/account/user/invite', [payload].to_json) do
167
+ wf.user_invite([payload])
168
+ end
169
+
170
+ assert_raises(ArgumentError) { wf.user_invite }
171
+ assert_raises(ArgumentError) { wf.user_invite('test') }
172
+ end
173
+
174
+ def test_validate_accounts
175
+ assert_posts('/api/v2/account/validateAccounts', id_list.to_json) do
176
+ wf.validate_accounts(id_list)
177
+ end
178
+
179
+ assert_raises(ArgumentError) { wf.validate_accounts }
180
+ end
181
+
98
182
  private
99
183
 
100
184
  def api_class
@@ -114,10 +198,27 @@ class WavefrontAccountTest < WavefrontTestBase
114
198
  2659191e-aad4-4302-a94e-9667e1517127]
115
199
  end
116
200
 
201
+ def roles
202
+ %w[f8dc0c14-91a0-4ca9-8a2a-7d47f4db1234
203
+ 2659191e-aad4-4302-a94e-9667e1515678]
204
+ end
205
+
206
+ def invalid_role
207
+ %w[bad_role]
208
+ end
209
+
210
+ def invalid_group
211
+ %w[bad_group]
212
+ end
213
+
117
214
  def id_list
118
215
  %w[sa:test user@example.com]
119
216
  end
120
217
 
218
+ def invalid_permission
219
+ 'some_nonsense_permission_i_made_up'
220
+ end
221
+
121
222
  def permission
122
223
  'agent_management'
123
224
  end
@@ -129,4 +230,9 @@ class WavefrontAccountTest < WavefrontTestBase
129
230
  def invalid_policy_id
130
231
  'badpolicy'
131
232
  end
233
+
234
+ def payload
235
+ { emailAddress: id,
236
+ groups: %w[browse] }
237
+ end
132
238
  end
@@ -37,6 +37,36 @@ class WavefrontCloudIntegrationTest < WavefrontTestBase
37
37
  assert_raises(ArgumentError) { wf.disable }
38
38
  end
39
39
 
40
+ def test_create_aws_external_id
41
+ assert_posts('/api/v2/cloudintegration/awsExternalId', nil, :json) do
42
+ wf.create_aws_external_id
43
+ end
44
+ end
45
+
46
+ def test_delete_aws_external_id
47
+ assert_deletes("/api/v2/cloudintegration/awsExternalId/#{external_id}") do
48
+ wf.delete_aws_external_id(external_id)
49
+ end
50
+
51
+ assert_raises(Wavefront::Exception::InvalidAwsExternalId) do
52
+ wf.delete_aws_external_id(invalid_external_id)
53
+ end
54
+
55
+ assert_raises(ArgumentError) { wf.delete_aws_external_id }
56
+ end
57
+
58
+ def test_confirm_aws_external_id
59
+ assert_gets("/api/v2/cloudintegration/awsExternalId/#{external_id}") do
60
+ wf.confirm_aws_external_id(external_id)
61
+ end
62
+
63
+ assert_raises(Wavefront::Exception::InvalidAwsExternalId) do
64
+ wf.confirm_aws_external_id(invalid_external_id)
65
+ end
66
+
67
+ assert_raises(ArgumentError) { wf.confirm_aws_external_id }
68
+ end
69
+
40
70
  private
41
71
 
42
72
  def id
@@ -62,4 +92,12 @@ class WavefrontCloudIntegrationTest < WavefrontTestBase
62
92
  def api_class
63
93
  'cloudintegration'
64
94
  end
95
+
96
+ def external_id
97
+ 'HqOM4mru5svd3uFp'
98
+ end
99
+
100
+ def invalid_external_id
101
+ '__nonsense__'
102
+ end
65
103
  end