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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
require_relative '../support/minitest_assertions'
|
|
5
|
+
require_relative '../test_mixins/general'
|
|
6
|
+
require_relative '../../lib/wavefront-cli/controller'
|
|
7
|
+
|
|
8
|
+
# An abstract class which facilitates "end-to-end" testing of
|
|
9
|
+
# commands.
|
|
10
|
+
#
|
|
11
|
+
class EndToEndTest < MiniTest::Test
|
|
12
|
+
attr_reader :wf
|
|
13
|
+
|
|
14
|
+
def setup
|
|
15
|
+
before_setup if respond_to?(:before_setup)
|
|
16
|
+
@wf = WavefrontCliController
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def api_path
|
|
20
|
+
cmd_word
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def search_api_path
|
|
24
|
+
api_path
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def cmd_class
|
|
28
|
+
Object.const_get("WavefrontCli::#{sdk_class_name}")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def cmd_instance
|
|
32
|
+
cmd_class.new({})
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def sdk_class_name
|
|
36
|
+
api_path.capitalize
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Fields which must not be in import objects
|
|
40
|
+
#
|
|
41
|
+
def blocked_import_fields
|
|
42
|
+
%i[id]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# the key to use when testing the 'set' command. The value is
|
|
46
|
+
# always 'new_value'
|
|
47
|
+
#
|
|
48
|
+
def set_key
|
|
49
|
+
'name'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def friendly_name
|
|
53
|
+
cmd_word
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def wall_time
|
|
57
|
+
half_an_hour_ago = TEE_ZERO - (30 * 60)
|
|
58
|
+
start_time = Time.at(half_an_hour_ago.to_i - half_an_hour_ago.sec)
|
|
59
|
+
[start_time, Time.at(start_time + (10 * 60))]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def epoch_time
|
|
63
|
+
wall_time.map { |t| parse_time(t, true) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def start_and_end_opts
|
|
67
|
+
format('-s %<start_time>s -e %<end_time>s',
|
|
68
|
+
start_time: wall_time[0].strftime('%H:%M'),
|
|
69
|
+
end_time: wall_time[1].strftime('%H:%M'))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Set this to true for things that use cursors rather than offsets
|
|
73
|
+
#
|
|
74
|
+
def cannot_handle_offsets
|
|
75
|
+
false
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def dummy_response
|
|
79
|
+
{ status: { result: 'OK', message: '', code: 200 },
|
|
80
|
+
items: [] }.to_json
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spy'
|
|
4
|
+
require 'webmock/minitest'
|
|
5
|
+
require_relative '../constants'
|
|
6
|
+
|
|
7
|
+
# rubocop:disable Metrics/ModuleLength
|
|
8
|
+
module Minitest
|
|
9
|
+
#
|
|
10
|
+
# Custom assertions to facilitate CLI command testing
|
|
11
|
+
#
|
|
12
|
+
module Assertions
|
|
13
|
+
def assert_gets(api_path, headers, response, &block)
|
|
14
|
+
stub = stub_request(:get, api_path)
|
|
15
|
+
.with(headers: headers)
|
|
16
|
+
.to_return(body: response, status: 200)
|
|
17
|
+
yield block
|
|
18
|
+
assert_requested(stub)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def assert_gets_with_params(api_path, params, headers, response, &block)
|
|
22
|
+
stub = stub_request(:get, api_path)
|
|
23
|
+
.with(query: hash_including(params),
|
|
24
|
+
headers: headers)
|
|
25
|
+
.to_return(body: response, status: 200)
|
|
26
|
+
yield block
|
|
27
|
+
assert_requested(stub)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def assert_posts(api_path, headers, payload, response, &block)
|
|
31
|
+
stub = stub_request(:post, api_path)
|
|
32
|
+
.with(body: payload, headers: headers)
|
|
33
|
+
.to_return(body: response, status: 200)
|
|
34
|
+
yield block
|
|
35
|
+
assert_requested(stub)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def assert_puts(api_path, headers, _payload, response, &block)
|
|
39
|
+
stub = stub_request(:put, api_path)
|
|
40
|
+
.with(headers: headers)
|
|
41
|
+
.to_return(body: response, status: 200)
|
|
42
|
+
yield block
|
|
43
|
+
assert_requested(stub)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def assert_deletes(api_path, headers, response, &block)
|
|
47
|
+
stub = stub_request(:delete, api_path)
|
|
48
|
+
.with(headers: headers)
|
|
49
|
+
.to_return(body: response, status: 200)
|
|
50
|
+
yield block
|
|
51
|
+
assert_requested(stub)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Don't bother testing permutations for this
|
|
55
|
+
#
|
|
56
|
+
def assert_invalid_id(command)
|
|
57
|
+
out, err = capture_io do
|
|
58
|
+
assert_raises(SystemExit) { wf.new("#{cmd_word} #{command}".split) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
assert_empty(out)
|
|
62
|
+
assert_match(/is not a valid \w+ ID.$/, err)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def assert_usage(command)
|
|
66
|
+
out, err = capture_io do
|
|
67
|
+
assert_raises(SystemExit) { wf.new("#{cmd_word} #{command}".split) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
assert_empty(out)
|
|
71
|
+
assert_match(/^Usage:\n wf #{cmd_word}/, err)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def assert_abort_on_missing_creds(command)
|
|
75
|
+
out, err = capture_io do
|
|
76
|
+
assert_raises(SystemExit) do
|
|
77
|
+
wf.new("#{cmd_word} #{command} --config /nofile".split)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
assert_empty(out)
|
|
82
|
+
assert_equal("Configuration file '/nofile' not found.\n", err)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def assert_exits_with(message, command)
|
|
86
|
+
out, err = capture_io do
|
|
87
|
+
assert_raises(SystemExit) do
|
|
88
|
+
wf.new("#{cmd_word} #{command} --config #{CF}".split)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
assert_empty(out)
|
|
93
|
+
assert_equal(message, err.strip)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def assert_cannot_noop(command)
|
|
97
|
+
out, err = capture_io do
|
|
98
|
+
assert_raises(SystemExit) do
|
|
99
|
+
wf.new("#{cmd_word} #{command} --noop --config #{CF}".split)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
assert_empty(out)
|
|
104
|
+
assert_equal('Multiple API call operations cannot be ' \
|
|
105
|
+
"performed as no-ops.\n", err)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def assert_repeated_output(msg)
|
|
109
|
+
begin
|
|
110
|
+
out, err = capture_io do
|
|
111
|
+
yield
|
|
112
|
+
end
|
|
113
|
+
rescue SystemExit => e
|
|
114
|
+
puts e.backtrace
|
|
115
|
+
p e
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
assert_empty(err)
|
|
119
|
+
out.each_line { |l| assert_equal(msg, l.rstrip) }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def assert_cmd_gets(command, api_path, response = dummy_response)
|
|
123
|
+
all_permutations do |p|
|
|
124
|
+
assert_gets(full_uri(p[:endpoint], api_path),
|
|
125
|
+
mk_headers(p[:token]), response) do
|
|
126
|
+
wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def full_uri(host, api_path)
|
|
132
|
+
if api_path.is_a?(Regexp)
|
|
133
|
+
%r{^https://#{host}#{api_path.source}$}
|
|
134
|
+
else
|
|
135
|
+
"https://#{host}#{api_path}"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def assert_cmd_gets_with_params(command, api_path, params,
|
|
140
|
+
response = dummy_response)
|
|
141
|
+
all_permutations do |p|
|
|
142
|
+
assert_gets_with_params("https://#{p[:endpoint]}#{api_path}",
|
|
143
|
+
params,
|
|
144
|
+
mk_headers(p[:token]),
|
|
145
|
+
response) do
|
|
146
|
+
wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def assert_cmd_posts(command, api_path, payload = 'null',
|
|
152
|
+
response = dummy_response)
|
|
153
|
+
all_permutations do |p|
|
|
154
|
+
assert_posts("https://#{p[:endpoint]}#{api_path}",
|
|
155
|
+
mk_headers(p[:token]), payload, response) do
|
|
156
|
+
wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def assert_cmd_puts(command, api_path, payload, response = dummy_response)
|
|
162
|
+
all_permutations do |p|
|
|
163
|
+
assert_puts("https://#{p[:endpoint]}#{api_path}",
|
|
164
|
+
mk_headers(p[:token]), payload, response) do
|
|
165
|
+
wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def assert_cmd_deletes(command, api_path, response = dummy_response)
|
|
171
|
+
permutations.each do |p|
|
|
172
|
+
assert_deletes("https://#{p[:endpoint]}#{api_path}",
|
|
173
|
+
mk_headers(p[:token]), response) do
|
|
174
|
+
wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def assert_noop(command, *expected)
|
|
180
|
+
out, err = capture_io do
|
|
181
|
+
assert_raises(SystemExit) do
|
|
182
|
+
wf.new("#{cmd_word} #{command} -c #{CF} --noop".split)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
out.strip.split("\n").each.with_index do |l, i|
|
|
187
|
+
assert_equal("SDK INFO: #{expected[i]}", l)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
assert_empty(err)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Run tests with all available permutations. We'll always need
|
|
194
|
+
# to mock out display, unless we don't, when even if we do, it
|
|
195
|
+
# won't matter.
|
|
196
|
+
#
|
|
197
|
+
def all_permutations
|
|
198
|
+
perms = permutations
|
|
199
|
+
perms = [perms[2]]
|
|
200
|
+
|
|
201
|
+
perms.each do |p|
|
|
202
|
+
yield(p)
|
|
203
|
+
WebMock.reset!
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Helper to avoid dealing with our display methods
|
|
208
|
+
#
|
|
209
|
+
def quietly
|
|
210
|
+
d = Spy.on_instance_method(cmd_class, :display)
|
|
211
|
+
yield
|
|
212
|
+
assert d.has_been_called?
|
|
213
|
+
d.unhook
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
private
|
|
217
|
+
|
|
218
|
+
def mk_headers(token = nil)
|
|
219
|
+
{ 'Accept': /.*/,
|
|
220
|
+
'Accept-Encoding': /.*/,
|
|
221
|
+
'Authorization': 'Bearer ' + (token || '0123456789-ABCDEF'),
|
|
222
|
+
'User-Agent': "wavefront-cli-#{WF_CLI_VERSION}" }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Every command we simulate running is done under the following
|
|
226
|
+
# permutations
|
|
227
|
+
#
|
|
228
|
+
def permutations
|
|
229
|
+
[{ cmdline: "-t #{TOKEN} -E #{ENDPOINT}",
|
|
230
|
+
token: TOKEN,
|
|
231
|
+
endpoint: ENDPOINT },
|
|
232
|
+
|
|
233
|
+
{ cmdline: "-c #{CF}",
|
|
234
|
+
token: CF_VAL['default']['token'],
|
|
235
|
+
endpoint: CF_VAL['default']['endpoint'] },
|
|
236
|
+
|
|
237
|
+
{ cmdline: "-c #{CF} -P other",
|
|
238
|
+
token: CF_VAL['other']['token'],
|
|
239
|
+
endpoint: CF_VAL['other']['endpoint'] },
|
|
240
|
+
|
|
241
|
+
{ cmdline: "-c #{CF} --profile other -t #{TOKEN}",
|
|
242
|
+
token: TOKEN,
|
|
243
|
+
endpoint: CF_VAL['other']['endpoint'] },
|
|
244
|
+
|
|
245
|
+
{ cmdline: "--config #{CF} -E #{ENDPOINT}",
|
|
246
|
+
token: CF_VAL['default']['token'],
|
|
247
|
+
endpoint: ENDPOINT }]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Drop this into bodies when you need to check a non-specific
|
|
251
|
+
# timestamp is there
|
|
252
|
+
#
|
|
253
|
+
def a_timestamp
|
|
254
|
+
proc { |t| t.to_s =~ /^\d{10}$/ }
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def a_ms_timestamp
|
|
258
|
+
proc { |t| t.to_s =~ /^\d{13}$/ }
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require_relative '../constants'
|
|
5
|
+
|
|
6
|
+
# We keep a bunch of Wavefront API responses as text files alongside
|
|
7
|
+
# canned responses in various formats. This class groups helpers for
|
|
8
|
+
# consuming those files.
|
|
9
|
+
#
|
|
10
|
+
class OutputTester
|
|
11
|
+
# @param file [String] filename to load
|
|
12
|
+
# @param only_items [Bool] true for the items hash, false for the
|
|
13
|
+
# whole loadedobject
|
|
14
|
+
# @return [Object] canned raw responses used to test outputs
|
|
15
|
+
#
|
|
16
|
+
def load_input(file, only_items = true)
|
|
17
|
+
ret = JSON.parse(IO.read(RES_DIR + 'display' + file),
|
|
18
|
+
symbolize_names: true)
|
|
19
|
+
only_items ? ret[:items] : ret
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param file [String] file to load
|
|
23
|
+
# @return [String]
|
|
24
|
+
#
|
|
25
|
+
def load_expected(file)
|
|
26
|
+
IO.read(RES_DIR + 'display' + file)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def in_and_out(input, expected, only_items = true)
|
|
30
|
+
[load_input(input, only_items), load_expected(expected)]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../constants'
|
|
4
|
+
|
|
5
|
+
class SupportedCommands
|
|
6
|
+
attr_reader :cmd_dir
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@cmd_dir = ROOT + 'lib' + 'wavefront-cli' + 'commands'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def all
|
|
13
|
+
files = cmd_dir.children.select do |f|
|
|
14
|
+
f.extname == '.rb' && f.basename.to_s != 'base.rb'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
files.map { |f| f.basename.to_s.chomp('.rb') }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
|
4
|
+
module WavefrontCliTest
|
|
5
|
+
#
|
|
6
|
+
# Include this module to get full ACL tests
|
|
7
|
+
#
|
|
8
|
+
module Acl
|
|
9
|
+
def test_acl
|
|
10
|
+
assert_repeated_output('No data.') do
|
|
11
|
+
assert_cmd_gets("acls #{id}", "/api/v2/#{api_path}/acl?id=#{id}")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
assert_noop("acls #{id}",
|
|
15
|
+
'uri: GET https://default.wavefront.com/api/v2/' \
|
|
16
|
+
"#{api_path}/acl")
|
|
17
|
+
|
|
18
|
+
assert_invalid_id("acls #{invalid_id}")
|
|
19
|
+
assert_usage('acls')
|
|
20
|
+
assert_abort_on_missing_creds("acls #{id}")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_acl_clear
|
|
24
|
+
acl_stub = stub_do_acls
|
|
25
|
+
id_stub = stub_everyone_id
|
|
26
|
+
|
|
27
|
+
quietly do
|
|
28
|
+
assert_cmd_puts("acl clear #{id}",
|
|
29
|
+
"/api/v2/#{api_path}/acl/set",
|
|
30
|
+
[{ entityId: id,
|
|
31
|
+
viewAcl: [],
|
|
32
|
+
modifyAcl: [everyone_id] }].to_json)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
assert_cannot_noop("acl clear #{id}")
|
|
36
|
+
|
|
37
|
+
assert_invalid_id("acl clear #{invalid_id}")
|
|
38
|
+
assert_usage('acl clear')
|
|
39
|
+
assert_abort_on_missing_creds("acl clear #{id}")
|
|
40
|
+
acl_stub.unhook
|
|
41
|
+
id_stub.unhook
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_acl_grant_view_to_users
|
|
45
|
+
stub = stub_do_acls
|
|
46
|
+
|
|
47
|
+
quietly do
|
|
48
|
+
assert_cmd_posts("acl grant view on #{id} to #{user_acl_names}",
|
|
49
|
+
"/api/v2/#{api_path}/acl/add",
|
|
50
|
+
acl_body(id, user_acls, []))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
assert_noop("acl grant view on #{id} to #{user_acl_names}",
|
|
54
|
+
'uri: POST https://default.wavefront.com/api/v2/' \
|
|
55
|
+
"#{api_path}/acl/add",
|
|
56
|
+
"body: #{acl_body(id, user_acls, [])}")
|
|
57
|
+
|
|
58
|
+
assert_invalid_id("acl grant view on #{invalid_id} to user")
|
|
59
|
+
assert_usage("acl grant view on #{id}")
|
|
60
|
+
assert_abort_on_missing_creds(
|
|
61
|
+
"acl grant view on #{invalid_id} to user"
|
|
62
|
+
)
|
|
63
|
+
stub.unhook
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_acl_grant_modify_to_group
|
|
67
|
+
stub = stub_do_acls
|
|
68
|
+
|
|
69
|
+
quietly do
|
|
70
|
+
assert_cmd_posts("acl grant modify on #{id} to #{group_acls.first}",
|
|
71
|
+
"/api/v2/#{api_path}/acl/add",
|
|
72
|
+
acl_body(id, [], group_acls))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
assert_noop("acl grant modify on #{id} to #{group_acls.first}",
|
|
76
|
+
'uri: POST https://default.wavefront.com/api/v2/' \
|
|
77
|
+
"#{api_path}/acl/add",
|
|
78
|
+
"body: #{acl_body(id, [], group_acls)}")
|
|
79
|
+
|
|
80
|
+
assert_invalid_id("acl grant modify on #{invalid_id} to user")
|
|
81
|
+
assert_usage("acl grant modify on #{id}")
|
|
82
|
+
assert_abort_on_missing_creds(
|
|
83
|
+
"acl grant modify on #{invalid_id} to user"
|
|
84
|
+
)
|
|
85
|
+
stub.unhook
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_acl_revoke_view_from_group
|
|
89
|
+
stub = stub_do_acls
|
|
90
|
+
|
|
91
|
+
quietly do
|
|
92
|
+
assert_cmd_posts("acl revoke view on #{id} from #{group_acls.first}",
|
|
93
|
+
"/api/v2/#{api_path}/acl/remove",
|
|
94
|
+
acl_body(id, group_acls, []))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
assert_noop("acl revoke view on #{id} from #{group_acls.first}",
|
|
98
|
+
'uri: POST https://default.wavefront.com/api/v2/' \
|
|
99
|
+
"#{api_path}/acl/remove",
|
|
100
|
+
"body: #{acl_body(id, group_acls, [])}")
|
|
101
|
+
|
|
102
|
+
assert_invalid_id("acl revoke view on #{invalid_id} from user")
|
|
103
|
+
assert_usage("acl revoke view on #{id}")
|
|
104
|
+
assert_abort_on_missing_creds(
|
|
105
|
+
"acl revoke view on #{invalid_id} from user"
|
|
106
|
+
)
|
|
107
|
+
stub.unhook
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_acl_revoke_modify_from_user
|
|
111
|
+
stub = stub_do_acls
|
|
112
|
+
|
|
113
|
+
quietly do
|
|
114
|
+
assert_cmd_posts("acl revoke modify on #{id} from #{user_acls.first}",
|
|
115
|
+
"/api/v2/#{api_path}/acl/remove",
|
|
116
|
+
acl_body(id, [], user_acls.take(1)))
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
assert_noop("acl revoke modify on #{id} from #{user_acls.first}",
|
|
120
|
+
'uri: POST https://default.wavefront.com/api/v2/' \
|
|
121
|
+
"#{api_path}/acl/remove",
|
|
122
|
+
"body: #{acl_body(id, [], user_acls.take(1))}")
|
|
123
|
+
|
|
124
|
+
assert_invalid_id("acl revoke modify on #{invalid_id} from user")
|
|
125
|
+
assert_usage("acl revoke modify on #{id}")
|
|
126
|
+
assert_abort_on_missing_creds(
|
|
127
|
+
"acl revoke modify on #{invalid_id} from user"
|
|
128
|
+
)
|
|
129
|
+
stub.unhook
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def stub_everyone_id
|
|
135
|
+
Spy.on_instance_method(cmd_class, :everyone_id)
|
|
136
|
+
.and_return(everyone_id)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def stub_do_acls
|
|
140
|
+
Spy.on_instance_method(cmd_class, :do_acls).and_return('')
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def everyone_id
|
|
144
|
+
'abcd-1234'
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def user_acls
|
|
148
|
+
%w[someone@example.com other@elsewhere.com]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def user_acl_names
|
|
152
|
+
user_acls.join(' ')
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @return [Array[String]] list of group IDs for ACL testing
|
|
156
|
+
#
|
|
157
|
+
def group_acls
|
|
158
|
+
%w[f8dc0c14-91a0-4ca9-8a2a-7d47f4db4672]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# @return [String] JSON representation of an ACL request
|
|
162
|
+
# payload
|
|
163
|
+
#
|
|
164
|
+
def acl_body(id, view = [], modify = [])
|
|
165
|
+
[{ entityId: id, viewAcl: view, modifyAcl: modify }].to_json
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
# rubocop:enable Metrics/ModuleLength
|