wavefront-sdk 0.0.1

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 (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