wavefront-sdk 5.4.1 → 6.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.
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