wavefront-cli 8.3.0 → 8.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +37 -0
  3. data/.github/workflows/test.yml +23 -0
  4. data/.rubocop.yml +10 -6
  5. data/HISTORY.md +21 -1
  6. data/lib/wavefront-cli/base.rb +3 -0
  7. data/lib/wavefront-cli/commands/.rubocop.yml +2 -13
  8. data/lib/wavefront-cli/commands/event.rb +8 -6
  9. data/lib/wavefront-cli/commands/serviceaccount.rb +6 -4
  10. data/lib/wavefront-cli/controller.rb +9 -0
  11. data/lib/wavefront-cli/display/base.rb +3 -2
  12. data/lib/wavefront-cli/display/printer/sparkline.rb +1 -1
  13. data/lib/wavefront-cli/display/serviceaccount.rb +12 -4
  14. data/lib/wavefront-cli/event.rb +50 -166
  15. data/lib/wavefront-cli/event_store.rb +177 -0
  16. data/lib/wavefront-cli/exception.rb +21 -0
  17. data/lib/wavefront-cli/exception_handler.rb +4 -0
  18. data/lib/wavefront-cli/opt_handler.rb +1 -1
  19. data/lib/wavefront-cli/query.rb +1 -1
  20. data/lib/wavefront-cli/serviceaccount.rb +16 -6
  21. data/lib/wavefront-cli/settings.rb +3 -4
  22. data/lib/wavefront-cli/stdlib/string.rb +1 -1
  23. data/lib/wavefront-cli/version.rb +1 -1
  24. data/lib/wavefront-cli/write.rb +1 -1
  25. data/spec/.rubocop.yml +2 -17
  26. data/spec/spec_helper.rb +0 -1
  27. data/spec/support/minitest_assertions.rb +2 -2
  28. data/spec/wavefront-cli/commands/base_spec.rb +2 -2
  29. data/spec/wavefront-cli/commands/config_spec.rb +1 -1
  30. data/spec/wavefront-cli/controller_spec.rb +14 -0
  31. data/spec/wavefront-cli/event_spec.rb +69 -109
  32. data/spec/wavefront-cli/event_store_spec.rb +186 -0
  33. data/spec/wavefront-cli/opt_handler_spec.rb +3 -3
  34. data/spec/wavefront-cli/serviceaccount_spec.rb +53 -21
  35. data/wavefront-cli.gemspec +5 -2
  36. metadata +62 -10
  37. data/.travis.yml +0 -20
@@ -22,6 +22,18 @@ class WavefrontCliHelpTest < MiniTest::Test
22
22
  assert_match(/^ \w+ --help$/, e.message)
23
23
  end
24
24
 
25
+ def test_commands_no_args
26
+ SupportedCommands.new.all.each do |cmd|
27
+ _test_command_no_args(cmd)
28
+ end
29
+ end
30
+
31
+ def _test_command_no_args(cmd)
32
+ capture_io { WavefrontCliController.new([cmd]) }
33
+ rescue SystemExit => e
34
+ assert e.message.end_with?("wf #{cmd} --help")
35
+ end
36
+
25
37
  def test_version
26
38
  capture_io { WavefrontCliController.new(%w[--version]) }
27
39
  rescue SystemExit => e
@@ -40,6 +52,7 @@ class WavefrontCliHelpTest < MiniTest::Test
40
52
  end
41
53
  end
42
54
 
55
+ # rubocop:disable Style/RedundantBegin
43
56
  def test_command_help
44
57
  SupportedCommands.new.all.each do |cmd|
45
58
  begin
@@ -54,6 +67,7 @@ class WavefrontCliHelpTest < MiniTest::Test
54
67
  end
55
68
  end
56
69
  end
70
+ # rubocop:enable Style/RedundantBegin
57
71
 
58
72
  def test_malformed_config
59
73
  capture_io do
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'tmpdir'
5
5
  require_relative '../support/command_base'
6
+ require_relative '../test_mixins/tag'
6
7
  require_relative '../../lib/wavefront-cli/event'
7
8
  require 'wavefront-sdk/support/mixins'
8
9
 
@@ -15,12 +16,11 @@ class EventEndToEndTest < EndToEndTest
15
16
  attr_reader :test_state_dir
16
17
 
17
18
  include Wavefront::Mixins
18
- include WavefrontCliTest::Describe
19
- include WavefrontCliTest::Delete
20
- # Ones above work, ones below don't
19
+ # include WavefrontCliTest::Describe
20
+ # include WavefrontCliTest::Delete
21
21
  # include WavefrontCliTest::Search
22
- # include WavefrontCliTest::Set
23
- # include WavefrontCliTest::Tags
22
+ # #include WavefrontCliTest::Set
23
+ # include WavefrontCliTest::Tag
24
24
 
25
25
  def before_setup
26
26
  @test_state_dir = Pathname.new(Dir.mktmpdir)
@@ -31,11 +31,6 @@ class EventEndToEndTest < EndToEndTest
31
31
  FileUtils.rm_r(test_state_dir)
32
32
  end
33
33
 
34
- def cmd_instance
35
- cmd_class.new(event_state_dir: TEST_EVENT_DIR)
36
- puts cmd_class
37
- end
38
-
39
34
  def test_list_no_options
40
35
  str = '/api/v2/event\?' \
41
36
  'earliestStartTimeEpochMillis=\d{13}+&' \
@@ -65,6 +60,22 @@ class EventEndToEndTest < EndToEndTest
65
60
  end
66
61
  end
67
62
 
63
+ def test_show_with_no_local_events
64
+ assert_exits_with('No locally recorded events.', 'show')
65
+ end
66
+
67
+ def test_show
68
+ setup_test_state_dir
69
+
70
+ out, err = capture_io do
71
+ assert_raises(SystemExit) { wf.new("event show -c #{CF}".split) }
72
+ end
73
+
74
+ assert_empty(err)
75
+ assert_equal("1568133440530:ev3:0\n1568133440520:ev2:0\n" \
76
+ "1568133440515:ev1:1\n1568133440510:ev1:0\n", out)
77
+ end
78
+
68
79
  def test_create
69
80
  mock_id = "#{start_time}:#{event_name}:1"
70
81
  state_file = state_dir + mock_id
@@ -100,8 +111,8 @@ class EventEndToEndTest < EndToEndTest
100
111
  refute state_file.exist?
101
112
 
102
113
  out, err = capture_io do
103
- assert_cmd_posts('create -d reason -H host1 -H host2 -g ' \
104
- "mytag #{event_name}",
114
+ assert_cmd_posts('create -d reason -H host1 -H host2 -g mytag ' \
115
+ "#{event_name}",
105
116
  '/api/v2/event',
106
117
  { name: event_name,
107
118
  startTime: a_ms_timestamp,
@@ -148,15 +159,6 @@ class EventEndToEndTest < EndToEndTest
148
159
  assert_match(/\ntags tag1\n tag2\n/, out)
149
160
  end
150
161
 
151
- def test_close_named_event
152
- quietly do
153
- assert_cmd_posts('close 1568133440520:ev2:0',
154
- '/api/v2/event/1568133440520:ev2:0/close')
155
- end
156
-
157
- assert_abort_on_missing_creds("close #{id}")
158
- end
159
-
160
162
  def test_close_with_no_local_events
161
163
  quietly { assert_cmd_posts("close #{id}", "/api/v2/event/#{id}/close") }
162
164
  assert_exits_with('No locally recorded events.', 'close')
@@ -212,26 +214,47 @@ class EventEndToEndTest < EndToEndTest
212
214
  end
213
215
  end
214
216
 
215
- def test_show
216
- setup_test_state_dir
217
+ def test_window_start
218
+ wfse = WavefrontCli::Event.new(start: wall_time[0], end: wall_time[1])
219
+ assert_kind_of(Numeric, wfse.window_start)
220
+ assert_equal(epoch_ms_time[0], wfse.window_start)
221
+ end
217
222
 
218
- out, err = capture_io do
219
- assert_raises(SystemExit) { wf.new("event show -c #{CF}".split) }
220
- end
223
+ def test_window_end
224
+ wfse = WavefrontCli::Event.new(start: wall_time[0], end: wall_time[1])
225
+ assert_kind_of(Numeric, wfse.window_end)
226
+ assert_equal(epoch_ms_time[1], wfse.window_end)
227
+ end
221
228
 
222
- assert_empty(err)
223
- assert_equal("1568133440530:ev3:0\n1568133440520:ev2:0\n" \
224
- "1568133440515:ev1:1\n1568133440510:ev1:0\n", out)
229
+ def test_list_args_defaults
230
+ wfe = WavefrontCli::Event.new({})
231
+ x = wfe.list_args
232
+ assert_instance_of(Array, x)
233
+ assert_equal(4, x.size)
234
+ assert_in_delta(((Time.now - 600).to_i * 1000), x[0], 1000)
235
+ assert_in_delta((Time.now.to_i * 1000), x[1], 1000)
236
+ assert_equal(100, x[2])
237
+ assert_nil(x[3])
238
+ end
239
+
240
+ def test_list_args_options
241
+ wfse = WavefrontCli::Event.new(limit: 55,
242
+ start: wall_time[0],
243
+ cursor: id,
244
+ end: wall_time[1])
245
+ x = wfse.list_args
246
+ assert_instance_of(Array, x)
247
+ assert_equal(4, x.size)
248
+ assert_equal(epoch_ms_time[0], x[0])
249
+ assert_equal(epoch_ms_time[1], x[1])
250
+ assert_equal(55, x[2])
251
+ assert_equal(id, x[3])
225
252
  end
226
253
 
227
254
  private
228
255
 
229
256
  def id
230
- '1481553823153:testev'
231
- end
232
-
233
- def event_name
234
- 'test_event'
257
+ '1481553823153:testev:0'
235
258
  end
236
259
 
237
260
  def invalid_id
@@ -242,18 +265,24 @@ class EventEndToEndTest < EndToEndTest
242
265
  'event'
243
266
  end
244
267
 
268
+ def event_name
269
+ 'test_event'
270
+ end
271
+
245
272
  def start_time
246
273
  1_481_553_823_153
247
274
  end
248
275
 
249
- def import_fields
250
- %i[method title creatorId triggers template]
276
+ def epoch_ms_time
277
+ wall_time.map { |t| (t.to_i * 1000) }
251
278
  end
252
279
 
253
280
  def state_dir
254
281
  test_state_dir + (Etc.getlogin || 'notty')
255
282
  end
256
283
 
284
+ # Puts some test events in the state directory
285
+ #
257
286
  def setup_test_state_dir
258
287
  FileUtils.mkdir_p(state_dir)
259
288
 
@@ -285,79 +314,10 @@ class EventEndToEndTest < EndToEndTest
285
314
  "https://#{perm[:endpoint]}/api/v2/event/#{mock_id}/close")
286
315
  .with(body: 'null')
287
316
  end
288
- end
289
-
290
- # Unit tests for class methods
291
- #
292
- class EventMethodTests < Minitest::Test
293
- attr_reader :wf, :wfse
294
-
295
- def setup
296
- @wf = WavefrontCli::Event.new({})
297
- @wfse = WavefrontCli::Event.new(start: wall_time[0],
298
- end: wall_time[1],
299
- limit: 55,
300
- cursor: '1481553823153:testev')
301
- end
302
-
303
- def test_create_dir_ok
304
- base = Pathname.new(Dir.mktmpdir)
305
- dir = base + 'testdir'
306
- refute dir.exist?
307
- wf.create_dir(dir)
308
- assert dir.exist?
309
- dir.unlink
310
- base.unlink
311
- end
312
-
313
- def test_create_dir_fail
314
- spy = Spy.on(FileUtils, :mkdir_p).and_return(false)
315
-
316
- assert_raises(WavefrontCli::Exception::SystemError) do
317
- wf.create_dir(Pathname.new('/any/old/directory'))
318
- end
319
-
320
- assert spy.has_been_called?
321
- spy.unhook
322
- end
323
-
324
- def test_list_args_defaults
325
- x = wf.list_args
326
- assert_instance_of(Array, x)
327
- assert_equal(4, x.size)
328
- assert_in_delta(((Time.now - 600).to_i * 1000), x[0], 1000)
329
- assert_in_delta((Time.now.to_i * 1000), x[1], 1000)
330
- assert_equal(100, x[2])
331
- assert_nil(x[3])
332
- end
333
-
334
- def test_list_args_options
335
- x = wfse.list_args
336
- assert_instance_of(Array, x)
337
- assert_equal(4, x.size)
338
- assert_equal(epoch_ms_time[0], x[0])
339
- assert_equal(epoch_ms_time[1], x[1])
340
- assert_equal(55, x[2])
341
- assert_equal('1481553823153:testev', x[3])
342
- end
343
-
344
- def test_window_start
345
- assert_kind_of(Numeric, wf.window_start)
346
- assert_equal(epoch_ms_time[0], wfse.window_start)
347
- end
348
-
349
- def test_window_end
350
- assert_kind_of(Numeric, wf.window_end)
351
- assert_equal(epoch_ms_time[1], wfse.window_end)
352
- end
353
317
 
354
- private
355
-
356
- def wall_time
357
- [Time.at(1_568_112_000), Time.at(1_568_112_999)]
358
- end
359
-
360
- def epoch_ms_time
361
- wall_time.map { |t| (t.to_i * 1000) }
318
+ # Event searching uses a cursor, not an offset
319
+ #
320
+ def cannot_handle_offsets
321
+ true
362
322
  end
363
323
  end
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'pathname'
5
+ require 'spy'
6
+ require 'minitest/autorun'
7
+ require_relative '../../lib/wavefront-cli/event_store'
8
+
9
+ TEST_EVENT_STORE_DIR = Pathname.new(Dir.mktmpdir)
10
+
11
+ # Tests for event store class. This is tested well via the interface of the
12
+ # events CLI class.
13
+ #
14
+ class Test < MiniTest::Test
15
+ attr_reader :wf
16
+
17
+ include WavefrontCli::Constants
18
+
19
+ def before_setup
20
+ FileUtils.mkdir_p(TEST_EVENT_STORE_DIR)
21
+ end
22
+
23
+ def setup
24
+ @wf = WavefrontCli::EventStore.new({}, TEST_EVENT_STORE_DIR)
25
+ end
26
+
27
+ def teardown
28
+ FileUtils.rm_r(TEST_EVENT_STORE_DIR)
29
+ end
30
+
31
+ def test_state_file_needed?
32
+ wf1 = WavefrontCli::EventStore.new({}, TEST_EVENT_STORE_DIR)
33
+ assert wf1.state_file_needed?
34
+
35
+ wf2 = WavefrontCli::EventStore.new({ nostate: true }, TEST_EVENT_STORE_DIR)
36
+ refute wf2.state_file_needed?
37
+
38
+ wf3 = WavefrontCli::EventStore.new({ instant: true }, TEST_EVENT_STORE_DIR)
39
+ refute wf3.state_file_needed?
40
+
41
+ wf4 = WavefrontCli::EventStore.new({ start: Time.now - 20, end: Time.now },
42
+ TEST_EVENT_STORE_DIR)
43
+ refute wf4.state_file_needed?
44
+ end
45
+
46
+ def test_event_file
47
+ x = wf.event_file(id)
48
+ assert_instance_of(Pathname, x)
49
+ assert_equal(wf.dir, x.dirname)
50
+ assert_equal(id, x.basename.to_s)
51
+
52
+ assert_nil(wf.event_file('not_a_valid_id'))
53
+ end
54
+
55
+ def test_create_dir_ok
56
+ dir = TEST_EVENT_STORE_DIR + 'testdir'
57
+ refute dir.exist?
58
+ wf.create_dir(dir)
59
+ assert dir.exist?
60
+ dir.unlink
61
+ end
62
+
63
+ def test_list
64
+ setup_test_state_dir
65
+
66
+ x = wf.list
67
+ assert(x.all? { |e| e.is_a?(Pathname) })
68
+ assert_equal(4, x.size)
69
+
70
+ empty_test_state_dir
71
+ end
72
+
73
+ def test_list_empty_stack
74
+ out, err = capture_io { assert_raises(SystemExit) { wf.list } }
75
+ assert_empty(out)
76
+ assert_equal("No locally recorded events.\n", err)
77
+ end
78
+
79
+ def test_pop_event
80
+ setup_test_state_dir
81
+
82
+ assert (wf.dir + '1568133440530:ev3:0').exist?
83
+ assert_equal('1568133440530:ev3:0', wf.pop_event!)
84
+ refute (wf.dir + '1568133440530:ev3:0').exist?
85
+
86
+ empty_test_state_dir
87
+ end
88
+
89
+ def test_pop_event_named
90
+ setup_test_state_dir
91
+
92
+ assert (wf.dir + '1568133440515:ev1:1').exist?
93
+ assert_equal('1568133440515:ev1:1', wf.pop_event!('ev1'))
94
+ refute (wf.dir + '1568133440515:ev1:1').exist?
95
+
96
+ empty_test_state_dir
97
+ end
98
+
99
+ def test_event_specific
100
+ setup_test_state_dir
101
+
102
+ assert (wf.dir + '1568133440515:ev1:1').exist?
103
+ assert_equal('1568133440515:ev1:1', wf.event('1568133440515:ev1:1'))
104
+ assert (wf.dir + '1568133440515:ev1:1').exist?
105
+
106
+ empty_test_state_dir
107
+ end
108
+
109
+ def test_pop_event_empty_stack
110
+ out, err = capture_io { assert_raises(SystemExit) { wf.pop_event! } }
111
+ assert_empty(out)
112
+ assert_equal("No locally recorded events.\n", err)
113
+ end
114
+
115
+ def test_event_state_dir
116
+ ENV['WF_EVENT_STATE_DIR'] = nil
117
+ assert_equal(EVENT_STATE_DIR, wf.event_state_dir)
118
+
119
+ ENV['WF_EVENT_STATE_DIR'] = '/tmp/tester'
120
+ assert_equal(Pathname.new('/tmp/tester'), wf.event_state_dir)
121
+ ENV['WF_EVENT_STATE_DIR'] = nil
122
+
123
+ assert_equal(Pathname.new('/tmp/mydir'), wf.event_state_dir('/tmp/mydir'))
124
+ end
125
+
126
+ def test_create_dir_fail
127
+ spy = Spy.on(FileUtils, :mkdir_p).and_return(false)
128
+
129
+ assert_raises(WavefrontCli::Exception::SystemError) do
130
+ wf.create_dir(Pathname.new('/any/old/directory'))
131
+ end
132
+
133
+ assert spy.has_been_called?
134
+ spy.unhook
135
+ end
136
+
137
+ def test_event_file_data
138
+ wf = WavefrontCli::EventStore.new({ desc: 'test event' },
139
+ TEST_EVENT_STORE_DIR)
140
+ x = wf.event_file_data
141
+ assert_instance_of(String, x)
142
+ y = JSON.parse(x, symbolize_names: true)
143
+ assert_equal('test event', y[:description])
144
+ assert_equal(%i[hosts description severity tags], y.keys)
145
+ assert_nil(y[:tags])
146
+ end
147
+
148
+ def test_create
149
+ refute (wf.dir + id).exist?
150
+ out, err = capture_io { wf.create!(id) }
151
+ assert_match(/Event state recorded at .*1481553823153:testev:0./, out)
152
+ assert_empty(err)
153
+ assert (wf.dir + id).exist?
154
+ end
155
+
156
+ def test_create_with_nostate
157
+ wf1 = WavefrontCli::EventStore.new(nostate: true)
158
+ assert_nil wf1.create!(id)
159
+ end
160
+
161
+ private
162
+
163
+ def id
164
+ '1481553823153:testev:0'
165
+ end
166
+
167
+ def dummy_event_files
168
+ %w[1568133440510:ev1:0
169
+ 1568133440515:ev1:1
170
+ 1568133440520:ev2:0
171
+ 1568133440530:ev3:0]
172
+ end
173
+
174
+ def setup_test_state_dir
175
+ dummy_event_files.each do |f|
176
+ File.open(wf.dir + f, 'w') { |fh| fh.puts('dummy_data') }
177
+ end
178
+ end
179
+
180
+ def empty_test_state_dir
181
+ dummy_event_files.each do |f|
182
+ file = wf.dir + f
183
+ FileUtils.rm(file) if file.exist?
184
+ end
185
+ end
186
+ end