wavefront-cli 4.2.1 → 4.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.rubocop.yml +1 -14
- data/.travis.yml +4 -4
- data/Gemfile +2 -0
- data/HISTORY.md +82 -60
- data/Rakefile +2 -0
- data/bin/wf +1 -0
- data/lib/wavefront-cli/alert.rb +13 -5
- data/lib/wavefront-cli/apitoken.rb +2 -0
- data/lib/wavefront-cli/base.rb +95 -47
- data/lib/wavefront-cli/cloudintegration.rb +6 -0
- data/lib/wavefront-cli/command_mixins/acl.rb +6 -1
- data/lib/wavefront-cli/command_mixins/tag.rb +2 -0
- data/lib/wavefront-cli/commands/.rubocop.yml +3 -4
- data/lib/wavefront-cli/commands/alert.rb +2 -1
- data/lib/wavefront-cli/commands/apitoken.rb +6 -0
- data/lib/wavefront-cli/commands/base.rb +30 -21
- data/lib/wavefront-cli/commands/cloudintegration.rb +2 -0
- data/lib/wavefront-cli/commands/config.rb +2 -0
- data/lib/wavefront-cli/commands/dashboard.rb +2 -0
- data/lib/wavefront-cli/commands/derivedmetric.rb +2 -0
- data/lib/wavefront-cli/commands/event.rb +3 -1
- data/lib/wavefront-cli/commands/integration.rb +2 -1
- data/lib/wavefront-cli/commands/link.rb +2 -0
- data/lib/wavefront-cli/commands/message.rb +2 -0
- data/lib/wavefront-cli/commands/metric.rb +2 -0
- data/lib/wavefront-cli/commands/notificant.rb +2 -0
- data/lib/wavefront-cli/commands/proxy.rb +2 -0
- data/lib/wavefront-cli/commands/query.rb +2 -0
- data/lib/wavefront-cli/commands/savedsearch.rb +2 -0
- data/lib/wavefront-cli/commands/serviceaccount.rb +58 -0
- data/lib/wavefront-cli/commands/settings.rb +2 -0
- data/lib/wavefront-cli/commands/source.rb +3 -1
- data/lib/wavefront-cli/commands/user.rb +4 -1
- data/lib/wavefront-cli/commands/usergroup.rb +3 -0
- data/lib/wavefront-cli/commands/webhook.rb +2 -0
- data/lib/wavefront-cli/commands/window.rb +2 -0
- data/lib/wavefront-cli/commands/write.rb +2 -0
- data/lib/wavefront-cli/config.rb +23 -12
- data/lib/wavefront-cli/constants.rb +10 -4
- data/lib/wavefront-cli/controller.rb +53 -22
- data/lib/wavefront-cli/dashboard.rb +3 -0
- data/lib/wavefront-cli/derivedmetric.rb +12 -11
- data/lib/wavefront-cli/display/alert.rb +7 -4
- data/lib/wavefront-cli/display/apitoken.rb +2 -0
- data/lib/wavefront-cli/display/base.rb +34 -8
- data/lib/wavefront-cli/display/cloudintegration.rb +4 -2
- data/lib/wavefront-cli/display/dashboard.rb +2 -0
- data/lib/wavefront-cli/display/derivedmetric.rb +2 -0
- data/lib/wavefront-cli/display/distribution.rb +2 -0
- data/lib/wavefront-cli/display/event.rb +2 -0
- data/lib/wavefront-cli/display/externallink.rb +2 -0
- data/lib/wavefront-cli/display/integration.rb +2 -0
- data/lib/wavefront-cli/display/maintenancewindow.rb +2 -0
- data/lib/wavefront-cli/display/message.rb +7 -3
- data/lib/wavefront-cli/display/metric.rb +3 -1
- data/lib/wavefront-cli/display/notificant.rb +3 -1
- data/lib/wavefront-cli/display/printer/long.rb +36 -11
- data/lib/wavefront-cli/display/printer/sparkline.rb +3 -0
- data/lib/wavefront-cli/display/printer/terse.rb +6 -1
- data/lib/wavefront-cli/display/proxy.rb +2 -0
- data/lib/wavefront-cli/display/query.rb +35 -24
- data/lib/wavefront-cli/display/savedsearch.rb +2 -0
- data/lib/wavefront-cli/display/serviceaccount.rb +60 -0
- data/lib/wavefront-cli/display/settings.rb +2 -0
- data/lib/wavefront-cli/display/source.rb +18 -4
- data/lib/wavefront-cli/display/user.rb +56 -10
- data/lib/wavefront-cli/display/usergroup.rb +25 -19
- data/lib/wavefront-cli/display/webhook.rb +2 -0
- data/lib/wavefront-cli/display/write.rb +6 -2
- data/lib/wavefront-cli/event.rb +83 -62
- data/lib/wavefront-cli/exception.rb +3 -0
- data/lib/wavefront-cli/externallink.rb +6 -4
- data/lib/wavefront-cli/integration.rb +2 -0
- data/lib/wavefront-cli/maintenancewindow.rb +28 -17
- data/lib/wavefront-cli/message.rb +4 -0
- data/lib/wavefront-cli/metric.rb +4 -1
- data/lib/wavefront-cli/notificant.rb +2 -0
- data/lib/wavefront-cli/opt_handler.rb +2 -0
- data/lib/wavefront-cli/output/base.rb +8 -3
- data/lib/wavefront-cli/output/csv.rb +2 -0
- data/lib/wavefront-cli/output/csv/base.rb +2 -0
- data/lib/wavefront-cli/output/csv/query.rb +14 -7
- data/lib/wavefront-cli/output/hcl.rb +2 -0
- data/lib/wavefront-cli/output/hcl/alert.rb +2 -0
- data/lib/wavefront-cli/output/hcl/base.rb +10 -4
- data/lib/wavefront-cli/output/hcl/dashboard.rb +17 -8
- data/lib/wavefront-cli/output/hcl/notificant.rb +2 -0
- data/lib/wavefront-cli/output/hcl/stdlib/array.rb +2 -0
- data/lib/wavefront-cli/output/hcl/stdlib/string.rb +2 -0
- data/lib/wavefront-cli/output/json.rb +2 -0
- data/lib/wavefront-cli/output/ruby.rb +2 -0
- data/lib/wavefront-cli/output/wavefront.rb +2 -0
- data/lib/wavefront-cli/output/wavefront/query.rb +7 -4
- data/lib/wavefront-cli/output/yaml.rb +2 -0
- data/lib/wavefront-cli/proxy.rb +15 -3
- data/lib/wavefront-cli/query.rb +14 -12
- data/lib/wavefront-cli/savedsearch.rb +2 -0
- data/lib/wavefront-cli/serviceaccount.rb +179 -0
- data/lib/wavefront-cli/settings.rb +2 -0
- data/lib/wavefront-cli/source.rb +2 -0
- data/lib/wavefront-cli/stdlib/array.rb +3 -0
- data/lib/wavefront-cli/stdlib/string.rb +17 -11
- data/lib/wavefront-cli/user.rb +10 -4
- data/lib/wavefront-cli/usergroup.rb +4 -2
- data/lib/wavefront-cli/version.rb +3 -1
- data/lib/wavefront-cli/webhook.rb +2 -0
- data/lib/wavefront-cli/write.rb +80 -46
- data/spec/.rubocop.yml +3 -16
- data/spec/constants.rb +21 -0
- data/spec/spec_helper.rb +8 -422
- data/spec/support/command_base.rb +82 -0
- data/spec/support/minitest_assertions.rb +262 -0
- data/spec/support/output_tester.rb +32 -0
- data/spec/support/supported_commands.rb +19 -0
- data/spec/test_mixins/acl.rb +169 -0
- data/spec/test_mixins/delete.rb +25 -0
- data/spec/test_mixins/deleteundelete.rb +106 -0
- data/spec/test_mixins/describe.rb +24 -0
- data/spec/test_mixins/dump.rb +43 -0
- data/spec/test_mixins/general.rb +11 -0
- data/spec/test_mixins/history.rb +35 -0
- data/spec/test_mixins/import.rb +65 -0
- data/spec/test_mixins/list.rb +29 -0
- data/spec/test_mixins/search.rb +98 -0
- data/spec/test_mixins/set.rb +47 -0
- data/spec/test_mixins/tag.rb +99 -0
- data/spec/wavefront-cli/alert_spec.rb +288 -111
- data/spec/wavefront-cli/apitoken_spec.rb +53 -24
- data/spec/wavefront-cli/base_spec.rb +9 -27
- data/spec/wavefront-cli/cloudintegration_spec.rb +65 -29
- data/spec/wavefront-cli/commands/alert_spec.rb +1 -0
- data/spec/wavefront-cli/commands/base_spec.rb +15 -13
- data/spec/wavefront-cli/commands/cloudintegration_spec.rb +1 -0
- data/spec/wavefront-cli/commands/config_spec.rb +3 -0
- data/spec/wavefront-cli/commands/dashboard_spec.rb +1 -0
- data/spec/wavefront-cli/commands/derivedmetric_spec.rb +1 -0
- data/spec/wavefront-cli/commands/event_spec.rb +1 -0
- data/spec/wavefront-cli/commands/link_spec.rb +1 -0
- data/spec/wavefront-cli/commands/message_spec.rb +1 -0
- data/spec/wavefront-cli/commands/metric_spec.rb +1 -0
- data/spec/wavefront-cli/commands/proxy_spec.rb +1 -0
- data/spec/wavefront-cli/commands/query_spec.rb +1 -0
- data/spec/wavefront-cli/commands/webhook_spec.rb +1 -0
- data/spec/wavefront-cli/commands/window_spec.rb +1 -0
- data/spec/wavefront-cli/commands/write_spec.rb +1 -0
- data/spec/wavefront-cli/config_spec.rb +25 -14
- data/spec/wavefront-cli/controller_spec.rb +13 -3
- data/spec/wavefront-cli/dashboard_spec.rb +125 -76
- data/spec/wavefront-cli/derivedmetric_spec.rb +83 -67
- data/spec/wavefront-cli/display/base_spec.rb +5 -7
- data/spec/wavefront-cli/display/printer/long_spec.rb +20 -16
- data/spec/wavefront-cli/display/printer/terse_spec.rb +5 -4
- data/spec/wavefront-cli/event_spec.rb +360 -18
- data/spec/wavefront-cli/externallink_spec.rb +92 -58
- data/spec/wavefront-cli/integration_spec.rb +129 -31
- data/spec/wavefront-cli/maintenancewindow_spec.rb +270 -32
- data/spec/wavefront-cli/message_spec.rb +73 -30
- data/spec/wavefront-cli/metric_spec.rb +60 -22
- data/spec/wavefront-cli/notificant_spec.rb +45 -32
- data/spec/wavefront-cli/opt_handler_spec.rb +4 -1
- data/spec/wavefront-cli/output/csv/query_spec.rb +21 -19
- data/spec/wavefront-cli/output/csv_spec.rb +5 -2
- data/spec/wavefront-cli/output/hcl_spec.rb +5 -2
- data/spec/wavefront-cli/output/helpers.rb +18 -0
- data/spec/wavefront-cli/output/json_spec.rb +3 -1
- data/spec/wavefront-cli/output/ruby_spec.rb +3 -1
- data/spec/wavefront-cli/output/wavefront/query_spec.rb +3 -1
- data/spec/wavefront-cli/output/wavefront_spec.rb +6 -4
- data/spec/wavefront-cli/output/yaml_spec.rb +3 -1
- data/spec/wavefront-cli/proxy_spec.rb +49 -27
- data/spec/wavefront-cli/query_spec.rb +174 -92
- data/spec/wavefront-cli/resources/responses/query.json +1 -0
- data/spec/wavefront-cli/resources/updates/alert.json +15 -0
- data/spec/wavefront-cli/resources/updates/dashboard.json +1 -0
- data/spec/wavefront-cli/savedsearch_spec.rb +35 -18
- data/spec/wavefront-cli/serviceaccount_spec.rb +399 -0
- data/spec/wavefront-cli/settings_spec.rb +42 -11
- data/spec/wavefront-cli/source_spec.rb +120 -23
- data/spec/wavefront-cli/stdlib/array_spec.rb +2 -1
- data/spec/wavefront-cli/stdlib/string_spec.rb +9 -6
- data/spec/wavefront-cli/user_spec.rb +278 -108
- data/spec/wavefront-cli/usergroup_spec.rb +152 -102
- data/spec/wavefront-cli/webhook_spec.rb +30 -15
- data/spec/wavefront-cli/write_spec.rb +25 -1
- data/wavefront-cli.gemspec +5 -3
- metadata +65 -21
- data/spec/wavefront-cli/commands/spec_helper.rb +0 -3
- data/spec/wavefront-cli/display/spec_helper.rb +0 -3
data/lib/wavefront-cli/write.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'wavefront-sdk/support/mixins'
|
|
2
4
|
require_relative 'base'
|
|
3
5
|
|
|
@@ -10,15 +12,15 @@ module WavefrontCli
|
|
|
10
12
|
class Write < Base
|
|
11
13
|
attr_reader :fmt
|
|
12
14
|
include Wavefront::Mixins
|
|
13
|
-
SPLIT_PATTERN = /\s(?=(?:[^"]|"[^"]*")*$)
|
|
15
|
+
SPLIT_PATTERN = /\s(?=(?:[^"]|"[^"]*")*$)/.freeze
|
|
14
16
|
|
|
15
17
|
# rubocop:disable Metrics/AbcSize
|
|
16
18
|
def do_point
|
|
17
|
-
p = { path: options[:'<metric>'],
|
|
18
|
-
value: options[:'<value>'].delete('\\').to_f }
|
|
19
|
-
|
|
20
19
|
tags = tags_to_hash(options[:tag])
|
|
21
20
|
|
|
21
|
+
p = { path: options[:'<metric>'],
|
|
22
|
+
value: options[:'<value>'].delete('\\').to_f }
|
|
23
|
+
|
|
22
24
|
p[:tags] = tags unless tags.empty?
|
|
23
25
|
p[:source] = options[:host] if options[:host]
|
|
24
26
|
p[:ts] = parse_time(options[:time]) if options[:time]
|
|
@@ -32,17 +34,19 @@ module WavefrontCli
|
|
|
32
34
|
process_input(options[:'<file>'])
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
# rubocop:disable Metrics/AbcSize
|
|
36
37
|
def do_distribution
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
value: mk_dist }
|
|
38
|
+
send_point(make_distribution_point(tags_to_hash(options[:tag])))
|
|
39
|
+
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
# rubocop:disable Metrics/AbcSize
|
|
42
|
+
def make_distribution_point(tags)
|
|
43
|
+
{ path: options[:'<metric>'],
|
|
44
|
+
interval: options[:interval] || 'M',
|
|
45
|
+
tags: tags,
|
|
46
|
+
value: mk_dist }.tap do |p|
|
|
47
|
+
p[:source] = options[:host] if options[:host]
|
|
48
|
+
p[:ts] = parse_time(options[:time]) if options[:time]
|
|
49
|
+
end
|
|
46
50
|
end
|
|
47
51
|
# rubocop:enable Metrics/AbcSize
|
|
48
52
|
|
|
@@ -65,24 +69,26 @@ module WavefrontCli
|
|
|
65
69
|
#
|
|
66
70
|
def _sdk_class
|
|
67
71
|
return 'Wavefront::Distribution' if distribution?
|
|
72
|
+
|
|
68
73
|
'Wavefront::Write'
|
|
69
74
|
end
|
|
70
75
|
|
|
71
76
|
def distribution?
|
|
72
77
|
return true if options[:distribution]
|
|
78
|
+
|
|
73
79
|
options[:infileformat]&.include?('d')
|
|
74
80
|
end
|
|
75
81
|
|
|
76
82
|
def mk_creds
|
|
77
|
-
{ proxy:
|
|
78
|
-
port:
|
|
79
|
-
socket:
|
|
83
|
+
{ proxy: options[:proxy],
|
|
84
|
+
port: options[:port] || default_port,
|
|
85
|
+
socket: options[:socket],
|
|
80
86
|
endpoint: options[:endpoint],
|
|
81
|
-
token:
|
|
87
|
+
token: options[:token] }
|
|
82
88
|
end
|
|
83
89
|
|
|
84
90
|
def default_port
|
|
85
|
-
distribution? ?
|
|
91
|
+
distribution? ? 40_000 : 2878
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
def validate_opts
|
|
@@ -90,10 +96,12 @@ module WavefrontCli
|
|
|
90
96
|
|
|
91
97
|
if options[:using] == 'unix'
|
|
92
98
|
return true if options[:socket]
|
|
99
|
+
|
|
93
100
|
raise(WavefrontCli::Exception::CredentialError, 'No socket path.')
|
|
94
101
|
end
|
|
95
102
|
|
|
96
103
|
return true if options[:proxy]
|
|
104
|
+
|
|
97
105
|
raise(WavefrontCli::Exception::CredentialError, 'No proxy address.')
|
|
98
106
|
end
|
|
99
107
|
|
|
@@ -115,8 +123,7 @@ module WavefrontCli
|
|
|
115
123
|
def send_point(point)
|
|
116
124
|
call_write(point)
|
|
117
125
|
rescue Wavefront::Exception::InvalidEndpoint
|
|
118
|
-
abort format("Could not connect to proxy '
|
|
119
|
-
options[:proxy], options[:port])
|
|
126
|
+
abort format("Could not connect to proxy '%<proxy>s:%<port>s'.", options)
|
|
120
127
|
end
|
|
121
128
|
|
|
122
129
|
# Read the input, from a file or from STDIN, and turn each line
|
|
@@ -237,6 +244,7 @@ module WavefrontCli
|
|
|
237
244
|
options[:metric] ? [options[:metric], m].join('.') : m
|
|
238
245
|
rescue TypeError
|
|
239
246
|
return options[:metric] if options[:metric]
|
|
247
|
+
|
|
240
248
|
raise
|
|
241
249
|
end
|
|
242
250
|
|
|
@@ -264,14 +272,16 @@ module WavefrontCli
|
|
|
264
272
|
# @raise WavefrontCli::Exception::UnparseableInput if the line
|
|
265
273
|
# doesn't look right
|
|
266
274
|
#
|
|
267
|
-
# rubocop:disable Metrics/AbcSize
|
|
268
275
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
276
|
+
# rubocop:disable Metrics/MethodLength
|
|
277
|
+
# rubocop:disable Metrics/AbcSize
|
|
269
278
|
def process_line(line)
|
|
270
279
|
return true if line.empty?
|
|
280
|
+
|
|
271
281
|
chunks = line.split(SPLIT_PATTERN, fmt.length)
|
|
272
282
|
enough_fields?(line) # can raise exception
|
|
273
283
|
|
|
274
|
-
point = { path:
|
|
284
|
+
point = { path: extract_path(chunks),
|
|
275
285
|
value: extract_value(chunks) }
|
|
276
286
|
|
|
277
287
|
tags = line_tags(chunks)
|
|
@@ -283,8 +293,9 @@ module WavefrontCli
|
|
|
283
293
|
p[:interval] = options[:interval] || 'm' if fmt.include?('d')
|
|
284
294
|
end
|
|
285
295
|
end
|
|
286
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
287
296
|
# rubocop:enable Metrics/AbcSize
|
|
297
|
+
# rubocop:enable Metrics/MethodLength
|
|
298
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
288
299
|
|
|
289
300
|
# We can get tags from the file, from the -T option, or both.
|
|
290
301
|
# Merge them, making the -T win if there is a collision.
|
|
@@ -321,29 +332,49 @@ module WavefrontCli
|
|
|
321
332
|
#
|
|
322
333
|
# @param fmt [String] format of input file
|
|
323
334
|
#
|
|
324
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
|
325
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
326
|
-
# rubocop:disable Metrics/AbcSize
|
|
327
335
|
def valid_format?(fmt)
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
336
|
+
format_string_has_v_or_d?(fmt)
|
|
337
|
+
format_string_does_not_have_v_and_d?(fmt)
|
|
338
|
+
format_string_is_all_valid_chars?(fmt)
|
|
339
|
+
format_string_has_unique_chars?(fmt)
|
|
340
|
+
format_string_has_big_t_only_at_the_end?(fmt)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def format_string_has_v_or_d?(fmt)
|
|
344
|
+
return true if fmt.include?('v') || fmt.include?('d')
|
|
345
|
+
|
|
346
|
+
raise(WavefrontCli::Exception::UnparseableInput,
|
|
347
|
+
"format string must include 'v' or 'd'")
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def format_string_does_not_have_v_and_d?(fmt)
|
|
351
|
+
return true unless fmt.include?('v') && fmt.include?('d')
|
|
352
|
+
|
|
353
|
+
raise(WavefrontCli::Exception::UnparseableInput,
|
|
354
|
+
"'v' and 'd' are mutually exclusive")
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def format_string_is_all_valid_chars?(fmt)
|
|
358
|
+
return true if fmt =~ /^[dmstTv]+$/
|
|
359
|
+
|
|
360
|
+
raise(WavefrontCli::Exception::UnparseableInput,
|
|
361
|
+
'unsupported field in format string')
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def format_string_has_unique_chars?(fmt)
|
|
365
|
+
return true if fmt.chars.sort == fmt.chars.uniq.sort
|
|
366
|
+
|
|
367
|
+
raise(WavefrontCli::Exception::UnparseableInput,
|
|
368
|
+
'repeated field in format string')
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def format_string_has_big_t_only_at_the_end?(fmt)
|
|
372
|
+
return true unless fmt.include?('T')
|
|
373
|
+
return true if fmt.end_with?('T')
|
|
374
|
+
|
|
375
|
+
raise(WavefrontCli::Exception::UnparseableInput,
|
|
376
|
+
"if used, 'T' must come at end of format string")
|
|
377
|
+
end
|
|
347
378
|
|
|
348
379
|
# Make sure we have the right number of columns, according to
|
|
349
380
|
# the format string. We want to take every precaution we can to
|
|
@@ -359,8 +390,11 @@ module WavefrontCli
|
|
|
359
390
|
ncols = line.split(SPLIT_PATTERN).length
|
|
360
391
|
return true if fmt.include?('T') && ncols >= fmt.length
|
|
361
392
|
return true if ncols == fmt.length
|
|
393
|
+
|
|
362
394
|
raise(WavefrontCli::Exception::UnparseableInput,
|
|
363
|
-
format('Expected
|
|
395
|
+
format('Expected %<expected>s fields, got %<got>s',
|
|
396
|
+
expected: fmt.length,
|
|
397
|
+
got: ncols))
|
|
364
398
|
end
|
|
365
399
|
|
|
366
400
|
# Although the SDK does value checking, we'll add another layer
|
data/spec/.rubocop.yml
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
TargetRubyVersion: 2.2
|
|
3
|
-
|
|
4
|
-
Style/FormatStringToken:
|
|
5
|
-
Enabled: false
|
|
6
|
-
|
|
7
|
-
# Allow long blocks of tests
|
|
8
|
-
#
|
|
9
|
-
Metrics/BlockLength:
|
|
10
|
-
Max: 120
|
|
11
|
-
|
|
1
|
+
---
|
|
12
2
|
Metrics/MethodLength:
|
|
13
|
-
Max:
|
|
3
|
+
Max: 30
|
|
14
4
|
|
|
15
5
|
Metrics/AbcSize:
|
|
16
6
|
Max: 45
|
|
17
7
|
|
|
18
8
|
Metrics/ClassLength:
|
|
19
|
-
Max:
|
|
20
|
-
|
|
21
|
-
Metrics/CyclomaticComplexity:
|
|
22
|
-
Max: 10
|
|
9
|
+
Max: 250
|
data/spec/constants.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'inifile'
|
|
5
|
+
|
|
6
|
+
# Constants for testing
|
|
7
|
+
|
|
8
|
+
ROOT = Pathname.new(__dir__).parent
|
|
9
|
+
|
|
10
|
+
CMD = 'wf'
|
|
11
|
+
TW = 80
|
|
12
|
+
|
|
13
|
+
ENDPOINT = 'metrics.wavefront.com'
|
|
14
|
+
TOKEN = '0123456789-ABCDEF'
|
|
15
|
+
RES_DIR = ROOT + 'spec' + 'wavefront-cli' + 'resources'
|
|
16
|
+
CF = RES_DIR + 'wavefront.conf'
|
|
17
|
+
CF_VAL = IniFile.load(CF)
|
|
18
|
+
JSON_POST_HEADERS = {
|
|
19
|
+
'Content-Type': 'application/json', Accept: 'application/json'
|
|
20
|
+
}.freeze
|
|
21
|
+
TEE_ZERO = Time.now.freeze
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'json'
|
|
2
4
|
require 'webmock/minitest'
|
|
3
5
|
require 'spy/integration'
|
|
@@ -8,47 +10,22 @@ require 'minitest/spec'
|
|
|
8
10
|
require 'pathname'
|
|
9
11
|
require_relative '../lib/wavefront-cli/controller'
|
|
10
12
|
|
|
11
|
-
def all_commands
|
|
12
|
-
cmd_dir = ROOT + 'lib' + 'wavefront-cli' + 'commands'
|
|
13
|
-
|
|
14
|
-
files = cmd_dir.children.select do |f|
|
|
15
|
-
f.extname == '.rb' && f.basename.to_s != 'base.rb'
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
files.each.with_object([]) { |c, a| a.<< c.basename.to_s.chomp('.rb') }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
13
|
unless defined?(CMD)
|
|
22
14
|
ROOT = Pathname.new(__FILE__).dirname.parent
|
|
23
|
-
CMD = 'wavefront'
|
|
24
|
-
ENDPOINT = 'metrics.wavefront.com'
|
|
25
|
-
TOKEN = '0123456789-ABCDEF'
|
|
15
|
+
CMD = 'wavefront'
|
|
16
|
+
ENDPOINT = 'metrics.wavefront.com'
|
|
17
|
+
TOKEN = '0123456789-ABCDEF'
|
|
26
18
|
RES_DIR = Pathname.new(__FILE__).dirname + 'wavefront-cli' + 'resources'
|
|
27
19
|
CF = RES_DIR + 'wavefront.conf'
|
|
28
20
|
CF_VAL = IniFile.load(CF)
|
|
29
21
|
JSON_POST_HEADERS = {
|
|
30
22
|
'Content-Type': 'application/json', Accept: 'application/json'
|
|
31
23
|
}.freeze
|
|
32
|
-
|
|
33
|
-
BAD_TAG = '*BAD_TAG*'.freeze
|
|
24
|
+
BAD_TAG = '*BAD_TAG*'
|
|
34
25
|
TW = 80
|
|
35
26
|
HOME_CONFIG = Pathname.new(ENV['HOME']) + '.wavefront'
|
|
36
27
|
end
|
|
37
28
|
|
|
38
|
-
# Return an array of CLI permutations and the values to which they relate
|
|
39
|
-
#
|
|
40
|
-
def permutations
|
|
41
|
-
[["-t #{TOKEN} -E #{ENDPOINT}", { t: TOKEN, e: ENDPOINT }],
|
|
42
|
-
["-c #{CF}", { t: CF_VAL['default']['token'],
|
|
43
|
-
e: CF_VAL['default']['endpoint'] }],
|
|
44
|
-
["-c #{CF} -P other", { t: CF_VAL['other']['token'],
|
|
45
|
-
e: CF_VAL['other']['endpoint'] }],
|
|
46
|
-
["-c #{CF} -P other -t #{TOKEN}", { t: TOKEN,
|
|
47
|
-
e: CF_VAL['other']['endpoint'] }],
|
|
48
|
-
["-c #{CF} -E #{ENDPOINT}", { t: CF_VAL['default']['token'],
|
|
49
|
-
e: ENDPOINT }]]
|
|
50
|
-
end
|
|
51
|
-
|
|
52
29
|
# Object returned by cmd_to_call. Has just enough methods to satisfy
|
|
53
30
|
# the SDK
|
|
54
31
|
#
|
|
@@ -70,356 +47,6 @@ end
|
|
|
70
47
|
|
|
71
48
|
CANNED_RESPONSE = DummyResponse.new
|
|
72
49
|
|
|
73
|
-
# Match a command to the final API call it should produce, applying
|
|
74
|
-
# options in as many combinations as possible, and ensuring the
|
|
75
|
-
# requisite display methods are called.
|
|
76
|
-
#
|
|
77
|
-
# @param cmd [String] command line args to supply to the Wavefront
|
|
78
|
-
# @param call [Hash]
|
|
79
|
-
# @param spies [Array[Hash]] array of spies to set up, for stubbing
|
|
80
|
-
# methods in any class. Hash has keys :class, :method, :return.
|
|
81
|
-
# rubocop:disable Metrics/AbcSize
|
|
82
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
|
83
|
-
def cmd_to_call(word, args, call, sdk_class = nil, spies = [])
|
|
84
|
-
headers = { 'Accept': /.*/,
|
|
85
|
-
'Accept-Encoding': /.*/,
|
|
86
|
-
'Authorization': 'Bearer 0123456789-ABCDEF',
|
|
87
|
-
'User-Agent': "wavefront-cli-#{WF_CLI_VERSION}" }
|
|
88
|
-
|
|
89
|
-
sdk_class ||= Object.const_get("WavefrontCli::#{word.capitalize}")
|
|
90
|
-
|
|
91
|
-
headers.merge!(call[:headers]) if call.key?(:headers)
|
|
92
|
-
method = call[:method] || :get
|
|
93
|
-
fmts = call[:formats] ? ['-f json', '-f yaml', '-f human', ''] : ['']
|
|
94
|
-
|
|
95
|
-
permutations.each do |opts, vals|
|
|
96
|
-
describe "with #{word} #{args}" do
|
|
97
|
-
fmts.each do |fmt|
|
|
98
|
-
cmd = "#{word} #{args} #{opts} #{fmt}"
|
|
99
|
-
|
|
100
|
-
uri = if call[:regex]
|
|
101
|
-
Regexp.new(call[:path])
|
|
102
|
-
else
|
|
103
|
-
'https://' + vals[:e] + call[:path]
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
h = headers.dup
|
|
107
|
-
h[:Authorization] = "Bearer #{vals[:t]}"
|
|
108
|
-
|
|
109
|
-
it "runs #{cmd} and makes the correct API call" do
|
|
110
|
-
if call.key?(:body)
|
|
111
|
-
stub_request(method, uri).with(headers: h, body: call[:body])
|
|
112
|
-
.to_return(body: {}.to_json,
|
|
113
|
-
status: 200)
|
|
114
|
-
else
|
|
115
|
-
stub_request(method, uri).with(headers: h)
|
|
116
|
-
.to_return(body: {}.to_json,
|
|
117
|
-
status: 200)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
require "wavefront-sdk/#{sdk_class.name.split('::').last.downcase}"
|
|
121
|
-
spies.each do |spy|
|
|
122
|
-
Spy.on_instance_method(
|
|
123
|
-
Object.const_get(spy[:class]), spy[:method]
|
|
124
|
-
).and_return(spy[:return])
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
Spy.on_instance_method(
|
|
128
|
-
Object.const_get('Wavefront::ApiCaller'), :respond
|
|
129
|
-
).and_return(CANNED_RESPONSE)
|
|
130
|
-
|
|
131
|
-
d = Spy.on_instance_method(sdk_class, :display)
|
|
132
|
-
WavefrontCliController.new(cmd.split)
|
|
133
|
-
assert d.has_been_called?
|
|
134
|
-
assert_requested(method, uri, headers: h)
|
|
135
|
-
WebMock.reset!
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
|
142
|
-
# rubocop:enable Metrics/AbcSize
|
|
143
|
-
|
|
144
|
-
# Test no-ops
|
|
145
|
-
#
|
|
146
|
-
# @param output [Array] [URI, params]
|
|
147
|
-
#
|
|
148
|
-
def cmd_noop(word, cmd, output, sdk_class = nil)
|
|
149
|
-
cmd = [word] + cmd.split + ['--noop'] + ["-t #{TOKEN} -E #{ENDPOINT}"]
|
|
150
|
-
|
|
151
|
-
exit_code = output == :impossible ? 1 : 0
|
|
152
|
-
|
|
153
|
-
it "runs #{cmd.join(' ')} and gets output without an API call" do
|
|
154
|
-
out, err = capture_io do
|
|
155
|
-
sdk_class ||= Object.const_get("WavefrontCli::#{word.capitalize}")
|
|
156
|
-
require "wavefront-sdk/#{sdk_class.name.split('::').last.downcase}"
|
|
157
|
-
begin
|
|
158
|
-
WavefrontCliController.new(cmd).run
|
|
159
|
-
rescue SystemExit => e
|
|
160
|
-
assert_equal(exit_code, e.status)
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
if output == :impossible
|
|
165
|
-
assert_equal('Multiple API call operations cannot be performed ' \
|
|
166
|
-
"as no-ops.\n", err)
|
|
167
|
-
assert_empty(out)
|
|
168
|
-
else
|
|
169
|
-
out = out.split("\n")
|
|
170
|
-
refute_empty(out)
|
|
171
|
-
assert_equal("SDK INFO: uri: #{output.first}", out.first)
|
|
172
|
-
if output.size > 1
|
|
173
|
-
assert_equal("SDK INFO: params: #{output.last}", out.last)
|
|
174
|
-
end
|
|
175
|
-
assert_empty(err)
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Wrapper to standard noop tests
|
|
181
|
-
#
|
|
182
|
-
def noop_tests(cmd, id, nodelete = false, pth = nil, sdk_class = nil)
|
|
183
|
-
pth ||= cmd
|
|
184
|
-
cmd_noop(cmd, 'list',
|
|
185
|
-
["GET https://metrics.wavefront.com/api/v2/#{pth}",
|
|
186
|
-
offset: 0, limit: 100], sdk_class)
|
|
187
|
-
cmd_noop(cmd, "describe #{id}",
|
|
188
|
-
["GET https://metrics.wavefront.com/api/v2/#{pth}/#{id}"],
|
|
189
|
-
sdk_class)
|
|
190
|
-
|
|
191
|
-
if nodelete == :skip
|
|
192
|
-
elsif nodelete
|
|
193
|
-
cmd_noop(cmd, "delete #{id}", :impossible, sdk_class)
|
|
194
|
-
else
|
|
195
|
-
cmd_noop(cmd, "delete #{id}",
|
|
196
|
-
["DELETE https://metrics.wavefront.com/api/v2/#{pth}/#{id}"],
|
|
197
|
-
sdk_class)
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
# Run a command we expect to fail, returning stdout and stderr
|
|
202
|
-
#
|
|
203
|
-
def fail_command(cmd)
|
|
204
|
-
capture_io do
|
|
205
|
-
begin
|
|
206
|
-
WavefrontCliController.new(cmd.split).run
|
|
207
|
-
rescue SystemExit => e
|
|
208
|
-
assert_equal(1, e.status)
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def invalid_something(cmd, subcmds, thing)
|
|
214
|
-
subcmds.each do |sc|
|
|
215
|
-
it "fails '#{sc}' because of an invalid #{thing}" do
|
|
216
|
-
_out, err = fail_command("#{cmd} #{sc}")
|
|
217
|
-
assert_match(/^'.*' is not a valid #{thing}.\n$/, err)
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def invalid_tags(cmd, subcmds)
|
|
223
|
-
subcmds.each do |sc|
|
|
224
|
-
it "fails '#{sc}' because of an invalid tag" do
|
|
225
|
-
_out, err = fail_command("#{cmd} #{sc}")
|
|
226
|
-
assert_equal(err, "Invalid input. '#{BAD_TAG}' is not a valid tag.\n")
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def invalid_ids(cmd, subcmds)
|
|
232
|
-
subcmds.each do |sc|
|
|
233
|
-
it "fails '#{sc}' on invalid input" do
|
|
234
|
-
_out, err = fail_command("#{cmd} #{sc}")
|
|
235
|
-
assert_match(/^'.+' is not a valid \w/, err)
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
# Without a token, you should get an error. If you don't supply an
|
|
241
|
-
# endpoint, it will default to 'metrics.wavefront.com'. The
|
|
242
|
-
# behaviour is different now, depending on whether you have
|
|
243
|
-
# ~/.wavefront or not.
|
|
244
|
-
#
|
|
245
|
-
def missing_creds(cmd, subcmds)
|
|
246
|
-
describe 'commands with missing credentials' do
|
|
247
|
-
subcmds.each do |subcmd|
|
|
248
|
-
it "'#{subcmd}' tells the user config file not found" do
|
|
249
|
-
_out, err = fail_command("#{cmd} #{subcmd} -c /f")
|
|
250
|
-
assert_equal("Configuration file '/f' not found.\n", err)
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
# I've generally got a config file on my dev box, but Travis
|
|
254
|
-
# won't have one. Therefore this test probably won't get run
|
|
255
|
-
# locally, but it will get run in CI, which is what counts.
|
|
256
|
-
#
|
|
257
|
-
next if HOME_CONFIG.exist?
|
|
258
|
-
|
|
259
|
-
it "'#{subcmd}' errors and tells the user to generate config" do
|
|
260
|
-
out, _err = fail_command("#{cmd} #{subcmd}")
|
|
261
|
-
assert_match(/Please run 'wf config setup'/, out)
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def search_tests(word, id, klass = nil, pth = nil)
|
|
268
|
-
pth ||= word
|
|
269
|
-
cmd_to_call(word,
|
|
270
|
-
"search id=#{id}",
|
|
271
|
-
{ method: :post, path: "/api/v2/search/#{pth}",
|
|
272
|
-
body: { limit: 10,
|
|
273
|
-
offset: 0,
|
|
274
|
-
query: [{ key: 'id',
|
|
275
|
-
value: id,
|
|
276
|
-
matchingMethod: 'EXACT',
|
|
277
|
-
negated: false }],
|
|
278
|
-
sort: { field: 'id', ascending: true } },
|
|
279
|
-
headers: JSON_POST_HEADERS },
|
|
280
|
-
klass)
|
|
281
|
-
|
|
282
|
-
cmd_to_call(word,
|
|
283
|
-
"search id=#{id} thing!^word",
|
|
284
|
-
{ method: :post, path: "/api/v2/search/#{pth}",
|
|
285
|
-
body: { limit: 10,
|
|
286
|
-
offset: 0,
|
|
287
|
-
query: [{ key: 'id',
|
|
288
|
-
value: id,
|
|
289
|
-
matchingMethod: 'EXACT',
|
|
290
|
-
negated: false },
|
|
291
|
-
{ key: 'thing',
|
|
292
|
-
value: 'word',
|
|
293
|
-
matchingMethod: 'STARTSWITH',
|
|
294
|
-
negated: true }],
|
|
295
|
-
sort: { field: 'id', ascending: true } },
|
|
296
|
-
headers: JSON_POST_HEADERS },
|
|
297
|
-
klass)
|
|
298
|
-
|
|
299
|
-
cmd_to_call(word,
|
|
300
|
-
'search id!~avoid',
|
|
301
|
-
{ method: :post, path: "/api/v2/search/#{pth}",
|
|
302
|
-
body: { limit: 10,
|
|
303
|
-
offset: 0,
|
|
304
|
-
query: [{ key: 'id',
|
|
305
|
-
value: 'avoid',
|
|
306
|
-
matchingMethod: 'CONTAINS',
|
|
307
|
-
negated: true }],
|
|
308
|
-
sort: { field: 'id', ascending: true } },
|
|
309
|
-
headers: JSON_POST_HEADERS },
|
|
310
|
-
klass)
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
# Generic list tests, needed by most commands
|
|
314
|
-
#
|
|
315
|
-
def list_tests(cmd, pth = nil, klass = nil)
|
|
316
|
-
pth ||= cmd
|
|
317
|
-
cmd_to_call(cmd, 'list', { path: "/api/v2/#{pth}?limit=100&offset=0" },
|
|
318
|
-
klass)
|
|
319
|
-
cmd_to_call(cmd, 'list -L 50',
|
|
320
|
-
{ path: "/api/v2/#{pth}?limit=50&offset=0" },
|
|
321
|
-
klass)
|
|
322
|
-
cmd_to_call(cmd, 'list -L 20 -o 8',
|
|
323
|
-
{ path: "/api/v2/#{pth}?limit=20&offset=8" }, klass)
|
|
324
|
-
cmd_to_call(cmd, 'list -o 60',
|
|
325
|
-
{ path: "/api/v2/#{pth}?limit=100&offset=60" },
|
|
326
|
-
klass)
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
def tag_tests(cmd, id, bad_id, pth = nil, klass = nil)
|
|
330
|
-
pth ||= cmd
|
|
331
|
-
cmd_to_call(cmd, "tags #{id}", { path: "/api/v2/#{pth}/#{id}/tag" },
|
|
332
|
-
klass)
|
|
333
|
-
cmd_to_call(cmd, "tag set #{id} mytag",
|
|
334
|
-
{ method: :post,
|
|
335
|
-
path: "/api/v2/#{pth}/#{id}/tag",
|
|
336
|
-
body: %w[mytag].to_json,
|
|
337
|
-
headers: JSON_POST_HEADERS }, klass)
|
|
338
|
-
cmd_to_call(cmd, "tag set #{id} mytag1 mytag2",
|
|
339
|
-
{ method: :post,
|
|
340
|
-
path: "/api/v2/#{pth}/#{id}/tag",
|
|
341
|
-
body: %w[mytag1 mytag2].to_json,
|
|
342
|
-
headers: JSON_POST_HEADERS }, klass)
|
|
343
|
-
cmd_to_call(cmd, "tag add #{id} mytag",
|
|
344
|
-
{ method: :put, path: "/api/v2/#{pth}/#{id}/tag/mytag" },
|
|
345
|
-
klass)
|
|
346
|
-
cmd_to_call(cmd, "tag delete #{id} mytag",
|
|
347
|
-
{ method: :delete, path: "/api/v2/#{pth}/#{id}/tag/mytag" },
|
|
348
|
-
klass)
|
|
349
|
-
cmd_to_call(cmd, "tag clear #{id}", { method: :post,
|
|
350
|
-
path: "/api/v2/#{pth}/#{id}/tag",
|
|
351
|
-
body: [].to_json,
|
|
352
|
-
headers: JSON_POST_HEADERS }, klass)
|
|
353
|
-
invalid_ids(cmd, ["tags #{bad_id}",
|
|
354
|
-
"tag clear #{bad_id}",
|
|
355
|
-
"tag add #{bad_id} mytag",
|
|
356
|
-
"tag delete #{bad_id} mytag"])
|
|
357
|
-
invalid_tags(cmd, ["tag add #{id} #{BAD_TAG}",
|
|
358
|
-
"tag delete #{id} #{BAD_TAG}"])
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
def acl_tests(cmd, id, bad_id, pth = nil, klass = nil)
|
|
362
|
-
gid1 = '2659191e-aad4-4302-a94e-9667e1517127'
|
|
363
|
-
pth ||= cmd
|
|
364
|
-
|
|
365
|
-
cmd_to_call(cmd, "acls #{id}", { path: "/api/v2/#{pth}/acl?id=#{id}" },
|
|
366
|
-
klass)
|
|
367
|
-
|
|
368
|
-
spies = [{ class: "WavefrontCli::#{cmd.capitalize}",
|
|
369
|
-
method: :do_acls,
|
|
370
|
-
return: true }]
|
|
371
|
-
|
|
372
|
-
cmd_to_call(cmd, "acl clear #{id}",
|
|
373
|
-
{ method: :put,
|
|
374
|
-
path: "/api/v2/#{pth}/acl/set",
|
|
375
|
-
body: [{ entityId: id,
|
|
376
|
-
viewAcl: [],
|
|
377
|
-
modifyAcl: %w[abcd-1234] }].to_json,
|
|
378
|
-
headers: JSON_POST_HEADERS }, klass, [
|
|
379
|
-
{ class: "WavefrontCli::#{cmd.capitalize}",
|
|
380
|
-
method: :everyone_id,
|
|
381
|
-
return: 'abcd-1234' },
|
|
382
|
-
{ class: "WavefrontCli::#{cmd.capitalize}",
|
|
383
|
-
method: :do_acls,
|
|
384
|
-
return: true }
|
|
385
|
-
])
|
|
386
|
-
|
|
387
|
-
cmd_to_call(cmd, "acl grant view on #{id} to testuser1 testuser2",
|
|
388
|
-
{ method: :post,
|
|
389
|
-
path: "/api/v2/#{pth}/acl/add",
|
|
390
|
-
body: [{ entityId: id,
|
|
391
|
-
viewAcl: %w[testuser1 testuser2],
|
|
392
|
-
modifyAcl: [] }].to_json,
|
|
393
|
-
headers: JSON_POST_HEADERS }, klass, spies)
|
|
394
|
-
cmd_to_call(cmd, "acl revoke view on #{id} from testuser1",
|
|
395
|
-
{ method: :post,
|
|
396
|
-
path: "/api/v2/#{pth}/acl/remove",
|
|
397
|
-
body: [{ entityId: id,
|
|
398
|
-
viewAcl: %w[testuser1],
|
|
399
|
-
modifyAcl: [] }].to_json,
|
|
400
|
-
headers: JSON_POST_HEADERS }, klass, spies)
|
|
401
|
-
|
|
402
|
-
cmd_to_call(cmd, "acl grant modify on #{id} to testuser1",
|
|
403
|
-
{ method: :post,
|
|
404
|
-
path: "/api/v2/#{pth}/acl/add",
|
|
405
|
-
body: [{ entityId: id,
|
|
406
|
-
viewAcl: [],
|
|
407
|
-
modifyAcl: %w[testuser1] }].to_json,
|
|
408
|
-
headers: JSON_POST_HEADERS }, klass, spies)
|
|
409
|
-
cmd_to_call(cmd, "acl revoke modify on #{id} from testuser1",
|
|
410
|
-
{ method: :post,
|
|
411
|
-
path: "/api/v2/#{pth}/acl/remove",
|
|
412
|
-
body: [{ entityId: id,
|
|
413
|
-
viewAcl: [],
|
|
414
|
-
modifyAcl: %w[testuser1] }].to_json,
|
|
415
|
-
headers: JSON_POST_HEADERS }, klass, spies)
|
|
416
|
-
|
|
417
|
-
invalid_ids(cmd, ["acls #{bad_id}",
|
|
418
|
-
"acl clear #{bad_id}",
|
|
419
|
-
"acl grant modify on #{bad_id} to testuser1",
|
|
420
|
-
"acl revoke view on #{bad_id} from #{gid1}"])
|
|
421
|
-
end
|
|
422
|
-
|
|
423
50
|
# Unit tests
|
|
424
51
|
#
|
|
425
52
|
class CliMethodTest < MiniTest::Test
|
|
@@ -438,48 +65,6 @@ class CliMethodTest < MiniTest::Test
|
|
|
438
65
|
end
|
|
439
66
|
end
|
|
440
67
|
|
|
441
|
-
# Load in a canned query response
|
|
442
|
-
#
|
|
443
|
-
def load_query_response
|
|
444
|
-
JSON.parse(IO.read(RES_DIR + 'sample_query_response.json'),
|
|
445
|
-
symbolize_names: true)
|
|
446
|
-
end
|
|
447
|
-
|
|
448
|
-
def load_raw_query_response
|
|
449
|
-
JSON.parse(IO.read(RES_DIR + 'sample_raw_query_response.json'),
|
|
450
|
-
symbolize_names: true)
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
# We keep a bunch of Wavefront API responses as text files alongside
|
|
454
|
-
# canned responses in various formats. This class groups helpers for
|
|
455
|
-
# doing that.
|
|
456
|
-
#
|
|
457
|
-
class OutputTester
|
|
458
|
-
# @param file [String] filename to load
|
|
459
|
-
# @param only_items [Bool] true for the items hash, false for the
|
|
460
|
-
# whole loadedobject
|
|
461
|
-
# @return [Object] canned raw responses used to test outputs
|
|
462
|
-
#
|
|
463
|
-
def load_input(file, only_items = true)
|
|
464
|
-
ret = JSON.parse(IO.read(RES_DIR + 'display' + file),
|
|
465
|
-
symbolize_names: true)
|
|
466
|
-
only_items ? ret[:items] : ret
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
# @param file [String] file to load
|
|
470
|
-
# @return [String]
|
|
471
|
-
#
|
|
472
|
-
def load_expected(file)
|
|
473
|
-
IO.read(RES_DIR + 'display' + file)
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def in_and_out(input, expected, only_items = true)
|
|
477
|
-
[load_input(input, only_items), load_expected(expected)]
|
|
478
|
-
end
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
OUTPUT_TESTER = OutputTester.new
|
|
482
|
-
|
|
483
68
|
# stdlib extensions
|
|
484
69
|
#
|
|
485
70
|
class Hash
|
|
@@ -507,7 +92,8 @@ def command_output(word, method, klass = nil, infile = nil)
|
|
|
507
92
|
infile ||= "#{word}-list.json"
|
|
508
93
|
json = IO.read(RES_DIR + 'responses' + infile)
|
|
509
94
|
resp = Wavefront::Response.new(json, 200)
|
|
510
|
-
klass ||= Object.const_get(format('WavefrontCli
|
|
95
|
+
klass ||= Object.const_get(format('WavefrontCli::%<class_word>s',
|
|
96
|
+
class_word: word.capitalize))
|
|
511
97
|
klass = klass.new(format: :human)
|
|
512
98
|
|
|
513
99
|
capture_io { klass.display(resp, method) }
|