wavefront-sdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +20 -0
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +1157 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +58 -0
  8. data/LICENSE.txt +27 -0
  9. data/README.md +103 -0
  10. data/Rakefile +18 -0
  11. data/lib/wavefront-sdk/alert.rb +195 -0
  12. data/lib/wavefront-sdk/base.rb +251 -0
  13. data/lib/wavefront-sdk/cloudintegration.rb +88 -0
  14. data/lib/wavefront-sdk/credentials.rb +79 -0
  15. data/lib/wavefront-sdk/dashboard.rb +157 -0
  16. data/lib/wavefront-sdk/event.rb +173 -0
  17. data/lib/wavefront-sdk/exception.rb +39 -0
  18. data/lib/wavefront-sdk/externallink.rb +77 -0
  19. data/lib/wavefront-sdk/maintenancewindow.rb +75 -0
  20. data/lib/wavefront-sdk/message.rb +36 -0
  21. data/lib/wavefront-sdk/metric.rb +52 -0
  22. data/lib/wavefront-sdk/mixins.rb +60 -0
  23. data/lib/wavefront-sdk/proxy.rb +95 -0
  24. data/lib/wavefront-sdk/query.rb +96 -0
  25. data/lib/wavefront-sdk/response.rb +56 -0
  26. data/lib/wavefront-sdk/savedsearch.rb +88 -0
  27. data/lib/wavefront-sdk/search.rb +58 -0
  28. data/lib/wavefront-sdk/source.rb +131 -0
  29. data/lib/wavefront-sdk/user.rb +108 -0
  30. data/lib/wavefront-sdk/validators.rb +395 -0
  31. data/lib/wavefront-sdk/version.rb +1 -0
  32. data/lib/wavefront-sdk/webhook.rb +73 -0
  33. data/lib/wavefront-sdk/write.rb +225 -0
  34. data/pkg/wavefront-client-3.5.0.gem +0 -0
  35. data/spec/.rubocop.yml +14 -0
  36. data/spec/spec_helper.rb +157 -0
  37. data/spec/wavefront-sdk/alert_spec.rb +83 -0
  38. data/spec/wavefront-sdk/base_spec.rb +88 -0
  39. data/spec/wavefront-sdk/cloudintegration_spec.rb +54 -0
  40. data/spec/wavefront-sdk/credentials_spec.rb +55 -0
  41. data/spec/wavefront-sdk/dashboard_spec.rb +74 -0
  42. data/spec/wavefront-sdk/event_spec.rb +83 -0
  43. data/spec/wavefront-sdk/externallink_spec.rb +65 -0
  44. data/spec/wavefront-sdk/maintenancewindow_spec.rb +48 -0
  45. data/spec/wavefront-sdk/message_spec.rb +19 -0
  46. data/spec/wavefront-sdk/metric_spec.rb +21 -0
  47. data/spec/wavefront-sdk/mixins_spec.rb +27 -0
  48. data/spec/wavefront-sdk/proxy_spec.rb +41 -0
  49. data/spec/wavefront-sdk/query_spec.rb +51 -0
  50. data/spec/wavefront-sdk/resources/test.conf +10 -0
  51. data/spec/wavefront-sdk/response_spec.rb +47 -0
  52. data/spec/wavefront-sdk/savedsearch_spec.rb +54 -0
  53. data/spec/wavefront-sdk/search_spec.rb +47 -0
  54. data/spec/wavefront-sdk/source_spec.rb +48 -0
  55. data/spec/wavefront-sdk/user_spec.rb +56 -0
  56. data/spec/wavefront-sdk/validators_spec.rb +238 -0
  57. data/spec/wavefront-sdk/webhook_spec.rb +50 -0
  58. data/spec/wavefront-sdk/write_spec.rb +167 -0
  59. data/wavefront-sdk.gemspec +34 -0
  60. metadata +269 -0
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'date'
4
+ require 'minitest/autorun'
5
+ require_relative '../spec_helper'
6
+ require_relative '../../lib/wavefront-sdk/validators'
7
+
8
+ class WavefrontValidatorsTest < MiniTest::Test
9
+ include Wavefront::Validators
10
+
11
+ def good_and_bad(method, exception, good, bad)
12
+ ex = Object.const_get("Wavefront::Exception::#{exception}")
13
+
14
+ good.each { |m| assert send(method, m) }
15
+ bad.each { |m| assert_raises(ex) { send(method, m) } }
16
+ end
17
+
18
+ def test_wf_metric_name?
19
+ good = ['a.l33t.metric_path-passes', 'NO.NEED.TO.SHOUT',
20
+ '"slash/allowed_in_quotes"', '"comma,allowed_in_quotes"']
21
+ bad = ['metric.is.(>_<)', { key: 'val' }, 'no/slash', 'no,comma', []]
22
+ good_and_bad('wf_metric_name?', 'InvalidMetricName', good, bad)
23
+ end
24
+
25
+ def test_wf_string?
26
+ good = ['string', 'valid string', 'valid, valid string.',
27
+ 'valid-string', ' VALID_string']
28
+ bad = ['a' * 1024, '(>_<)', { key: 'val' }, [], 123456]
29
+ good_and_bad('wf_string?', 'InvalidString', good, bad)
30
+ end
31
+
32
+ def test_wf_name?
33
+ good = %w(name name123)
34
+ bad = ['a' * 1024, '(>_<)', { key: 'val' }, [], 123456, '']
35
+ good_and_bad('wf_name?', 'InvalidName', good, bad)
36
+ end
37
+
38
+ def test_wf_source_id?
39
+ good = ['validsource1', 'valid-source', 'valid_source',
40
+ 'valid.source', 'Valid_Source', 'a' * 1023, '123456']
41
+ bad = ['a' * 1024, '(>_<)', { key: 'val' }, [], 123456]
42
+ good_and_bad('wf_source_id?', 'InvalidSourceId', good, bad)
43
+ end
44
+
45
+ def test_wf_value?
46
+ good = [0, 123, -10, 1.23456789, 1.23e04]
47
+ bad = ['1', 'abc', '0', {}, []]
48
+ good_and_bad('wf_value?', 'InvalidMetricValue', good, bad)
49
+ end
50
+
51
+ def test_wf_ts?
52
+ good = [Time.now, Date.today, DateTime.now]
53
+ bad = ['2017-03-25 23:52:22 +0000', 1490485946,
54
+ '#<Date: 2017-03-25 ((2457838j,0s,0n),+0s,2299161j)>']
55
+ good_and_bad('wf_ts?', 'InvalidTimestamp', good, bad)
56
+ end
57
+
58
+ def test_wf_ms_ts?
59
+ good = [Time.now.to_i * 1000]
60
+ bad = ['2017-03-25 23:52:22 +0000']
61
+ good_and_bad('wf_ms_ts?', 'InvalidTimestamp', good, bad)
62
+ end
63
+
64
+ def test_wf_epoch?
65
+ good = [Time.now.to_i]
66
+ bad = ['2017-03-25 23:52:22 +0000']
67
+ good_and_bad('wf_epoch?', 'InvalidTimestamp', good, bad)
68
+ end
69
+
70
+ def test_wf_tag?
71
+ good = ['abc', 'abc123', '__tag__', 'my:tag', ['abc', 'abc123']]
72
+ bad = ['^^^', Time.now, 'bad tag', ['abc', '!BAD!']]
73
+ good_and_bad('wf_tag?', 'InvalidTag', good, bad)
74
+ end
75
+
76
+ def test_wf_point_tags?
77
+ good = [{},
78
+ {tag1: 'val1', tag2: 'val2'},
79
+ {tag1: 'val 1', tag2: 'val 2'},
80
+ {TAG1: 'val 1', tag2: 'val 2'},
81
+ {'TAG-1': 'val 1', tag2: 'val 2'},
82
+ {'TAG_1': 'val 1', tag_2: 'val 2'},
83
+ {'TAG.1': 'val 1', tag_2: 'val 2'},
84
+ {'TAG-1': 'val 1', tag2: 'val 2'},
85
+ {tag1: '(>_<)', tag2: '^_^'}]
86
+ bad = ['key=value',
87
+ {'tag 1': 'val1', 'tag 2': 'val2'},
88
+ {'TAG*1': 'val 1', tag_2: 'val 2'},
89
+ {'(>_<)': 'val1', '^_^': 'val2'},
90
+ {tag1: 'v' * 255},
91
+ {'k' * 255 => 'val1'},
92
+ {'k' * 130 => 'v' * 130}]
93
+ good_and_bad('wf_point_tags?', 'InvalidTag', good, bad)
94
+ end
95
+
96
+ def test_wf_proxy_id?
97
+ good = %w(fd248f53-378e-4fbe-bbd3-efabace8d724
98
+ 917102d1-a10e-497b-ba63-95058f98d4fb)
99
+ bad = %w(proxy 17102d1-a10e-497b-ba63-95058f98d4fb)
100
+ good_and_bad('wf_proxy_id?', 'InvalidProxyId', good, bad)
101
+ end
102
+
103
+ def test_wf_cloudintegration_id?
104
+ good = %w(3b56f61d-ba79-47f6-905c-d75a0f613d10
105
+ 71e435ca-3d8c-43ab-bc1e-d072a335cbe6)
106
+ bad = %w(proxy 71e43dca-3d8c-41ab-bc1e-d072a335Xbe6)
107
+ good_and_bad('wf_cloudintegration_id?', 'InvalidCloudIntegrationId',
108
+ good, bad)
109
+ end
110
+
111
+ def test_wf_alert_id?
112
+ good = [1481553823153, '1481553823153']
113
+ bad = [481553823153, '481553823153', [], {}, 'alert']
114
+ good_and_bad('wf_alert_id?', 'InvalidAlertId', good, bad)
115
+ end
116
+
117
+ def test_wf_dashboard_id?
118
+ good = %w(my_dash my-dashboard S3 123)
119
+ bad = ['a' * 260, 'A Dashboard Name', 'and_1_more!', {}, [], 1234]
120
+ good_and_bad('wf_dashboard_id?', 'InvalidDashboardId', good, bad)
121
+ end
122
+
123
+ def test_wf_event_id?
124
+ good = %w(1493370839062:test1)
125
+ bad = %w(1493370839062 1493370839062:test!)
126
+ good_and_bad('wf_event_id?', 'InvalidEventId', good, bad)
127
+ end
128
+
129
+ def test_wf_version?
130
+ good = [1, 2, 3, 4, '10']
131
+ bad = [-1, 'ab', [1]]
132
+ good_and_bad('wf_version?', 'InvalidVersion', good, bad)
133
+ end
134
+
135
+ def test_wf_link_id?
136
+ good = %w(lq6rPlSg2CFMSrg6)
137
+ bad = %w(lq%rPlSg2CFMSrg6, lq6rPlSg2CFMSrg)
138
+ good_and_bad('wf_link_id?', 'InvalidExternalLinkId', good, bad)
139
+ end
140
+
141
+ def test_wf_link_template?
142
+ good = %w(http://link.xyz https://link.xyz/{{holder}})
143
+ bad = %w(link.xyz https:/link.xyz/{{holder}})
144
+ good_and_bad('wf_link_template?', 'InvalidLinkTemplate', good, bad)
145
+ end
146
+
147
+ def test_wf_maintenance_window_id?
148
+ good = ['1493324005091', 1493324005091, Time.now.to_i * 1000]
149
+ bad = [149332400509, '14933240050', Time.now, [], 'abcdef']
150
+ good_and_bad('wf_maintenance_window_id?', 'InvalidMaintenanceWindowId',
151
+ good, bad)
152
+ end
153
+
154
+ def test_wf_alert_severity?
155
+ good = %w(INFO SMOKE WARN SEVERE)
156
+ bad = %w(any THING else)
157
+ good_and_bad('wf_alert_severity?', 'InvalidAlertSeverity', good, bad)
158
+ end
159
+
160
+ def test_wf_granularity?
161
+ good = ['d', 'h', 'm', 's', :d, :h, :m, :s]
162
+ bad = [1, 'a', 'day', :hour]
163
+ good_and_bad('wf_granularity?', 'InvalidGranularity', good, bad)
164
+ end
165
+
166
+ def test_wf_savedsearch_id?
167
+ good = %w(e2hLH2FR)
168
+ bad = %w(e2hLH2F e2hLH2FRz)
169
+ good_and_bad('wf_savedsearch_id?', 'InvalidSavedSearchId', good, bad)
170
+ end
171
+
172
+ def test_wf_savedsearch_entity?
173
+ good = %w(EVENT MAINTENANCE_WINDOW DASHBOARD ALERT)
174
+ bad = %w(1 a day hour)
175
+ good_and_bad('wf_savedsearch_entity?',
176
+ 'InvalidSavedSearchEntity', good, bad)
177
+ end
178
+
179
+ def test_wf_user_id?
180
+ good = %w(Some.User@example.com general99+specific@somewhere.net someone@somewhere.com)
181
+ bad = %w(word Name)
182
+ good_and_bad('wf_user_id?', 'InvalidUserId', good, bad)
183
+ end
184
+
185
+ def test_wf_webhook_id?
186
+ good = %w(4OfsEM8RcvkM7nwG)
187
+ bad = %w(4OfsEM8RcvkM7n 4OfsEM8Rcvk-7nw)
188
+ good_and_bad('wf_webhook_id?', 'InvalidWebhookId', good, bad)
189
+ end
190
+
191
+ def test_wf_point?
192
+ good = { path: 'test.metric', value: 123456, ts: Time.now.to_i,
193
+ source: 'testhost', tags: { t1: 'v 1', t2: 'v2' } }
194
+
195
+ assert(wf_point?(good))
196
+
197
+ %w(tags source ts).each do |t|
198
+ p = good.dup
199
+ p.delete(t)
200
+ assert(wf_point?(p))
201
+ end
202
+
203
+ bad = good.dup
204
+ bad[:path] = '!n\/@1!d_metric'
205
+
206
+ assert_raises(Wavefront::Exception::InvalidMetricName) do
207
+ wf_point?(bad)
208
+ end
209
+
210
+ bad = good.dup
211
+ bad[:value] = 'abc'
212
+
213
+ assert_raises(Wavefront::Exception::InvalidMetricValue) do
214
+ wf_point?(bad)
215
+ end
216
+
217
+ bad = good.dup
218
+ bad[:ts] = 'abc'
219
+
220
+ assert_raises(Wavefront::Exception::InvalidTimestamp) do
221
+ wf_point?(bad)
222
+ end
223
+
224
+ bad = good.dup
225
+ bad[:source] = '<------>'
226
+
227
+ assert_raises(Wavefront::Exception::InvalidSourceId) do
228
+ wf_point?(bad)
229
+ end
230
+
231
+ bad = good.dup
232
+ bad[:tags] = {'<------>': 45}
233
+
234
+ assert_raises(Wavefront::Exception::InvalidTag) do
235
+ wf_point?(bad)
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ WEBHOOK = '9095WaGklE8Gy3M1'.freeze
6
+
7
+ WEBHOOK_BODY = {
8
+ description: 'WebHook Description',
9
+ template: 'POST Body -- Mustache syntax',
10
+ title: 'WebHook Title',
11
+ triggers: %w(ALERT_OPENED),
12
+ recipient: 'http://example.com',
13
+ customHttpHeaders: {},
14
+ contentType: 'text/plain'
15
+ }.freeze
16
+
17
+ # Unit tests for Webhook class
18
+ #
19
+ class WavefrontWebhookTest < WavefrontTestBase
20
+ def test_list
21
+ should_work(:list, 10, '?offset=10&limit=100')
22
+ should_work(:list, [20, 30], '?offset=20&limit=30')
23
+ end
24
+
25
+ def test_describe
26
+ should_work(:describe, WEBHOOK, WEBHOOK)
27
+ should_be_invalid(:describe, 'abcdefg')
28
+ assert_raises(ArgumentError) { wf.describe }
29
+ end
30
+
31
+ def test_create
32
+ should_work(:create, WEBHOOK_BODY, '', :post,
33
+ JSON_POST_HEADERS, WEBHOOK_BODY.to_json)
34
+ assert_raises(ArgumentError) { wf.create }
35
+ assert_raises(ArgumentError) { wf.create('test') }
36
+ end
37
+
38
+ def test_delete
39
+ should_work(:delete, WEBHOOK, WEBHOOK, :delete)
40
+ should_be_invalid(:delete, 'abcdefg')
41
+ assert_raises(ArgumentError) { wf.delete }
42
+ end
43
+
44
+ def test_update
45
+ should_work(:update, [WEBHOOK, WEBHOOK_BODY], WEBHOOK, :put,
46
+ JSON_POST_HEADERS, WEBHOOK_BODY.to_json)
47
+ should_be_invalid(:update, ['abcde', WEBHOOK_BODY])
48
+ assert_raises(ArgumentError) { wf.update }
49
+ end
50
+ end
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../../lib/wavefront-sdk/write.rb'
4
+ require 'minitest/autorun'
5
+ require 'webmock/minitest'
6
+ require 'spy'
7
+ require 'spy/integration'
8
+ require 'socket'
9
+
10
+ W_CREDS = { proxy: 'wavefront', port: 2878 }.freeze
11
+
12
+ TAGS = { gt1: 'gv1', gt2: 'gv2' }.freeze
13
+
14
+ POINT = { path: 'test.metric',
15
+ value: 123_456,
16
+ ts: 1_469_987_572,
17
+ source: 'testhost',
18
+ tags: { t1: 'v1', t2: 'v2' } }.freeze
19
+
20
+ POINT_L = 'test.metric 123456 1469987572 source=testhost t1="v1" t2="v2"'.freeze
21
+
22
+ POINT_A = [
23
+ POINT, POINT.dup.update(ts: 1_469_987_588, value: 54_321)
24
+ ].freeze
25
+
26
+ # This class is sufficiently different to the API calling classes
27
+ # that it doesn't use spec helper or inherit anything.
28
+ #
29
+ class WavefrontWriteTest < MiniTest::Test
30
+ attr_reader :wf, :wf_noop, :wf_tags
31
+
32
+ def setup
33
+ @wf = Wavefront::Write.new(W_CREDS)
34
+ @wf_noop = Wavefront::Write.new(W_CREDS, noop: true)
35
+ @wf_tags = Wavefront::Write.new(W_CREDS, tags: TAGS)
36
+ end
37
+
38
+ def test_initialize
39
+ refute(wf.opts[:tags])
40
+ refute(wf.opts[:verbose])
41
+ refute(wf.opts[:debug])
42
+ refute(wf.opts[:noop])
43
+ assert(wf_noop.opts[:noop])
44
+ assert_equal(wf_tags.opts[:tags], TAGS)
45
+ assert_equal(wf.summary, sent: 0, rejected: 0, unsent: 0)
46
+ end
47
+
48
+ def test_write_openclose
49
+ mocket = Mocket.new
50
+ Spy.on(TCPSocket, :new).and_return(mocket)
51
+ mocket_spy = Spy.on(mocket, :puts)
52
+ wf.write(POINT)
53
+ assert mocket_spy.has_been_called?
54
+ end
55
+
56
+ def test_write_noop
57
+ mocket = Mocket.new
58
+ Spy.on(TCPSocket, :new).and_return(mocket)
59
+ mocket_spy = Spy.on(mocket, :puts)
60
+ wf_noop.open
61
+ wf_noop.write(POINT, false)
62
+ refute mocket_spy.has_been_called?
63
+ end
64
+
65
+ def test_write_noop_openclose
66
+ mocket = Mocket.new
67
+ Spy.on(TCPSocket, :new).and_return(mocket)
68
+ mocket_spy = Spy.on(mocket, :puts)
69
+ wf_noop.write(POINT)
70
+ refute mocket_spy.has_been_called?
71
+ end
72
+
73
+ def test_write
74
+ mocket = Mocket.new
75
+ Spy.on(TCPSocket, :new).and_return(mocket)
76
+ mocket_spy = Spy.on(mocket, :puts)
77
+ wf.open
78
+ wf.write(POINT, false)
79
+ assert mocket_spy.has_been_called?
80
+ end
81
+
82
+ def test_write_array
83
+ mocket = Mocket.new
84
+ Spy.on(TCPSocket, :new).and_return(mocket)
85
+ mocket_spy = Spy.on(mocket, :puts)
86
+ wf.open
87
+ wf.write(POINT_A, false)
88
+ assert mocket_spy.has_been_called?
89
+ end
90
+
91
+ def test_hash_to_wf
92
+ assert_equal(wf.hash_to_wf(POINT),
93
+ 'test.metric 123456 1469987572 ' \
94
+ 'source=testhost t1="v1" t2="v2"')
95
+ assert_equal(wf_tags.hash_to_wf(POINT),
96
+ 'test.metric 123456 1469987572 ' \
97
+ 'source=testhost t1="v1" t2="v2" ' \
98
+ 'gt1="gv1" gt2="gv2"')
99
+
100
+ p1 = POINT.dup
101
+ p1.delete(:ts)
102
+ assert_equal(wf.hash_to_wf(p1),
103
+ 'test.metric 123456 source=testhost t1="v1" t2="v2"')
104
+
105
+ p2 = POINT.dup
106
+ p2.delete(:tags)
107
+ assert_equal(wf.hash_to_wf(p2),
108
+ 'test.metric 123456 1469987572 source=testhost')
109
+
110
+ [:value, :path].each do |k|
111
+ p3 = POINT.dup
112
+ p3.delete(k)
113
+
114
+ assert_raises(Wavefront::Exception::InvalidPoint) do
115
+ wf.hash_to_wf(p3)
116
+ end
117
+
118
+ assert_raises(Wavefront::Exception::InvalidPoint) do
119
+ wf_tags.hash_to_wf(p3)
120
+ end
121
+ end
122
+ end
123
+
124
+ def test_to_wf_tag
125
+ assert_equal({}.to_wf_tag, '')
126
+ assert_equal(TAGS.to_wf_tag, 'gt1="gv1" gt2="gv2"')
127
+ end
128
+
129
+ def test_send_point
130
+ mocket = Mocket.new
131
+ Spy.on(TCPSocket, :new).and_return(mocket)
132
+ mocket_spy = Spy.on(mocket, :puts)
133
+ wf.open
134
+ wf.send_point(POINT_L)
135
+ assert mocket_spy.has_been_called_with?(POINT_L)
136
+ end
137
+
138
+ def test_noop_send_point
139
+ mocket = Mocket.new
140
+ Spy.on(TCPSocket, :new).and_return(mocket)
141
+ mocket_spy = Spy.on(mocket, :puts)
142
+ wf_noop.open
143
+ wf_noop.send_point(POINT_L)
144
+ refute mocket_spy.has_been_called?
145
+ end
146
+
147
+ def test_open
148
+ tcp_spy = Spy.on(TCPSocket, :new)
149
+ wf.open
150
+ assert tcp_spy.has_been_called?
151
+ assert_equal(tcp_spy.calls.first.args, ['wavefront', 2878])
152
+ end
153
+
154
+ def test_noop_open
155
+ tcp_spy = Spy.on(TCPSocket, :new)
156
+ wf_noop.open
157
+ refute tcp_spy.has_been_called?
158
+ end
159
+ end
160
+
161
+ # A mock socket
162
+ #
163
+ class Mocket
164
+ def puts(s); end
165
+
166
+ def close; end
167
+ end