wavefront-client 3.2.0 → 3.3.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.
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+ require 'pathname'
3
+ require 'json'
4
+ require 'erb'
5
+
6
+ # Valid alert states as defined in alerting.rb
7
+ #
8
+ states = %w(active affected_by_maintenance all invalid snoozed)
9
+ formats = %w(ruby json human)
10
+
11
+ opts = {
12
+ token: TEST_TOKEN,
13
+ }
14
+
15
+ describe Wavefront::Cli::Alerts do
16
+
17
+ describe '#run' do
18
+
19
+ it 'raises an exception if there are no arguments' do
20
+ k = Wavefront::Cli::Alerts.new(opts, [])
21
+ expect{k.run}.to raise_exception('Missing query.')
22
+ end
23
+ end
24
+
25
+ describe '#valid_state?' do
26
+ wfa = Wavefront::Alerting.new(TEST_TOKEN)
27
+
28
+ it 'raises an exception if the alert type is invalid' do
29
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
30
+ expect{k.valid_state?(wfa, 'nosuch_alert')}.to raise_exception(
31
+ RuntimeError, "State must be one of: #{states.join(', ')}.")
32
+ end
33
+
34
+ it 'accepts all valid states' do
35
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
36
+
37
+ states.each do |state|
38
+ expect(k.valid_state?(wfa, state.to_sym)).to be(true)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#valid_format?' do
44
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
45
+
46
+ it 'accepts valid formats as symbols and strings' do
47
+ formats.each do |fmt|
48
+ expect(k.valid_format?(fmt)).to be(true)
49
+ expect(k.valid_format?(fmt.to_s)).to be(true)
50
+ end
51
+ end
52
+
53
+ it 'raises an exception on an invalid format' do
54
+ expect{k.valid_format?('junk')}.to raise_exception( RuntimeError,
55
+ "Output format must be one of: #{formats.join(', ')}.")
56
+ end
57
+ end
58
+
59
+ describe '#format_result' do
60
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
61
+ res = "{\n \"a\": 1,\n \"b\": 2\n}"
62
+
63
+ it 'raises an error on unknown type' do
64
+ expect{k.format_result(res, :nonsense)}.to raise_exception(RuntimeError)
65
+ end
66
+
67
+ it 'pretty-prints when requested' do
68
+ expect{k.format_result(res, :ruby)}.to match_stdout(
69
+ "[{\n \"a\": 1,\n \"b\": 2\n}]")
70
+ end
71
+
72
+ it 'prints as JSON when requested' do
73
+ expect{k.format_result(res, :json)}.to match_stdout(res)
74
+ end
75
+
76
+ it 'reconstructs JSON output' do
77
+ src = IO.read(Pathname.new(__FILE__).dirname + 'resources' +
78
+ 'alert.raw')
79
+ out = IO.read(Pathname.new(__FILE__).dirname + 'resources' +
80
+ 'alert.json')
81
+ expect{k.format_result(src, :json)}.to match_stdout(out)
82
+ end
83
+ end
84
+
85
+ describe '#humanize' do
86
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
87
+ src = IO.read(Pathname.new(__FILE__).dirname + 'resources' +
88
+ 'alert.raw')
89
+ #
90
+ # The output has to get munged a bit here because it turns out
91
+ # that comparing multi-line things isn't anywhere near so
92
+ # straightforward as I expected.
93
+ #
94
+ it 'reconstructs human output' do
95
+ out = ERB.new(IO.read(Pathname.new(__FILE__).dirname +
96
+ 'resources' + 'alert.human.erb')).result
97
+ expect(k.humanize(JSON.parse(src)).join("\n") + "\n").to eq(out)
98
+ end
99
+ end
100
+
101
+ describe '#human_line' do
102
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
103
+ it 'prints in the correct format' do
104
+ expect(k.human_line('desc', 123)).to eq('desc 123')
105
+ end
106
+ end
107
+
108
+ describe '#human_line_created' do
109
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
110
+ it 'prints in the correct format' do
111
+ expect(k.human_line_created('time', 1469804504000)).to eq(
112
+ "time #{Time.at(1469804504)}")
113
+ end
114
+ end
115
+
116
+ describe '#human_line_hostsUsed' do
117
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
118
+
119
+ it 'just prints the header if there are no hosts' do
120
+ expect(k.human_line_hostsUsed('host', false)).to eq('host')
121
+ expect(k.human_line_hostsUsed('host', [])).to eq('host')
122
+ expect(k.human_line_hostsUsed('host', {})).to eq('host')
123
+ end
124
+
125
+ it 'prints in the correct format for a single host' do
126
+ expect(k.human_line_hostsUsed('host', ['hostname'])).to eq(
127
+ ['host hostname'])
128
+ end
129
+
130
+ it 'prints in the correct format for a multiple hosts' do
131
+ expect(k.human_line_hostsUsed('host', ['host1', 'host2'])).to eq(
132
+ ['host host1', ' host2'])
133
+ end
134
+ end
135
+
136
+ describe '#indent_wrap' do
137
+ k = Wavefront::Cli::Alerts.new(opts, ['all'])
138
+
139
+ it 'leaves short strings unchanged' do
140
+ expect(k.indent_wrap('short string')).to eq("short string")
141
+ end
142
+
143
+ it 'wraps long strings with a hanging indent' do
144
+ expect(k.indent_wrap('lots and lots of words which are ' +
145
+ 'altogether far too wide for an 80 column terminal to ' +
146
+ 'display without breaking at least once, especially with ' +
147
+ 'a hanging indent')).to eq(
148
+ "lots and lots of words which are altogether far too wide
149
+ for an 80 column terminal to display without breaking at
150
+ least once, especially with a hanging indent")
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,251 @@
1
+ require 'pathname'
2
+ require 'spec_helper'
3
+
4
+ opts = {}
5
+
6
+ describe '#run' do
7
+ end
8
+
9
+ describe '#load_data' do
10
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
11
+
12
+ it 'loads in a data file' do
13
+ expect(k.load_data(Pathname.new(__FILE__).dirname + 'resources' +
14
+ 'write.parabola').length).to eq(784)
15
+ end
16
+
17
+ it 'raises an error if the file does not exist' do
18
+ expect{k.load_data(Pathname.new('/no/such/file'))}.to raise_exception(
19
+ RuntimeError)
20
+ end
21
+ end
22
+
23
+ describe '#tags_to_hash' do
24
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
25
+
26
+ it 'parses a single tag' do
27
+ expect(k.tags_to_hash('key=value')).to eq(key: 'value')
28
+ end
29
+
30
+ it 'parses multiple tags' do
31
+ expect(k.tags_to_hash(['k1=v1', 'k2=v2', 'k3=v3'])).to eq(
32
+ {k1: 'v1', k2: 'v2', k3: 'v3'})
33
+ end
34
+
35
+ it 'skips tags with no value' do
36
+ expect(k.tags_to_hash(['k1=v1', 'k2v2', 'k3=v3'])).to eq(
37
+ {k1: 'v1', k3: 'v3'})
38
+ end
39
+
40
+ it 'handles tags containing an "="' do
41
+ expect(k.tags_to_hash(['k1=v1', 'k2=^=^', 'k3=v3'])).to eq(
42
+ {k1: 'v1', k2: '^=^', k3: 'v3'})
43
+ end
44
+
45
+ it 'silently handles things which are not arrays' do
46
+ expect(k.tags_to_hash({})).to eq({})
47
+ end
48
+
49
+ it 'deals with quoted tags' do
50
+ expect(k.tags_to_hash(["'k1'='v1'", '"k2"="v2"', 'k3="v3"'])).to eq(
51
+ {k1: 'v1', k2: 'v2', k3: 'v3'})
52
+ end
53
+ end
54
+
55
+ describe '#process_filedata' do
56
+ end
57
+
58
+ describe '#valid_format?' do
59
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
60
+ context 'valid format strings' do
61
+ %w(v vT tv tvT mv vm mvt mtv tmv mvT vmT mvtT tmvT).each do |fmt|
62
+ it 'accepts #{fmt}' do
63
+ expect(k.valid_format?(fmt)).to be true
64
+ end
65
+ end
66
+ end
67
+
68
+ context 'invalid format strings' do
69
+ %w(Tmv m mvTt amv mmv vv mvTm).each do |fmt|
70
+ it "rejects #{fmt}" do
71
+ expect(k.valid_format?(fmt)).to be_falsey
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#valid_line?' do
78
+ context 'using four columns including points tags' do
79
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
80
+ k.setup_fmt('mtvT')
81
+
82
+ it 'accepts four columns' do
83
+ expect(k.valid_line?('metric time value TAG1')).to be true
84
+ end
85
+
86
+ it 'accepts six columns' do
87
+ expect(k.valid_line?('metric time value TAG1 TAG2 TAG3')).to be true
88
+ end
89
+
90
+ it 'rejects three columns' do
91
+ expect(k.valid_line?('metric time value')).to be false
92
+ end
93
+ end
94
+
95
+ context 'using two columns, not including points tags' do
96
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
97
+ k.setup_fmt('mv')
98
+
99
+ it 'accepts two columns' do
100
+ expect(k.valid_line?('metric value')).to be true
101
+ end
102
+
103
+ it 'rejects three columns' do
104
+ expect(k.valid_line?('metric time TAG1')).to be false
105
+ end
106
+
107
+ it 'rejects one column' do
108
+ expect(k.valid_line?('metric')).to be false
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#valid_timestamp?' do
114
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
115
+
116
+ it 'accepts a valid timestamp as an integer' do
117
+ expect(k.valid_timestamp?(Time.now.to_i)).to be true
118
+ end
119
+
120
+ it 'accepts a valid timestamp as a string' do
121
+ expect(k.valid_timestamp?(Time.now.to_i.to_s)).to be true
122
+ end
123
+
124
+ it 'rejects a timestamp too far in the past' do
125
+ expect(k.valid_timestamp?(Time.new('1999-12-31').to_i)).to be false
126
+ end
127
+
128
+ it 'rejects a timestamp too far in the future' do
129
+ expect(k.valid_timestamp?((Date.today + 367).to_time.to_i)).to be false
130
+ end
131
+ end
132
+
133
+ describe '#valid_value?' do
134
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
135
+ context 'numerics' do
136
+ [-1, 0, 10, 1e6, 3.14].each do |n|
137
+ it "accepts #{n}" do
138
+ expect(k.valid_value?(n)).to be true
139
+ end
140
+ end
141
+ end
142
+
143
+ context 'strings' do
144
+ %w(-1 0 10 1e6 3.14).each do |n|
145
+ it "accepts #{n}" do
146
+ expect(k.valid_value?(n)).to be_truthy
147
+ end
148
+ end
149
+
150
+ %w(1-2 a --6 1.2.3).each do |s|
151
+ it "rejects #{s}" do
152
+ expect(k.valid_value?(s)).to be_falsey
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ describe '#process_line' do
159
+
160
+ context 'without metric prefix' do
161
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
162
+ k.setup_opts(opts)
163
+
164
+ it 'processes a four-field line' do
165
+ k.setup_fmt('mtvT')
166
+ expect(k.process_line('test_metric 1470176262 1234 t1="v1"')).to eq(
167
+ { path: 'test_metric',
168
+ ts: Time.at(1470176262),
169
+ source: HOSTNAME,
170
+ value: 1234,
171
+ tags: { t1: 'v1' }
172
+ })
173
+ end
174
+
175
+ it 'processes a four-field line with multiple tags' do
176
+ k.setup_fmt('mtvT')
177
+ expect(k.process_line('test_metric 1470176262 3.14 t1=v1 t2=v2 t3=v3')
178
+ ).to eq(
179
+ { path: 'test_metric',
180
+ ts: Time.at(1470176262),
181
+ source: HOSTNAME,
182
+ value: 3.14,
183
+ tags: { t1: 'v1', t2: 'v2', t3: 'v3' }
184
+ })
185
+ end
186
+
187
+ it 'skips a blank line' do
188
+ expect(k.process_line('')).to be true
189
+ end
190
+
191
+ it 'rejects a three-field line when expecting two fields' do
192
+ k.setup_fmt('mvt')
193
+ expect(k.process_line('3 1470176262')).to be false
194
+ expect{k.process_line('3 1470176262')}.to match_stdout(
195
+ 'WARNING: wrong number of fields. Skipping.')
196
+ end
197
+
198
+ it 'ignores dodgy tags' do
199
+ k.setup_fmt('mtvT')
200
+ expect(k.process_line('test_metric 1470176262 3.14 bad_tag')).to eq(
201
+ { path: 'test_metric',
202
+ ts: Time.at(1470176262),
203
+ source: HOSTNAME,
204
+ value: 3.14,
205
+ tags: {}
206
+ })
207
+ end
208
+ end
209
+
210
+ context 'with metric prefix' do
211
+ k = Wavefront::Cli::BatchWrite.new(opts, 'write')
212
+ k.setup_opts(metric: 'test_metric_3')
213
+
214
+ it 'rejects a two-field line with the fields backwards' do
215
+ k.setup_fmt('vt')
216
+ expect(k.process_line('1470176262 3.14')).to be false
217
+ expect{k.process_line('1470176262 3.14')}.to match_stdout(
218
+ "WARNING: invalid timestamp '3.14'. Skipping.")
219
+ end
220
+
221
+ it 'rejects a two-field line with an invalid value' do
222
+ k.setup_fmt('vt')
223
+ expect(k.process_line('x 1470176262')).to be false
224
+ expect{k.process_line('x 14701762624')}.to match_stdout(
225
+ "WARNING: invalid value 'x'. Skipping.")
226
+ end
227
+
228
+ it 'processes a two-field line with a CLI metric path' do
229
+ k.setup_fmt('tv')
230
+ expect(k.process_line('1470176262 3.14')
231
+ ).to eq(
232
+ { path: 'test_metric_3',
233
+ ts: Time.at(1470176262),
234
+ source: HOSTNAME,
235
+ value: 3.14,
236
+ })
237
+ end
238
+
239
+ it 'processes a two-field line with spacey tags' do
240
+ k.setup_fmt('tvT')
241
+ expect(k.process_line('1470176262 3.14 t1="value 1" t2="value 2"')
242
+ ).to eq(
243
+ { path: 'test_metric_3',
244
+ ts: Time.at(1470176262),
245
+ source: HOSTNAME,
246
+ value: 3.14,
247
+ tags: { t1: 'value 1', t2: 'value 2' }
248
+ })
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'pathname'
3
+ require 'json'
4
+
5
+ # Valid alert states as defined in alerting.rb
6
+ #
7
+ states = %w(active affected_by_maintenance all invalid snoozed)
8
+ formats = %w(ruby json human)
9
+
10
+ opts = {
11
+ token: TEST_TOKEN,
12
+ }
13
+
14
+ describe Wavefront::Cli::Alerts do
15
+
16
+ describe '#prep_time' do
17
+
18
+ [Time.now, 1469826353, 1469826353000,
19
+ '2016-07-29 22:05:51 +0100', '12:00', '2001-01-01'].each do |t|
20
+ it "converts time like '#{t}' (#{t.class}) into epoch ms" do
21
+ opts[:start] = t
22
+ k = Wavefront::Cli::Events.new(opts, [])
23
+ expect(k.prep_time(:start)).to be_kind_of(Numeric)
24
+ expect(k.prep_time(:start)).to be > 978307000000
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#prep_hosts' do
30
+ k = Wavefront::Cli::Events.new(opts, [])
31
+ k.hostname = 'this-host'
32
+
33
+ it 'returns the local hostname if nothing is given' do
34
+ expect(k.prep_hosts).to eq ['this-host']
35
+ end
36
+
37
+ it 'returns multiple hosts if an array is passed' do
38
+ expect(k.prep_hosts('host-a,host-b,host-c')).to eq(
39
+ ['host-a', 'host-b', 'host-c'])
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,14 @@
1
+ name Test Alert
2
+ created <%= Time.at(1469807662271 / 1000) %>
3
+ severity WARN
4
+ condition ts("dev.cli.test_metric") > 0
5
+ displayExpression ts("dev.cli.test_metric")
6
+ minutes 5
7
+ resolveAfterMinutes
8
+ updated <%= Time.at(1469807735018 / 1000) %>
9
+ alertStates CHECKING
10
+ metricsUsed
11
+ hostsUsed
12
+ additionalInformation This alert has been made up to feed into the test
13
+ framework for the Ruby CLI. It is not real. Even this
14
+ text is just placeholder text.