kontena-cli 1.0.6 → 1.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/VERSION +1 -1
  4. data/bin/kontena +4 -1
  5. data/kontena-cli.gemspec +1 -1
  6. data/lib/kontena/callback.rb +1 -1
  7. data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +1 -1
  8. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +5 -5
  9. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +1 -1
  10. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +25 -0
  11. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +1 -1
  12. data/lib/kontena/cli/common.rb +3 -3
  13. data/lib/kontena/cli/config.rb +1 -1
  14. data/lib/kontena/cli/grid_command.rb +2 -0
  15. data/lib/kontena/cli/grids/common.rb +12 -0
  16. data/lib/kontena/cli/grids/health_command.rb +69 -0
  17. data/lib/kontena/cli/helpers/health_helper.rb +53 -0
  18. data/lib/kontena/cli/localhost_web_server.rb +3 -3
  19. data/lib/kontena/cli/master/users/invite_command.rb +1 -1
  20. data/lib/kontena/cli/node_command.rb +2 -0
  21. data/lib/kontena/cli/nodes/health_command.rb +32 -0
  22. data/lib/kontena/cli/nodes/list_command.rb +40 -26
  23. data/lib/kontena/cli/nodes/show_command.rb +0 -1
  24. data/lib/kontena/cli/plugins/install_command.rb +28 -30
  25. data/lib/kontena/cli/plugins/search_command.rb +6 -14
  26. data/lib/kontena/cli/plugins/uninstall_command.rb +7 -11
  27. data/lib/kontena/cli/services/stats_command.rb +4 -2
  28. data/lib/kontena/cli/spinner.rb +20 -4
  29. data/lib/kontena/cli/stacks/show_command.rb +5 -1
  30. data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +22 -0
  31. data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +1 -1
  32. data/lib/kontena/cli/stacks/yaml/reader.rb +1 -0
  33. data/lib/kontena/cli/vault/export_command.rb +22 -0
  34. data/lib/kontena/cli/vault/import_command.rb +80 -0
  35. data/lib/kontena/cli/vault/list_command.rb +4 -0
  36. data/lib/kontena/cli/vault/read_command.rb +8 -3
  37. data/lib/kontena/cli/vault/remove_command.rb +2 -1
  38. data/lib/kontena/cli/vault/update_command.rb +5 -7
  39. data/lib/kontena/cli/vault_command.rb +5 -1
  40. data/lib/kontena/client.rb +25 -2
  41. data/lib/kontena/command.rb +1 -1
  42. data/lib/kontena/debug_instrumentor.rb +70 -0
  43. data/lib/kontena/light_prompt.rb +103 -0
  44. data/lib/kontena/plugin_manager.rb +167 -6
  45. data/lib/kontena/stacks_cache.rb +1 -1
  46. data/lib/kontena_cli.rb +23 -6
  47. data/spec/kontena/cli/grids/health_command_spec.rb +390 -0
  48. data/spec/kontena/cli/nodes/health_command_spec.rb +206 -0
  49. data/spec/kontena/cli/nodes/list_command_spec.rb +205 -0
  50. data/spec/kontena/cli/vault/export_spec.rb +32 -0
  51. data/spec/kontena/cli/vault/import_spec.rb +69 -0
  52. data/spec/kontena/client_spec.rb +39 -0
  53. data/spec/kontena/plugin_manager_spec.rb +7 -7
  54. data/spec/spec_helper.rb +1 -0
  55. data/spec/support/output_helpers.rb +51 -0
  56. metadata +27 -6
@@ -68,7 +68,7 @@ module Kontena
68
68
  end
69
69
 
70
70
  def dputs(msg)
71
- ENV["DEBUG"] && puts(msg)
71
+ ENV["DEBUG"] && STDERR.puts(msg)
72
72
  end
73
73
 
74
74
  def cache(stack, version = nil)
data/lib/kontena_cli.rb CHANGED
@@ -7,16 +7,16 @@ module Kontena
7
7
  # @param [String] command_line
8
8
  # @return [Fixnum] exit_code
9
9
  def self.run(cmdline = "", returning: :status)
10
- ENV["DEBUG"] && puts("Running Kontena.run(#{cmdline.inspect}, returning: #{returning}")
10
+ ENV["DEBUG"] && STDERR.puts("Running Kontena.run(#{cmdline.inspect}, returning: #{returning}")
11
11
  result = Kontena::MainCommand.new(File.basename(__FILE__)).run(cmdline.shellsplit)
12
- ENV["DEBUG"] && puts("Command completed, result: #{result.inspect} status: 0")
12
+ ENV["DEBUG"] && STDERR.puts("Command completed, result: #{result.inspect} status: 0")
13
13
  return 0 if returning == :status
14
14
  return result if returning == :result
15
15
  rescue SystemExit
16
- ENV["DEBUG"] && puts("Command completed with failure, result: #{result.inspect} status: #{$!.status}")
16
+ ENV["DEBUG"] && STDERR.puts("Command completed with failure, result: #{result.inspect} status: #{$!.status}")
17
17
  returning == :status ? $!.status : nil
18
18
  rescue
19
- ENV["DEBUG"] && puts("Command raised #{$!} with message: #{$!.message}\n #{$!.backtrace.join(" \n")}")
19
+ ENV["DEBUG"] && STDERR.puts("Command raised #{$!} with message: #{$!.message}\n #{$!.backtrace.join(" \n")}")
20
20
  returning == :status ? 1 : nil
21
21
  end
22
22
 
@@ -25,12 +25,29 @@ module Kontena
25
25
  "kontena-cli/#{Kontena::Cli::VERSION}"
26
26
  end
27
27
 
28
+ def self.on_windows?
29
+ ENV['OS'] == 'Windows_NT' && RUBY_PLATFORM !~ /cygwin/
30
+ end
31
+
32
+ def self.simple_terminal?
33
+ ENV['KONTENA_SIMPLE_TERM'] || !$stdout.tty?
34
+ end
35
+
28
36
  def self.pastel
29
- @pastel ||= Pastel.new(enabled: $stdout.tty?)
37
+ @pastel ||= Pastel.new(enabled: !simple_terminal?)
30
38
  end
31
39
 
32
40
  def self.prompt
33
- @prompt ||= TTY::Prompt.new(
41
+ return @prompt if @prompt
42
+ if simple_terminal?
43
+ require_relative 'kontena/light_prompt'
44
+ klass = Kontena::LightPrompt
45
+ else
46
+ require 'tty-prompt'
47
+ klass = TTY::Prompt
48
+ end
49
+
50
+ @prompt = klass.new(
34
51
  active_color: :cyan,
35
52
  help_color: :white,
36
53
  error_color: :red,
@@ -0,0 +1,390 @@
1
+ require 'kontena/cli/grids/health_command'
2
+
3
+ describe Kontena::Cli::Grids::HealthCommand do
4
+ include ClientHelpers
5
+ include OutputHelpers
6
+
7
+ before do
8
+ allow(subject).to receive(:health_icon) {|health| health.inspect }
9
+ end
10
+
11
+ context "For a initial_size=1 grid" do
12
+ let :grid do
13
+ {
14
+ "id" => "test",
15
+ "name" => "test",
16
+ "initial_size" => 1,
17
+ "node_count" => 1,
18
+ }
19
+ end
20
+
21
+ context "without any nodes" do
22
+ let :grid_nodes do
23
+ { "nodes" => [ ] }
24
+ end
25
+
26
+ describe '#grid_health' do
27
+ it "returns error" do
28
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:error)
29
+ end
30
+ end
31
+
32
+ describe '#show_grid_health' do
33
+ it "returns false" do
34
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output false, [
35
+ ":error Grid does not have any initial nodes, and requires at least 1 of 1 initial nodes for operation",
36
+ ]
37
+ end
38
+ end
39
+ end
40
+
41
+ context "with a single offline node" do
42
+ let :grid_nodes do
43
+ { "nodes" => [
44
+ {
45
+ "connected" => false,
46
+ "name" => "node-1",
47
+ "node_number" => 1,
48
+ "initial_member" => true,
49
+ },
50
+ ] }
51
+ end
52
+
53
+ describe '#grid_health' do
54
+ it "returns error" do
55
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:error)
56
+ end
57
+ end
58
+
59
+ describe '#show_grid_health' do
60
+ it "returns false" do
61
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output false, [
62
+ ":error Grid does not have any initial nodes online, and requires at least 1 of 1 initial nodes for operation",
63
+ ":error Initial node node-1 is offline",
64
+ ]
65
+ end
66
+ end
67
+ end
68
+
69
+ context "with a single online node" do
70
+ let :grid_nodes do
71
+ { "nodes" => [
72
+ {
73
+ "connected" => true,
74
+ "name" => "node-1",
75
+ "node_number" => 1,
76
+ "initial_member" => true,
77
+ },
78
+ ] }
79
+ end
80
+
81
+ describe '#grid_health' do
82
+ it "returns ok" do
83
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:ok)
84
+ end
85
+ end
86
+
87
+ describe '#show_grid_health' do
88
+ it "returns true" do
89
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
90
+ ":warning Grid only has 1 initial node, and is not high-availability"
91
+ ]
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ context "For a initial_size=2 grid" do
98
+ let :grid do
99
+ {
100
+ "id" => "test",
101
+ "name" => "test",
102
+ "initial_size" => 2,
103
+ "node_count" => 1,
104
+ }
105
+ end
106
+
107
+ context "with a single online node" do
108
+ let :grid_nodes do
109
+ { "nodes" => [
110
+ {
111
+ "connected" => true,
112
+ "name" => "node-1",
113
+ "node_number" => 1,
114
+ "initial_member" => true,
115
+ },
116
+ ] }
117
+ end
118
+
119
+ describe '#grid_health' do
120
+ it "returns error" do
121
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:error)
122
+ end
123
+ end
124
+
125
+ describe '#show_grid_health' do
126
+ it "returns false" do
127
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output false, [
128
+ ":error Grid only has 1 initial nodes, and requires at least 2 of 2 initial nodes for operation",
129
+ ]
130
+ end
131
+ end
132
+ end
133
+
134
+ context "with two online nodes" do
135
+ let :grid_nodes do
136
+ { "nodes" => [
137
+ {
138
+ "connected" => true,
139
+ "name" => "node-1",
140
+ "node_number" => 1,
141
+ "initial_member" => true,
142
+ },
143
+ {
144
+ "connected" => true,
145
+ "name" => "node-2",
146
+ "node_number" => 2,
147
+ "initial_member" => true,
148
+ },
149
+ ] }
150
+ end
151
+
152
+ describe '#grid_health' do
153
+ it "returns ok" do
154
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:ok)
155
+ end
156
+ end
157
+
158
+ describe '#show_grid_health' do
159
+ it "returns true" do
160
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
161
+ ":warning Grid only has 2 initial nodes, and is not high-availability",
162
+ ]
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ context "For a initial_size=3 grid" do
169
+ let :grid do
170
+ {
171
+ "id" => "test",
172
+ "name" => "test",
173
+ "initial_size" => 3,
174
+ "node_count" => 1,
175
+ }
176
+ end
177
+
178
+ context "with a single node" do
179
+ let :grid_nodes do
180
+ { "nodes" => [
181
+ {
182
+ "connected" => true,
183
+ "name" => "node-1",
184
+ "node_number" => 1,
185
+ "initial_member" => true,
186
+ },
187
+ ] }
188
+ end
189
+
190
+ describe '#grid_health' do
191
+ it "returns error" do
192
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:error)
193
+ end
194
+ end
195
+
196
+ describe '#show_grid_health' do
197
+ it "returns false" do
198
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output false, [
199
+ ":error Grid only has 1 initial nodes, and requires at least 2 of 3 initial nodes for operation",
200
+ ]
201
+ end
202
+ end
203
+ end
204
+
205
+ context "with a single online node" do
206
+ let :grid_nodes do
207
+ { "nodes" => [
208
+ {
209
+ "connected" => true,
210
+ "name" => "node-1",
211
+ "node_number" => 1,
212
+ "initial_member" => true,
213
+ },
214
+ {
215
+ "connected" => false,
216
+ "name" => "node-2",
217
+ "node_number" => 1,
218
+ "initial_member" => true,
219
+ },
220
+ ] }
221
+ end
222
+
223
+ describe '#grid_health' do
224
+ it "returns error" do
225
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:error)
226
+ end
227
+ end
228
+
229
+ describe '#show_grid_health' do
230
+ it "returns false" do
231
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output false, [
232
+ ":error Grid only has 1 initial nodes online, and requires at least 2 of 3 initial nodes for operation",
233
+ ":error Initial node node-2 is offline",
234
+ ]
235
+ end
236
+ end
237
+ end
238
+
239
+ context "with two online nodes" do
240
+ let :grid_nodes do
241
+ { "nodes" => [
242
+ {
243
+ "connected" => true,
244
+ "name" => "node-1",
245
+ "node_number" => 1,
246
+ "initial_member" => true,
247
+ },
248
+ {
249
+ "connected" => true,
250
+ "name" => "node-2",
251
+ "node_number" => 2,
252
+ "initial_member" => true,
253
+ },
254
+ ] }
255
+ end
256
+
257
+ describe '#grid_health' do
258
+ it "returns warning" do
259
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:warning)
260
+ end
261
+ end
262
+
263
+ describe '#show_grid_health' do
264
+ it "returns true" do
265
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
266
+ ":warning Grid only has 2 initial nodes of 3 required for high-availability",
267
+ ]
268
+ end
269
+ end
270
+ end
271
+
272
+ context "with two online nodes and one offline node" do
273
+ let :grid_nodes do
274
+ { "nodes" => [
275
+ {
276
+ "connected" => true,
277
+ "name" => "node-1",
278
+ "node_number" => 1,
279
+ "initial_member" => true,
280
+ },
281
+ {
282
+ "connected" => true,
283
+ "name" => "node-2",
284
+ "node_number" => 2,
285
+ "initial_member" => true,
286
+ },
287
+ {
288
+ "connected" => false,
289
+ "name" => "node-3",
290
+ "node_number" => 3,
291
+ "initial_member" => true,
292
+ },
293
+ ] }
294
+ end
295
+
296
+ describe '#grid_health' do
297
+ it "returns warning" do
298
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:warning)
299
+ end
300
+ end
301
+
302
+ describe '#show_grid_health' do
303
+ it "returns true" do
304
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
305
+ ":warning Grid only has 2 initial nodes online of 3 required for high-availability",
306
+ ":warning Initial node node-3 is offline",
307
+ ]
308
+ end
309
+ end
310
+ end
311
+
312
+ context "with two online initial nodes and one non-initial node" do
313
+ let :grid_nodes do
314
+ { "nodes" => [
315
+ {
316
+ "connected" => true,
317
+ "name" => "node-1",
318
+ "node_number" => 1,
319
+ "initial_member" => true,
320
+ },
321
+ {
322
+ "connected" => true,
323
+ "name" => "node-2",
324
+ "node_number" => 2,
325
+ "initial_member" => true,
326
+ },
327
+ {
328
+ "connected" => true,
329
+ "name" => "node-4",
330
+ "node_number" => 4,
331
+ "initial_member" => false,
332
+ },
333
+ ] }
334
+ end
335
+
336
+ describe '#grid_health' do
337
+ it "returns warning" do
338
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:warning)
339
+ end
340
+ end
341
+
342
+ describe '#show_grid_health' do
343
+ it "returns true" do
344
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
345
+ ":warning Grid only has 2 initial nodes of 3 required for high-availability",
346
+ ]
347
+ end
348
+ end
349
+ end
350
+
351
+ context "with three online initial nodes" do
352
+ let :grid_nodes do
353
+ { "nodes" => [
354
+ {
355
+ "connected" => true,
356
+ "name" => "node-1",
357
+ "node_number" => 1,
358
+ "initial_member" => true,
359
+ },
360
+ {
361
+ "connected" => true,
362
+ "name" => "node-2",
363
+ "node_number" => 2,
364
+ "initial_member" => true,
365
+ },
366
+ {
367
+ "connected" => true,
368
+ "name" => "node-3",
369
+ "node_number" => 3,
370
+ "initial_member" => true,
371
+ },
372
+ ] }
373
+ end
374
+
375
+ describe '#grid_health' do
376
+ it "returns ok" do
377
+ expect(subject.grid_health(grid, grid_nodes['nodes'])).to eq(:ok)
378
+ end
379
+ end
380
+
381
+ describe '#show_grid_health' do
382
+ it "returns true" do
383
+ expect{subject.show_grid_health(grid, grid_nodes['nodes'])}.to return_and_output true, [
384
+ ":ok Grid has all 3 of 3 initial nodes online",
385
+ ]
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end