wavefront-cli 4.2.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -0
  3. data/.rubocop.yml +1 -14
  4. data/.travis.yml +4 -4
  5. data/Gemfile +2 -0
  6. data/HISTORY.md +82 -60
  7. data/Rakefile +2 -0
  8. data/bin/wf +1 -0
  9. data/lib/wavefront-cli/alert.rb +13 -5
  10. data/lib/wavefront-cli/apitoken.rb +2 -0
  11. data/lib/wavefront-cli/base.rb +95 -47
  12. data/lib/wavefront-cli/cloudintegration.rb +6 -0
  13. data/lib/wavefront-cli/command_mixins/acl.rb +6 -1
  14. data/lib/wavefront-cli/command_mixins/tag.rb +2 -0
  15. data/lib/wavefront-cli/commands/.rubocop.yml +3 -4
  16. data/lib/wavefront-cli/commands/alert.rb +2 -1
  17. data/lib/wavefront-cli/commands/apitoken.rb +6 -0
  18. data/lib/wavefront-cli/commands/base.rb +30 -21
  19. data/lib/wavefront-cli/commands/cloudintegration.rb +2 -0
  20. data/lib/wavefront-cli/commands/config.rb +2 -0
  21. data/lib/wavefront-cli/commands/dashboard.rb +2 -0
  22. data/lib/wavefront-cli/commands/derivedmetric.rb +2 -0
  23. data/lib/wavefront-cli/commands/event.rb +3 -1
  24. data/lib/wavefront-cli/commands/integration.rb +2 -1
  25. data/lib/wavefront-cli/commands/link.rb +2 -0
  26. data/lib/wavefront-cli/commands/message.rb +2 -0
  27. data/lib/wavefront-cli/commands/metric.rb +2 -0
  28. data/lib/wavefront-cli/commands/notificant.rb +2 -0
  29. data/lib/wavefront-cli/commands/proxy.rb +2 -0
  30. data/lib/wavefront-cli/commands/query.rb +2 -0
  31. data/lib/wavefront-cli/commands/savedsearch.rb +2 -0
  32. data/lib/wavefront-cli/commands/serviceaccount.rb +58 -0
  33. data/lib/wavefront-cli/commands/settings.rb +2 -0
  34. data/lib/wavefront-cli/commands/source.rb +3 -1
  35. data/lib/wavefront-cli/commands/user.rb +4 -1
  36. data/lib/wavefront-cli/commands/usergroup.rb +3 -0
  37. data/lib/wavefront-cli/commands/webhook.rb +2 -0
  38. data/lib/wavefront-cli/commands/window.rb +2 -0
  39. data/lib/wavefront-cli/commands/write.rb +2 -0
  40. data/lib/wavefront-cli/config.rb +23 -12
  41. data/lib/wavefront-cli/constants.rb +10 -4
  42. data/lib/wavefront-cli/controller.rb +53 -22
  43. data/lib/wavefront-cli/dashboard.rb +3 -0
  44. data/lib/wavefront-cli/derivedmetric.rb +12 -11
  45. data/lib/wavefront-cli/display/alert.rb +7 -4
  46. data/lib/wavefront-cli/display/apitoken.rb +2 -0
  47. data/lib/wavefront-cli/display/base.rb +34 -8
  48. data/lib/wavefront-cli/display/cloudintegration.rb +4 -2
  49. data/lib/wavefront-cli/display/dashboard.rb +2 -0
  50. data/lib/wavefront-cli/display/derivedmetric.rb +2 -0
  51. data/lib/wavefront-cli/display/distribution.rb +2 -0
  52. data/lib/wavefront-cli/display/event.rb +2 -0
  53. data/lib/wavefront-cli/display/externallink.rb +2 -0
  54. data/lib/wavefront-cli/display/integration.rb +2 -0
  55. data/lib/wavefront-cli/display/maintenancewindow.rb +2 -0
  56. data/lib/wavefront-cli/display/message.rb +7 -3
  57. data/lib/wavefront-cli/display/metric.rb +3 -1
  58. data/lib/wavefront-cli/display/notificant.rb +3 -1
  59. data/lib/wavefront-cli/display/printer/long.rb +36 -11
  60. data/lib/wavefront-cli/display/printer/sparkline.rb +3 -0
  61. data/lib/wavefront-cli/display/printer/terse.rb +6 -1
  62. data/lib/wavefront-cli/display/proxy.rb +2 -0
  63. data/lib/wavefront-cli/display/query.rb +35 -24
  64. data/lib/wavefront-cli/display/savedsearch.rb +2 -0
  65. data/lib/wavefront-cli/display/serviceaccount.rb +60 -0
  66. data/lib/wavefront-cli/display/settings.rb +2 -0
  67. data/lib/wavefront-cli/display/source.rb +18 -4
  68. data/lib/wavefront-cli/display/user.rb +56 -10
  69. data/lib/wavefront-cli/display/usergroup.rb +25 -19
  70. data/lib/wavefront-cli/display/webhook.rb +2 -0
  71. data/lib/wavefront-cli/display/write.rb +6 -2
  72. data/lib/wavefront-cli/event.rb +83 -62
  73. data/lib/wavefront-cli/exception.rb +3 -0
  74. data/lib/wavefront-cli/externallink.rb +6 -4
  75. data/lib/wavefront-cli/integration.rb +2 -0
  76. data/lib/wavefront-cli/maintenancewindow.rb +28 -17
  77. data/lib/wavefront-cli/message.rb +4 -0
  78. data/lib/wavefront-cli/metric.rb +4 -1
  79. data/lib/wavefront-cli/notificant.rb +2 -0
  80. data/lib/wavefront-cli/opt_handler.rb +2 -0
  81. data/lib/wavefront-cli/output/base.rb +8 -3
  82. data/lib/wavefront-cli/output/csv.rb +2 -0
  83. data/lib/wavefront-cli/output/csv/base.rb +2 -0
  84. data/lib/wavefront-cli/output/csv/query.rb +14 -7
  85. data/lib/wavefront-cli/output/hcl.rb +2 -0
  86. data/lib/wavefront-cli/output/hcl/alert.rb +2 -0
  87. data/lib/wavefront-cli/output/hcl/base.rb +10 -4
  88. data/lib/wavefront-cli/output/hcl/dashboard.rb +17 -8
  89. data/lib/wavefront-cli/output/hcl/notificant.rb +2 -0
  90. data/lib/wavefront-cli/output/hcl/stdlib/array.rb +2 -0
  91. data/lib/wavefront-cli/output/hcl/stdlib/string.rb +2 -0
  92. data/lib/wavefront-cli/output/json.rb +2 -0
  93. data/lib/wavefront-cli/output/ruby.rb +2 -0
  94. data/lib/wavefront-cli/output/wavefront.rb +2 -0
  95. data/lib/wavefront-cli/output/wavefront/query.rb +7 -4
  96. data/lib/wavefront-cli/output/yaml.rb +2 -0
  97. data/lib/wavefront-cli/proxy.rb +15 -3
  98. data/lib/wavefront-cli/query.rb +14 -12
  99. data/lib/wavefront-cli/savedsearch.rb +2 -0
  100. data/lib/wavefront-cli/serviceaccount.rb +179 -0
  101. data/lib/wavefront-cli/settings.rb +2 -0
  102. data/lib/wavefront-cli/source.rb +2 -0
  103. data/lib/wavefront-cli/stdlib/array.rb +3 -0
  104. data/lib/wavefront-cli/stdlib/string.rb +17 -11
  105. data/lib/wavefront-cli/user.rb +10 -4
  106. data/lib/wavefront-cli/usergroup.rb +4 -2
  107. data/lib/wavefront-cli/version.rb +3 -1
  108. data/lib/wavefront-cli/webhook.rb +2 -0
  109. data/lib/wavefront-cli/write.rb +80 -46
  110. data/spec/.rubocop.yml +3 -16
  111. data/spec/constants.rb +21 -0
  112. data/spec/spec_helper.rb +8 -422
  113. data/spec/support/command_base.rb +82 -0
  114. data/spec/support/minitest_assertions.rb +262 -0
  115. data/spec/support/output_tester.rb +32 -0
  116. data/spec/support/supported_commands.rb +19 -0
  117. data/spec/test_mixins/acl.rb +169 -0
  118. data/spec/test_mixins/delete.rb +25 -0
  119. data/spec/test_mixins/deleteundelete.rb +106 -0
  120. data/spec/test_mixins/describe.rb +24 -0
  121. data/spec/test_mixins/dump.rb +43 -0
  122. data/spec/test_mixins/general.rb +11 -0
  123. data/spec/test_mixins/history.rb +35 -0
  124. data/spec/test_mixins/import.rb +65 -0
  125. data/spec/test_mixins/list.rb +29 -0
  126. data/spec/test_mixins/search.rb +98 -0
  127. data/spec/test_mixins/set.rb +47 -0
  128. data/spec/test_mixins/tag.rb +99 -0
  129. data/spec/wavefront-cli/alert_spec.rb +288 -111
  130. data/spec/wavefront-cli/apitoken_spec.rb +53 -24
  131. data/spec/wavefront-cli/base_spec.rb +9 -27
  132. data/spec/wavefront-cli/cloudintegration_spec.rb +65 -29
  133. data/spec/wavefront-cli/commands/alert_spec.rb +1 -0
  134. data/spec/wavefront-cli/commands/base_spec.rb +15 -13
  135. data/spec/wavefront-cli/commands/cloudintegration_spec.rb +1 -0
  136. data/spec/wavefront-cli/commands/config_spec.rb +3 -0
  137. data/spec/wavefront-cli/commands/dashboard_spec.rb +1 -0
  138. data/spec/wavefront-cli/commands/derivedmetric_spec.rb +1 -0
  139. data/spec/wavefront-cli/commands/event_spec.rb +1 -0
  140. data/spec/wavefront-cli/commands/link_spec.rb +1 -0
  141. data/spec/wavefront-cli/commands/message_spec.rb +1 -0
  142. data/spec/wavefront-cli/commands/metric_spec.rb +1 -0
  143. data/spec/wavefront-cli/commands/proxy_spec.rb +1 -0
  144. data/spec/wavefront-cli/commands/query_spec.rb +1 -0
  145. data/spec/wavefront-cli/commands/webhook_spec.rb +1 -0
  146. data/spec/wavefront-cli/commands/window_spec.rb +1 -0
  147. data/spec/wavefront-cli/commands/write_spec.rb +1 -0
  148. data/spec/wavefront-cli/config_spec.rb +25 -14
  149. data/spec/wavefront-cli/controller_spec.rb +13 -3
  150. data/spec/wavefront-cli/dashboard_spec.rb +125 -76
  151. data/spec/wavefront-cli/derivedmetric_spec.rb +83 -67
  152. data/spec/wavefront-cli/display/base_spec.rb +5 -7
  153. data/spec/wavefront-cli/display/printer/long_spec.rb +20 -16
  154. data/spec/wavefront-cli/display/printer/terse_spec.rb +5 -4
  155. data/spec/wavefront-cli/event_spec.rb +360 -18
  156. data/spec/wavefront-cli/externallink_spec.rb +92 -58
  157. data/spec/wavefront-cli/integration_spec.rb +129 -31
  158. data/spec/wavefront-cli/maintenancewindow_spec.rb +270 -32
  159. data/spec/wavefront-cli/message_spec.rb +73 -30
  160. data/spec/wavefront-cli/metric_spec.rb +60 -22
  161. data/spec/wavefront-cli/notificant_spec.rb +45 -32
  162. data/spec/wavefront-cli/opt_handler_spec.rb +4 -1
  163. data/spec/wavefront-cli/output/csv/query_spec.rb +21 -19
  164. data/spec/wavefront-cli/output/csv_spec.rb +5 -2
  165. data/spec/wavefront-cli/output/hcl_spec.rb +5 -2
  166. data/spec/wavefront-cli/output/helpers.rb +18 -0
  167. data/spec/wavefront-cli/output/json_spec.rb +3 -1
  168. data/spec/wavefront-cli/output/ruby_spec.rb +3 -1
  169. data/spec/wavefront-cli/output/wavefront/query_spec.rb +3 -1
  170. data/spec/wavefront-cli/output/wavefront_spec.rb +6 -4
  171. data/spec/wavefront-cli/output/yaml_spec.rb +3 -1
  172. data/spec/wavefront-cli/proxy_spec.rb +49 -27
  173. data/spec/wavefront-cli/query_spec.rb +174 -92
  174. data/spec/wavefront-cli/resources/responses/query.json +1 -0
  175. data/spec/wavefront-cli/resources/updates/alert.json +15 -0
  176. data/spec/wavefront-cli/resources/updates/dashboard.json +1 -0
  177. data/spec/wavefront-cli/savedsearch_spec.rb +35 -18
  178. data/spec/wavefront-cli/serviceaccount_spec.rb +399 -0
  179. data/spec/wavefront-cli/settings_spec.rb +42 -11
  180. data/spec/wavefront-cli/source_spec.rb +120 -23
  181. data/spec/wavefront-cli/stdlib/array_spec.rb +2 -1
  182. data/spec/wavefront-cli/stdlib/string_spec.rb +9 -6
  183. data/spec/wavefront-cli/user_spec.rb +278 -108
  184. data/spec/wavefront-cli/usergroup_spec.rb +152 -102
  185. data/spec/wavefront-cli/webhook_spec.rb +30 -15
  186. data/spec/wavefront-cli/write_spec.rb +25 -1
  187. data/wavefront-cli.gemspec +5 -3
  188. metadata +65 -21
  189. data/spec/wavefront-cli/commands/spec_helper.rb +0 -3
  190. 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