wavefront-client 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.