wavefront-sdk 5.4.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.github/workflows/release.yml +37 -0
  4. data/.github/workflows/test.yml +23 -0
  5. data/.rubocop.yml +8 -6
  6. data/HISTORY.md +26 -0
  7. data/README.md +5 -5
  8. data/lib/wavefront-sdk/api_mixins/acl.rb +1 -1
  9. data/lib/wavefront-sdk/core/api.rb +1 -1
  10. data/lib/wavefront-sdk/core/api_caller.rb +2 -2
  11. data/lib/wavefront-sdk/core/exception.rb +58 -0
  12. data/lib/wavefront-sdk/credentials.rb +8 -8
  13. data/lib/wavefront-sdk/defs/version.rb +1 -1
  14. data/lib/wavefront-sdk/event.rb +70 -3
  15. data/lib/wavefront-sdk/metricspolicy.rb +57 -0
  16. data/lib/wavefront-sdk/query.rb +2 -0
  17. data/lib/wavefront-sdk/search.rb +2 -0
  18. data/lib/wavefront-sdk/spy.rb +22 -0
  19. data/lib/wavefront-sdk/support/parse_time.rb +1 -1
  20. data/lib/wavefront-sdk/user.rb +1 -1
  21. data/lib/wavefront-sdk/validators.rb +17 -2
  22. data/lib/wavefront-sdk/write.rb +3 -3
  23. data/lib/wavefront-sdk/writers/api.rb +2 -2
  24. data/lib/wavefront-sdk/writers/core.rb +1 -1
  25. data/lib/wavefront-sdk/writers/http.rb +2 -2
  26. data/lib/wavefront-sdk/writers/proxy.rb +71 -0
  27. data/lib/wavefront-sdk/writers/socket.rb +15 -27
  28. data/spec/.rubocop.yml +3 -15
  29. data/spec/constants.rb +2 -2
  30. data/spec/support/mocket.rb +3 -1
  31. data/spec/test_mixins/general.rb +1 -1
  32. data/spec/wavefront-sdk/core/response_spec.rb +2 -2
  33. data/spec/wavefront-sdk/event_spec.rb +46 -0
  34. data/spec/wavefront-sdk/metric_helper_spec.rb +6 -4
  35. data/spec/wavefront-sdk/metricspolicy_spec.rb +94 -0
  36. data/spec/wavefront-sdk/spy_spec.rb +27 -0
  37. data/spec/wavefront-sdk/validators_spec.rb +11 -1
  38. data/spec/wavefront-sdk/write_spec.rb +1 -1
  39. data/spec/wavefront-sdk/writers/api_spec.rb +4 -0
  40. data/spec/wavefront-sdk/writers/core_spec.rb +1 -3
  41. data/spec/wavefront-sdk/writers/http_spec.rb +24 -21
  42. data/spec/wavefront-sdk/writers/proxy_spec.rb +129 -0
  43. data/spec/wavefront-sdk/writers/socket_spec.rb +49 -27
  44. data/wavefront-sdk.gemspec +5 -3
  45. metadata +58 -11
  46. data/.github/workflows/ruby.yml +0 -32
  47. data/.travis.yml +0 -21
  48. data/lib/wavefront-sdk/writers/unix.rb +0 -59
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # A mock socket
3
+ # A mock socket. Stubs TCP sockets and UNIX domain sockets.
4
4
  #
5
5
  class Mocket
6
6
  def puts(socket); end
7
7
 
8
+ def write(socket); end
9
+
8
10
  def close; end
9
11
 
10
12
  def ok?
@@ -77,7 +77,7 @@ module WavefrontTest
77
77
 
78
78
  def test_update_keys
79
79
  assert_instance_of Array, wf.update_keys
80
- assert(wf.update_keys.all? { |k| k.is_a?(Symbol) })
80
+ assert(wf.update_keys.all?(Symbol))
81
81
  end
82
82
  end
83
83
 
@@ -7,8 +7,8 @@ require_relative '../../../lib/wavefront-sdk/core/exception'
7
7
  require_relative '../../../lib/wavefront-sdk/core/response'
8
8
 
9
9
  GOOD_RESP = '{"status":{"result":"OK","message":"","code":200},' \
10
- '"response":{"items":[{"name":"test agent"}],"offset":0,' \
11
- '"limit":100,"totalItems":3,"moreItems":false}}'
10
+ '"response":{"items":[{"name":"test agent"}],"offset":0,' \
11
+ '"limit":100,"totalItems":3,"moreItems":false}}'
12
12
 
13
13
  BAD_RESP = "error='not_found'
14
14
  message='resource cannot be found'
@@ -43,12 +43,58 @@ class WavefrontEventTest < WavefrontTestBase
43
43
  assert_raises(ArgumentError) { wf.close }
44
44
  end
45
45
 
46
+ def test_alert_firing_details
47
+ assert_gets("/api/v2/event/#{id}/alertFiringDetails") do
48
+ wf.alert_firing_details(id)
49
+ end
50
+
51
+ assert_raises(Wavefront::Exception::InvalidEventId) do
52
+ wf.alert_firing_details(invalid_id)
53
+ end
54
+ end
55
+
56
+ def test_alert_queries_slug
57
+ assert_gets("/api/v2/event/#{id}/alertQueriesSlug") do
58
+ wf.alert_queries_slug(id)
59
+ end
60
+
61
+ assert_raises(Wavefront::Exception::InvalidEventId) do
62
+ wf.alert_queries_slug(invalid_id)
63
+ end
64
+ end
65
+
66
+ def test_events
67
+ assert_gets(
68
+ "/api/v2/event/#{id}/events?isOverlapped=false&renderingMethod=HOST"
69
+ ) do
70
+ wf.events(id)
71
+ end
72
+
73
+ assert_raises(Wavefront::Exception::InvalidEventId) do
74
+ wf.events(invalid_id)
75
+ end
76
+ end
77
+
78
+ def test_alert_firings
79
+ assert_gets("/api/v2/event/alertFirings?alertId=#{alert_id}&asc=true") do
80
+ wf.alert_firings(alert_id, asc: true)
81
+ end
82
+
83
+ assert_raises(Wavefront::Exception::InvalidAlertId) do
84
+ wf.alert_firings(invalid_id)
85
+ end
86
+ end
87
+
46
88
  private
47
89
 
48
90
  def id
49
91
  '1481553823153:testev'
50
92
  end
51
93
 
94
+ def alert_id
95
+ '1481553823153'
96
+ end
97
+
52
98
  def invalid_id
53
99
  'nonsense'
54
100
  end
@@ -4,6 +4,8 @@
4
4
  require 'minitest/autorun'
5
5
  require_relative '../spec_helper'
6
6
  require_relative '../../lib/wavefront-sdk/metric_helper'
7
+ require_relative '../support/mocket'
8
+ require_relative '../support/bad_mocket'
7
9
 
8
10
  ND_CREDS = { proxy: 'wavefront' }.freeze
9
11
  WH_TAGS = { t1: 'v1', t2: 'v2' }.freeze
@@ -115,12 +117,12 @@ class WavefrontMetricHelperTest < MiniTest::Test
115
117
  out = wfd.dists_to_wf(input)
116
118
  assert_instance_of(Array, out)
117
119
  assert_equal(3, out.size)
118
- assert_equal(1, out.select do |o|
120
+ assert_equal(1, out.count do |o|
119
121
  o[:value] == [[2, 10.0], [1, 11.0],
120
122
  [1, 12.0]]
121
- end.size)
122
- assert_equal(1, out.select { |o| o[:tags] == WH_TAGS }.size)
123
- assert_equal(3, out.select { |o| o[:path] == 'test.dist1' }.size)
123
+ end)
124
+ assert_equal(1, out.count { |o| o[:tags] == WH_TAGS })
125
+ assert_equal(3, out.count { |o| o[:path] == 'test.dist1' })
124
126
  end
125
127
 
126
128
  def test_flush_gauges
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../spec_helper'
5
+ require_relative '../test_mixins/general'
6
+
7
+ # Unit tests for MetricsPolicy class
8
+ #
9
+ class WavefrontMetricsPolicyTest < WavefrontTestBase
10
+ def test_describe
11
+ assert_gets('/api/v2/metricspolicy') { wf.describe }
12
+
13
+ assert_gets('/api/v2/metricspolicy/history/5') { wf.describe(5) }
14
+
15
+ assert_raises(Wavefront::Exception::InvalidVersion) do
16
+ wf.describe('v5')
17
+ end
18
+ end
19
+
20
+ def test_history
21
+ assert_gets('/api/v2/metricspolicy?offset=10&limit=100') do
22
+ wf.history(10)
23
+ end
24
+
25
+ assert_gets('/api/v2/metricspolicy?offset=12&limit=34') do
26
+ wf.history(12, 34)
27
+ end
28
+ end
29
+
30
+ def test_revert
31
+ assert_posts('/api/v2/metricspolicy/revert/5') do
32
+ wf.revert(5)
33
+ end
34
+
35
+ assert_raises(Wavefront::Exception::InvalidVersion) do
36
+ wf.revert('v5')
37
+ end
38
+ end
39
+
40
+ def test_update
41
+ assert_puts('/api/v2/metricspolicy', payload.to_json) do
42
+ wf.update(payload)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def api_class
49
+ 'metricspolicy'
50
+ end
51
+
52
+ def id
53
+ 'a7d2e651-cec1-4154-a5e8-1946f57ef5b3'
54
+ end
55
+
56
+ def invalid_id
57
+ '+-+-+-+'
58
+ end
59
+
60
+ def payload
61
+ {
62
+ policyRules: [
63
+ {
64
+ name: 'Policy rule1 name',
65
+ description: 'Policy rule1 description',
66
+ prefixes: ['revenue.*'],
67
+ tags: [
68
+ {
69
+ key: 'sensitive',
70
+ value: 'false'
71
+ },
72
+ {
73
+ key: 'source',
74
+ value: 'app1'
75
+ }
76
+ ],
77
+ tagsAnded: 'true',
78
+ accessType: 'ALLOW',
79
+ accounts: %w[accountId1 accountId2],
80
+ userGroups: ['userGroupId1'],
81
+ roles: ['roleId']
82
+ },
83
+ {
84
+ name: 'Policy rule2 name',
85
+ description: 'Policy rule2 description',
86
+ prefixes: ['revenue.*'],
87
+ accessType: 'BLOCK',
88
+ accounts: ['accountId3'],
89
+ userGroups: ['userGroupId1']
90
+ }
91
+ ]
92
+ }
93
+ end
94
+ end
@@ -38,6 +38,33 @@ class WavefrontSpyTest < MiniTest::Test
38
38
  end
39
39
  end
40
40
 
41
+ def test_deltas
42
+ capture_io do
43
+ assert_gets('/api/spy/deltas?sampling=0.01') { wf.deltas }
44
+ assert_gets('/api/spy/deltas?sampling=0.05') { wf.deltas(0.05) }
45
+
46
+ assert_gets('/api/spy/deltas?sampling=0.05&counter=my_prefix') do
47
+ wf.deltas(0.05, prefix: 'my_prefix')
48
+ end
49
+
50
+ assert_gets(
51
+ '/api/spy/deltas?sampling=0.05&counter=my_prefix&host=h1'
52
+ ) do
53
+ wf.deltas(0.05, prefix: 'my_prefix', host: 'h1')
54
+ end
55
+
56
+ assert_gets('/api/spy/deltas?sampling=0.02&counter=my_prefix&' \
57
+ 'counterTagKey=the_tag') do
58
+ wf.deltas(0.02, prefix: 'my_prefix', tag_key: 'the_tag')
59
+ end
60
+
61
+ assert_gets('/api/spy/deltas?sampling=0.02&counter=my_prefix&' \
62
+ 'counterTagKey=tag1&counterTagKey=tag2') do
63
+ wf.deltas(0.02, prefix: 'my_prefix', tag_key: %w[tag1 tag2])
64
+ end
65
+ end
66
+ end
67
+
41
68
  def test_histograms
42
69
  capture_io do
43
70
  assert_gets('/api/spy/histograms?sampling=0.01') { wf.histograms }
@@ -84,7 +84,7 @@ class WavefrontValidatorsTest < MiniTest::Test
84
84
  { tag1: 'val 1', tag2: 'val 2' },
85
85
  { TAG1: 'val 1', tag2: 'val 2' },
86
86
  { 'TAG-1': 'val 1', tag2: 'val 2' },
87
- { 'TAG_1': 'val 1', tag_2: 'val 2' },
87
+ { TAG_1: 'val 1', tag_2: 'val 2' },
88
88
  { 'TAG.1': 'val 1', tag_2: 'val 2' },
89
89
  { 'TAG-1': 'val 1', tag2: 'val 2' },
90
90
  { tag1: '(>_<)', tag2: '^_^' }]
@@ -417,4 +417,14 @@ class WavefrontValidatorsTest < MiniTest::Test
417
417
  bad = %w[h5Z9dkr46jbvLtJ HqOM4mru5svd3uFp3 c!lBx!LC*NxLKdx*]
418
418
  good_and_bad('wf_aws_external_id?', 'InvalidAwsExternalId', good, bad)
419
419
  end
420
+
421
+ def test_wf_metricspolicy_id
422
+ good = %w[2bfdcac7-1c9c-4c4b-9b56-c41c22c586dc
423
+ a7d2e651-cec1-4154-a5e8-1946f57ef5b3
424
+ fca312fb-5ff4-420d-862d-5d6d99ed6bcf
425
+ 3a1957e0-459e-49e5-9209-3888a4e8ac5b]
426
+
427
+ bad = %w[fa312fb-5ff4-420d-862d-5d6d99ed6bcf thing 123]
428
+ good_and_bad('wf_metricspolicy_id?', 'InvalidMetricsPolicyId', good, bad)
429
+ end
420
430
  end
@@ -27,7 +27,7 @@ class WavefrontWriteTest < MiniTest::Test
27
27
  refute(wf.opts[:noop])
28
28
  assert(wf_noop.opts[:noop])
29
29
  assert_equal(wf_tags.opts[:tags], TAGS)
30
- assert_instance_of(Wavefront::Writer::Socket, wf.writer)
30
+ assert_instance_of(Wavefront::Writer::Proxy, wf.writer)
31
31
  end
32
32
 
33
33
  def test_composite_response
@@ -42,5 +42,9 @@ class WavefrontWriterApiTest < MiniTest::Test
42
42
  assert_raises(Wavefront::Exception::CredentialError) do
43
43
  Wavefront::Write.new({ token: 'abcdef' }, writer: :api)
44
44
  end
45
+
46
+ assert_raises(Wavefront::Exception::CredentialError) do
47
+ Wavefront::Write.new({ token: 'abcdef', endpoint: nil }, writer: :api)
48
+ end
45
49
  end
46
50
  end
@@ -6,9 +6,7 @@ require_relative '../../spec_helper'
6
6
  require_relative '../../../lib/wavefront-sdk/writers/core'
7
7
  require_relative '../resources/dummy_points'
8
8
 
9
- # rubocop:disable Style/MutableConstant
10
- WBWT_CREDS = { endpoint: 'stub.wavefront.com', token: 'tkn' }
11
- # rubocop:enable Style/MutableConstant
9
+ WBWT_CREDS = { endpoint: 'stub.wavefront.com', token: 'tkn' }.freeze
12
10
 
13
11
  # Fake class for testing
14
12
  #
@@ -6,6 +6,7 @@ require_relative '../resources/dummy_points'
6
6
  require_relative '../../../lib/wavefront-sdk/write'
7
7
 
8
8
  BODY = 'test.metric 123456 1469987572 source=testhost t1="v1" t2="v2"'
9
+ WH_CREDS = { proxy: 'wavefront-proxy' }.freeze
9
10
 
10
11
  # Test HTTP transport
11
12
  #
@@ -20,27 +21,6 @@ class WavefrontWriterSocketTest < MiniTest::Test
20
21
  assert_instance_of(Wavefront::Writer::Http, wf.writer)
21
22
  end
22
23
 
23
- def test_validate_credentials
24
- assert Wavefront::Write.new({ proxy: 'wavefront' }, writer: :http)
25
- assert_instance_of(Wavefront::Write, wf)
26
-
27
- assert_raises(Wavefront::Exception::CredentialError) do
28
- Wavefront::Write.new(CREDS, writer: :http)
29
- end
30
-
31
- assert_raises(Wavefront::Exception::CredentialError) do
32
- Wavefront::Write.new({}, writer: :http)
33
- end
34
-
35
- assert_raises(Wavefront::Exception::CredentialError) do
36
- Wavefront::Write.new({ endpoint: 'wavefront.com' }, writer: :http)
37
- end
38
-
39
- assert_raises(Wavefront::Exception::CredentialError) do
40
- Wavefront::Write.new({ token: 'abcdef' }, writer: :http)
41
- end
42
- end
43
-
44
24
  def test_write_2878
45
25
  wf1 = Wavefront::Write.new({ proxy: 'wavefront' }, writer: :http)
46
26
 
@@ -67,4 +47,27 @@ class WavefrontWriterSocketTest < MiniTest::Test
67
47
  assert_requested(:post, 'http://wavefront:1234', headers: POST_HEADERS)
68
48
  WebMock.reset!
69
49
  end
50
+
51
+ def test_validate_credentials
52
+ assert(Wavefront::Write.new(WH_CREDS, writer: :http))
53
+
54
+ assert_instance_of(Wavefront::Write,
55
+ Wavefront::Write.new(WH_CREDS, writer: :http))
56
+
57
+ assert_raises(Wavefront::Exception::CredentialError) do
58
+ Wavefront::Write.new({}, writer: :http)
59
+ end
60
+
61
+ assert_raises(Wavefront::Exception::CredentialError) do
62
+ Wavefront::Write.new({ endpoint: 'wavefront.com' }, writer: :http)
63
+ end
64
+
65
+ assert_raises(Wavefront::Exception::CredentialError) do
66
+ Wavefront::Write.new({ token: 'abcdef' }, writer: :http)
67
+ end
68
+
69
+ assert_raises(Wavefront::Exception::CredentialError) do
70
+ Wavefront::Write.new({ proxy: nil }, writer: :http)
71
+ end
72
+ end
70
73
  end
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'webmock/minitest'
5
+ require 'spy'
6
+ require 'spy/integration'
7
+ require 'socket'
8
+ require 'logger'
9
+ require_relative '../resources/dummy_points'
10
+ require_relative '../../spec_helper'
11
+ require_relative '../../../lib/wavefront-sdk/write'
12
+ require_relative '../../../spec/support/mocket'
13
+
14
+ WS_CREDS = { proxy: 'wavefront-proxy' }.freeze
15
+
16
+ # The Proxy class writes to a proxy TCP socket
17
+ #
18
+ class WavefrontWriterSocketTest < MiniTest::Test
19
+ attr_reader :wf, :wf_noop
20
+
21
+ def setup
22
+ @wf = Wavefront::Write.new(WS_CREDS, writer: :proxy)
23
+ @wf_noop = Wavefront::Write.new(WS_CREDS, writer: :proxy, noop: true)
24
+ end
25
+
26
+ def test_writer_class
27
+ assert_instance_of(Wavefront::Writer::Proxy, wf.writer)
28
+ end
29
+
30
+ def test_write_openclose
31
+ mocket = Mocket.new
32
+ Spy.on(TCPSocket, :new).and_return(mocket)
33
+ mocket_spy = Spy.on(mocket, :puts)
34
+ wf.write(POINT)
35
+ assert mocket_spy.has_been_called?
36
+ end
37
+
38
+ def test_write_noop
39
+ mocket = Mocket.new
40
+ Spy.on(TCPSocket, :new).and_return(mocket)
41
+ mocket_spy = Spy.on(mocket, :puts)
42
+ wf_noop.open
43
+ wf_noop.write(POINT, false)
44
+ refute mocket_spy.has_been_called?
45
+ end
46
+
47
+ def test_write_noop_openclose
48
+ mocket = Mocket.new
49
+ Spy.on(TCPSocket, :new).and_return(mocket)
50
+ mocket_spy = Spy.on(mocket, :puts)
51
+ wf_noop.write(POINT)
52
+ refute mocket_spy.has_been_called?
53
+ end
54
+
55
+ def test_write
56
+ mocket = Mocket.new
57
+ Spy.on(TCPSocket, :new).and_return(mocket)
58
+ mocket_spy = Spy.on(mocket, :puts)
59
+ wf.open
60
+ wf.write(POINT, false)
61
+ assert mocket_spy.has_been_called?
62
+ end
63
+
64
+ def test_write_array
65
+ mocket = Mocket.new
66
+ Spy.on(TCPSocket, :new).and_return(mocket)
67
+ mocket_spy = Spy.on(mocket, :puts)
68
+ wf.open
69
+ wf.write(POINT_A, false)
70
+ assert mocket_spy.has_been_called?
71
+ end
72
+
73
+ def test_noop_send_point
74
+ mocket = Mocket.new
75
+ Spy.on(TCPSocket, :new).and_return(mocket)
76
+ mocket_spy = Spy.on(mocket, :puts)
77
+ wf_noop.open
78
+ wf_noop.send_point(POINT_L)
79
+ refute mocket_spy.has_been_called?
80
+ end
81
+
82
+ def test_open
83
+ tcp_spy = Spy.on(TCPSocket, :new)
84
+ wf.open
85
+ assert tcp_spy.has_been_called?
86
+ assert_equal(['wavefront-proxy', 2878], tcp_spy.calls.first.args)
87
+ end
88
+
89
+ def test_noop_open
90
+ tcp_spy = Spy.on(TCPSocket, :new)
91
+ log_spy = Spy.on(wf_noop.logger, :log)
92
+ wf_noop.open
93
+ refute tcp_spy.has_been_called?
94
+ assert_equal(['No-op requested. Not opening connection to proxy.'],
95
+ log_spy.calls.last.args)
96
+ assert_equal(1, log_spy.calls.size)
97
+ end
98
+
99
+ def test_noop_close
100
+ tcp_spy = Spy.on(TCPSocket, :new)
101
+ log_spy = Spy.on(wf_noop.logger, :log)
102
+ wf_noop.close
103
+ refute tcp_spy.has_been_called?
104
+ refute log_spy.has_been_called?
105
+ end
106
+
107
+ def test_validate_credentials
108
+ assert(Wavefront::Write.new(WS_CREDS, writer: :proxy))
109
+
110
+ assert_instance_of(Wavefront::Write,
111
+ Wavefront::Write.new(WS_CREDS, writer: :proxy))
112
+
113
+ assert_raises(Wavefront::Exception::CredentialError) do
114
+ Wavefront::Write.new({}, writer: :proxy)
115
+ end
116
+
117
+ assert_raises(Wavefront::Exception::CredentialError) do
118
+ Wavefront::Write.new({ endpoint: 'wavefront.com' }, writer: :proxy)
119
+ end
120
+
121
+ assert_raises(Wavefront::Exception::CredentialError) do
122
+ Wavefront::Write.new({ token: 'abcdef' }, writer: :proxy)
123
+ end
124
+
125
+ assert_raises(Wavefront::Exception::CredentialError) do
126
+ Wavefront::Write.new({ proxy: nil }, writer: :proxy)
127
+ end
128
+ end
129
+ end