kontena-cli 1.0.6 → 1.1.0.pre1

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.
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