kontena-cli 1.1.0.rc1 → 1.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/kontena/cli/apps/deploy_command.rb +1 -5
  4. data/lib/kontena/cli/cloud/login_command.rb +9 -1
  5. data/lib/kontena/cli/common.rb +2 -2
  6. data/lib/kontena/cli/etcd/health_command.rb +58 -0
  7. data/lib/kontena/cli/etcd_command.rb +2 -0
  8. data/lib/kontena/cli/external_registry_command.rb +0 -2
  9. data/lib/kontena/cli/master/login_command.rb +5 -7
  10. data/lib/kontena/cli/service_command.rb +2 -2
  11. data/lib/kontena/cli/services/deploy_command.rb +1 -5
  12. data/lib/kontena/cli/services/exec_command.rb +84 -0
  13. data/lib/kontena/cli/services/services_helper.rb +4 -1
  14. data/lib/kontena/cli/stacks/common.rb +6 -17
  15. data/lib/kontena/cli/stacks/install_command.rb +2 -10
  16. data/lib/kontena/cli/stacks/show_command.rb +30 -4
  17. data/lib/kontena/cli/stacks/upgrade_command.rb +20 -7
  18. data/lib/kontena/cli/stacks/validate_command.rb +1 -9
  19. data/lib/kontena/cli/stacks/yaml/opto/service_link_resolver.rb +45 -0
  20. data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +15 -0
  21. data/lib/kontena/cli/stacks/yaml/opto/vault_resolver.rb +1 -0
  22. data/lib/kontena/cli/stacks/yaml/reader.rb +36 -26
  23. data/lib/kontena/command.rb +5 -0
  24. data/lib/kontena/main_command.rb +5 -4
  25. data/lib/kontena_cli.rb +4 -0
  26. data/spec/fixtures/stack-with-prompted-variables.yml +5 -1
  27. data/spec/fixtures/stack-with-variables.yml +5 -1
  28. data/spec/kontena/cli/cloud/login_command_spec.rb +1 -0
  29. data/spec/kontena/cli/etcd/health_command_spec.rb +87 -0
  30. data/spec/kontena/cli/master/login_command_spec.rb +8 -17
  31. data/spec/kontena/cli/services/exec_command_spec.rb +137 -0
  32. data/spec/kontena/cli/stacks/install_command_spec.rb +5 -5
  33. data/spec/kontena/cli/stacks/upgrade_command_spec.rb +39 -32
  34. data/spec/kontena/cli/stacks/yaml/reader_spec.rb +22 -0
  35. data/spec/support/client_helpers.rb +6 -2
  36. data/spec/support/output_helpers.rb +23 -0
  37. metadata +11 -7
  38. data/lib/kontena/cli/external_registries/delete_command.rb +0 -15
  39. data/lib/kontena/cli/login_command.rb +0 -12
  40. data/lib/kontena/cli/register_command.rb +0 -9
  41. data/lib/kontena/cli/services/delete_command.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e7c1e0f1f4b7150cbb38ae75bd31b5d9c011018
4
- data.tar.gz: 105cd534097a4479c050b0ca174014c61b327677
3
+ metadata.gz: f7edb62c595acf6b8f5aaea89084034682684ff6
4
+ data.tar.gz: c90522985a940d60902b7f817b5e1c1e9c26ebec
5
5
  SHA512:
6
- metadata.gz: c8fb7ead66ba6c861d79544f3955b13eadf8e3ceab55fbf3f3a1c108f7bcf23730ee97fccec1cf74b5d2ea8239af9eeb5ac6453b5892eb4b60ddbeda4392d9de
7
- data.tar.gz: 27978ab4aea44afadff0f59119b993771e36ef3fc4a8688e15d88d3a3cf54525600d70b4d8b5c566790063f8b5a603a25d1a782c0eac8ea81c70805faf2299b1
6
+ metadata.gz: f213b43e9dc53072014b7ded6f3700a4ff3158f1865c7c7c73aa63fd123af5372f8c7c9bf120dde7ae481104b43eef59e8e991e22cb76edc2472b9e1086e9146
7
+ data.tar.gz: 2d2d45f3431164ab8a56ce97b77d5296f6e03788c2e2f9dc0cefbecf2b2672219f377a09c7078a7512e1fead10dff3f721970ca32e4ed764571013d5bbde11b1
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0.rc1
1
+ 1.1.0.rc2
@@ -14,7 +14,6 @@ module Kontena::Cli::Apps
14
14
  option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
15
15
  option '--async', :flag, 'Run deploys async/parallel'
16
16
  option '--force', :flag, 'Force deploy even if service does not have any changes'
17
- option '--force-deploy', :flag, '[DEPRECATED: use --force]'
18
17
 
19
18
  option '--skip-validation', :flag, 'Skip YAML file validation', default: false
20
19
  parameter "[SERVICE] ...", "Services to start"
@@ -46,10 +45,7 @@ module Kontena::Cli::Apps
46
45
  queue.each do |service|
47
46
  name = service['id'].split('/').last
48
47
  options = {}
49
- options[:force] = true if force? || force_deploy? # deprecated
50
- if force_deploy?
51
- warning " --force-deploy will deprecate in the future, use --force"
52
- end
48
+ options[:force] = true if force?
53
49
  spinner "Deploying #{unprefixed_name(name).colorize(:cyan)} " do
54
50
  deployment = deploy_service(token, name, options)
55
51
  unless async?
@@ -51,6 +51,14 @@ module Kontena::Cli::Cloud
51
51
  end
52
52
 
53
53
  def web_flow
54
+ if Kontena.browserless? && !force?
55
+ STDERR.puts "Your current environment does not seem to support opening a local graphical WWW browser."
56
+ STDERR.puts
57
+ STDERR.puts "You can perorm a login on another computer, copy the token and use it with 'kontena cloud login --token <token>'."
58
+ STDERR.puts "There will be an easier way to log in from a browserless environment soon."
59
+ exit_with_error 'Unable to launch a web browser'
60
+ end
61
+
54
62
  require_relative '../localhost_web_server'
55
63
  require 'launchy'
56
64
 
@@ -85,7 +93,7 @@ module Kontena::Cli::Cloud
85
93
 
86
94
  server_thread = Thread.new { Thread.main['response'] = web_server.serve_one }
87
95
  browser_thread = Thread.new { Launchy.open(uri.to_s) }
88
-
96
+
89
97
  spinner "Waiting for browser authorization response" do
90
98
  server_thread.join
91
99
  end
@@ -92,12 +92,12 @@ module Kontena
92
92
 
93
93
  def warning(msg)
94
94
  warning = pastel.yellow('warn')
95
- STDERR.puts " [#{warning}] #{msg}"
95
+ $stderr.puts " [#{warning}] #{msg}"
96
96
  end
97
97
 
98
98
  def exit_with_error(msg, code = 1)
99
99
  error = pastel.red('error')
100
- STDERR.puts " [#{error}] #{msg}"
100
+ $stderr.puts " [#{error}] #{msg}"
101
101
  exit code
102
102
  end
103
103
 
@@ -0,0 +1,58 @@
1
+ require_relative 'common'
2
+
3
+ module Kontena::Cli::Etcd
4
+ class HealthCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Kontena::Cli::Helpers::HealthHelper
8
+
9
+ parameter "[NODE]", "Show health for specific node"
10
+
11
+ requires_current_master
12
+ requires_current_grid
13
+
14
+ def execute
15
+ require_api_url
16
+ token = require_token
17
+
18
+ health = true
19
+
20
+ if self.node
21
+ node_health = client.get("nodes/#{current_grid}/#{self.node}/health")
22
+
23
+ health = show_node_health(node_health)
24
+ else
25
+ nodes = client.get("grids/#{current_grid}/nodes")['nodes']
26
+
27
+ nodes.each do |node|
28
+ node_health = client.get("nodes/#{current_grid}/#{node['name']}/health")
29
+
30
+ if !show_node_health(node_health)
31
+ health = false
32
+ end
33
+ end
34
+ end
35
+
36
+ return health
37
+ end
38
+
39
+ # @return [Boolean]
40
+ def show_node_health(node_health)
41
+ etcd_health = node_health['etcd_health']
42
+
43
+ if !node_health['connected']
44
+ puts "#{health_icon :offline} Node #{node_health['name']} is offline"
45
+ return false
46
+ elsif etcd_health['health']
47
+ puts "#{health_icon :ok} Node #{node_health['name']} is healthy"
48
+ return true
49
+ elsif etcd_health['error']
50
+ puts "#{health_icon :error} Node #{node_health['name']} is unhealthy: #{etcd_health['error']}"
51
+ return false
52
+ else
53
+ puts "#{health_icon :error} Node #{node_health['name']} is unhealthy"
54
+ return false
55
+ end
56
+ end
57
+ end
58
+ end
@@ -3,6 +3,7 @@ require_relative 'etcd/set_command'
3
3
  require_relative 'etcd/mkdir_command'
4
4
  require_relative 'etcd/list_command'
5
5
  require_relative 'etcd/remove_command'
6
+ require_relative 'etcd/health_command'
6
7
 
7
8
  class Kontena::Cli::EtcdCommand < Kontena::Command
8
9
 
@@ -11,6 +12,7 @@ class Kontena::Cli::EtcdCommand < Kontena::Command
11
12
  subcommand ["mkdir", "mk"], "Create a directory", Kontena::Cli::Etcd::MkdirCommand
12
13
  subcommand ["list", "ls"], "List a directory", Kontena::Cli::Etcd::ListCommand
13
14
  subcommand "rm", "Remove a key or a directory", Kontena::Cli::Etcd::RemoveCommand
15
+ subcommand "health", "Check etcd health", Kontena::Cli::Etcd::HealthCommand
14
16
 
15
17
  def execute
16
18
  end
@@ -1,6 +1,5 @@
1
1
  require_relative 'external_registries/add_command'
2
2
  require_relative 'external_registries/list_command'
3
- require_relative 'external_registries/delete_command'
4
3
  require_relative 'external_registries/remove_command'
5
4
 
6
5
  class Kontena::Cli::ExternalRegistryCommand < Kontena::Command
@@ -8,7 +7,6 @@ class Kontena::Cli::ExternalRegistryCommand < Kontena::Command
8
7
  subcommand "add", "Add external Docker image registry", Kontena::Cli::ExternalRegistries::AddCommand
9
8
  subcommand ["list", "ls"], "List external Docker image registries", Kontena::Cli::ExternalRegistries::ListCommand
10
9
  subcommand ["remove", "rm"], "Remove external Docker image registry", Kontena::Cli::ExternalRegistries::RemoveCommand
11
- subcommand "delete", "[DEPRECATED] Delete external Docker image registry", Kontena::Cli::ExternalRegistries::DeleteCommand
12
10
 
13
11
  def execute
14
12
  end
@@ -9,7 +9,7 @@ module Kontena::Cli::Master
9
9
  option ['-t', '--token'], '[TOKEN]', 'Use a pre-generated access token', environment_variable: 'KONTENA_TOKEN'
10
10
  option ['-n', '--name'], '[NAME]', 'Set server name', environment_variable: 'KONTENA_MASTER'
11
11
  option ['-c', '--code'], '[CODE]', 'Use authorization code generated during master install'
12
- option ['-r', '--remote'], :flag, 'Do not try to open a browser'
12
+ option ['-r', '--[no-]remote'], :flag, 'Login using a browser on another device', default: Kontena.browserless?
13
13
  option ['-e', '--expires-in'], '[SECONDS]', 'Request token with expiration of X seconds. Use 0 to never expire', default: 7200
14
14
  option ['-v', '--verbose'], :flag, 'Increase output verbosity'
15
15
  option ['-f', '--force'], :flag, 'Force reauthentication'
@@ -69,13 +69,14 @@ module Kontena::Cli::Master
69
69
  if self.remote?
70
70
  # no local browser? tell user to launch an external one
71
71
  display_remote_message(server, auth_params)
72
- update_server_to_config(server)
73
- exit 1
72
+ auth_code = prompt.ask("Enter code displayed in browser:")
73
+ use_authorization_code(server, auth_code)
74
74
  else
75
75
  # local web flow
76
76
  web_flow(server, auth_params)
77
- display_login_info(only: :master) unless (running_silent? || self.no_login_info?)
78
77
  end
78
+
79
+ display_login_info(only: :master) unless (running_silent? || self.no_login_info?)
79
80
  end
80
81
 
81
82
  def next_default_name
@@ -170,9 +171,6 @@ module Kontena::Cli::Master
170
171
  else
171
172
  puts "Visit this URL in a browser:"
172
173
  puts "#{url}"
173
- puts
174
- puts "Then complete the authentication by using:"
175
- puts "kontena master login --code <CODE FROM BROWSER> #{server.url}"
176
174
  end
177
175
  end
178
176
 
@@ -7,7 +7,6 @@ require_relative 'services/start_command'
7
7
  require_relative 'services/restart_command'
8
8
  require_relative 'services/create_command'
9
9
  require_relative 'services/scale_command'
10
- require_relative 'services/delete_command'
11
10
  require_relative 'services/remove_command'
12
11
  require_relative 'services/containers_command'
13
12
  require_relative 'services/logs_command'
@@ -19,6 +18,7 @@ require_relative 'services/secret_command'
19
18
 
20
19
  require_relative 'services/link_command'
21
20
  require_relative 'services/unlink_command'
21
+ require_relative 'services/exec_command'
22
22
 
23
23
  class Kontena::Cli::ServiceCommand < Kontena::Command
24
24
 
@@ -32,7 +32,6 @@ class Kontena::Cli::ServiceCommand < Kontena::Command
32
32
  subcommand "restart", "Restart service", Kontena::Cli::Services::RestartCommand
33
33
  subcommand "scale", "Scale service", Kontena::Cli::Services::ScaleCommand
34
34
  subcommand ["remove", "rm"], "Remove service", Kontena::Cli::Services::RemoveCommand
35
- subcommand "delete", "[DEPRECATED] Delete service", Kontena::Cli::Services::DeleteCommand
36
35
  subcommand "containers", "List service containers", Kontena::Cli::Services::ContainersCommand
37
36
  subcommand "logs", "Show service logs", Kontena::Cli::Services::LogsCommand
38
37
  subcommand "stats", "Show service statistics", Kontena::Cli::Services::StatsCommand
@@ -44,6 +43,7 @@ class Kontena::Cli::ServiceCommand < Kontena::Command
44
43
 
45
44
  subcommand "link", "Link service to another service", Kontena::Cli::Services::LinkCommand
46
45
  subcommand "unlink", "Unlink service from another service", Kontena::Cli::Services::UnlinkCommand
46
+ subcommand "exec", "Execute commands in service containers", Kontena::Cli::Services::ExecCommand
47
47
 
48
48
  def execute
49
49
  end
@@ -8,17 +8,13 @@ module Kontena::Cli::Services
8
8
 
9
9
  parameter "NAME", "Service name"
10
10
  option '--force', :flag, 'Force deploy even if service does not have any changes'
11
- option '--force-deploy', :flag, '[DEPRECATED: use --force]'
12
11
 
13
12
  def execute
14
13
  require_api_url
15
14
  token = require_token
16
15
  service_id = name
17
16
  data = {}
18
- data[:force] = true if force? || force_deploy? # deprecated
19
- if force_deploy?
20
- warning "--force-deploy will deprecate in the future, use --force"
21
- end
17
+ data[:force] = true if force?
22
18
  spinner "Deploying service #{name.colorize(:cyan)} " do
23
19
  deployment = deploy_service(token, name, data)
24
20
  wait_for_deploy_to_finish(token, deployment)
@@ -0,0 +1,84 @@
1
+ require_relative 'services_helper'
2
+
3
+ module Kontena::Cli::Services
4
+ class ExecCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include ServicesHelper
8
+
9
+ parameter "NAME", "Service name"
10
+ parameter "CMD ...", "Command"
11
+
12
+ option ["-i", "--instance"], "INSTANCE", "Exec on given numbered instance, default first running" do |value| Integer(value) end
13
+ option ["-a", "--all"], :flag, "Exec on all running instances"
14
+ option ["--shell"], :flag, "Execute as a shell command"
15
+ option ["--skip"], :flag, "Skip failed instances when executing --all"
16
+ option ["--silent"], :flag, "Do not show exec status"
17
+ option ["--verbose"], :flag, "Show exec status"
18
+
19
+ requires_current_master
20
+ requires_current_grid
21
+
22
+ # Exits if exec returns with non-zero
23
+ def exec_container(container)
24
+ if shell?
25
+ cmd = ['sh', '-c', cmd_list.join(' ')]
26
+ else
27
+ cmd = cmd_list
28
+ end
29
+
30
+ stdout = stderr = exit_status = nil
31
+
32
+ if !silent? && (verbose? || all?)
33
+ spinner "Executing command on #{container['name']}" do
34
+ stdout, stderr, exit_status = client.post("containers/#{container['id']}/exec", {cmd: cmd})
35
+
36
+ raise Kontena::Cli::SpinAbort if exit_status != 0
37
+ end
38
+ else
39
+ stdout, stderr, exit_status = client.post("containers/#{container['id']}/exec", {cmd: cmd})
40
+ end
41
+
42
+ stdout.each do |chunk| $stdout.write chunk end
43
+ stderr.each do |chunk| $stderr.write chunk end
44
+
45
+ exit exit_status if exit_status != 0 && !skip?
46
+
47
+ return exit_status == 0
48
+ end
49
+
50
+ def execute
51
+ service_containers = client.get("services/#{parse_service_id(name)}/containers")['containers']
52
+ service_containers.sort_by! { |container| container['instance_number'] }
53
+ running_containers = service_containers.select{|container| container['status'] == 'running' }
54
+
55
+ if running_containers.empty?
56
+ exit_with_error "Service #{name} does not have any running containers"
57
+ end
58
+
59
+ if all?
60
+ ret = true
61
+ service_containers.each do |container|
62
+ if container['status'] == 'running'
63
+ if !exec_container(container)
64
+ ret = false
65
+ end
66
+ else
67
+ warning "Service #{name} container #{container['name']} is #{container['status']}, skipping"
68
+ end
69
+ end
70
+ return ret
71
+ elsif instance
72
+ if !(container = service_containers.find{|container| container['instance_number'] == instance})
73
+ exit_with_error "Service #{name} does not have container instance #{instance}"
74
+ elsif container['status'] != 'running'
75
+ exit_with_error "Service #{name} container #{container['name']} is not running, it is #{container['status']}"
76
+ else
77
+ exec_container(container)
78
+ end
79
+ else
80
+ exec_container(running_containers.first)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -43,10 +43,13 @@ module Kontena
43
43
  service = get_service(token, service_id)
44
44
  grid = service['id'].split('/')[0]
45
45
  puts "#{service['id']}:"
46
+ puts " created: #{service['created_at']}"
47
+ puts " updated: #{service['updated_at']}"
46
48
  puts " stack: #{service['stack']['id'] }"
47
- puts " status: #{service['state'] }"
49
+ puts " state: #{service['state'] }"
48
50
  puts " image: #{service['image']}"
49
51
  puts " revision: #{service['revision']}"
52
+ puts " stack_revision: #{service['stack_revision']}" if service['stack_revision']
50
53
  puts " stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
51
54
  puts " scaling: #{service['instances'] }"
52
55
  puts " strategy: #{service['strategy']}"
@@ -21,18 +21,8 @@ module Kontena::Cli::Stacks
21
21
  end
22
22
 
23
23
  module StackFileOrNameParam
24
- attr_accessor :from_registry
25
-
26
24
  def self.included(where)
27
- where.parameter "[FILE]", "Kontena stack file or a registry stack name (user/stack or user/stack:version)", default: "kontena.yml", attribute_name: :filename do |filename|
28
- if !File.exist?(filename) && filename =~ /\A[a-zA-Z0-9\_\.\-]+\/[a-zA-Z0-9\_\.\-]+(?::.*)?\z/
29
- @from_registry = true
30
- else
31
- @from_registry = false
32
- require_config_file(filename)
33
- end
34
- filename
35
- end
25
+ where.parameter "[FILE]", "Kontena stack file, registry stack name (user/stack or user/stack:version) or URL", default: "kontena.yml", attribute_name: :filename
36
26
  end
37
27
  end
38
28
 
@@ -59,8 +49,8 @@ module Kontena::Cli::Stacks
59
49
  @stack_name ||= self.name || stack_name_from_yaml(filename)
60
50
  end
61
51
 
62
- def reader_from_yaml(filename, from_registry: false, name: nil, values: nil)
63
- reader = Kontena::Cli::Stacks::YAML::Reader.new(filename, from_registry: from_registry, values: values)
52
+ def reader_from_yaml(filename, name: nil, values: nil, defaults: nil)
53
+ reader = Kontena::Cli::Stacks::YAML::Reader.new(filename, values: values, defaults: defaults)
64
54
  if reader.stack_name.nil?
65
55
  exit_with_error "Stack MUST have stack name in YAML top level field 'stack'! Aborting."
66
56
  end
@@ -68,8 +58,8 @@ module Kontena::Cli::Stacks
68
58
  reader
69
59
  end
70
60
 
71
- def stack_from_yaml(filename, from_registry: false, name: nil, values: nil)
72
- reader = reader_from_yaml(filename, from_registry: from_registry, name: name, values: values)
61
+ def stack_from_yaml(filename, name: nil, values: nil, defaults: nil)
62
+ reader = reader_from_yaml(filename, name: name, values: values, defaults: defaults)
73
63
  outcome = reader.execute
74
64
 
75
65
  hint_on_validation_notifications(outcome[:notifications]) if outcome[:notifications].size > 0
@@ -83,8 +73,7 @@ module Kontena::Cli::Stacks
83
73
  'source' => reader.raw_content,
84
74
  'registry' => 'file://',
85
75
  'services' => kontena_services,
86
- 'variables' => outcome[:variables],
87
- 'vault_keys' => outcome[:vault_keys]
76
+ 'variables' => outcome[:variables]
88
77
  }
89
78
  stack
90
79
  end
@@ -11,7 +11,7 @@ module Kontena::Cli::Stacks
11
11
  include Common::StackFileOrNameParam
12
12
 
13
13
  include Common::StackNameOption
14
- option '--deploy', :flag, 'Deploy after installation'
14
+ option '--[no-]deploy', :flag, 'Trigger deploy after installation', default: true
15
15
 
16
16
  include Common::StackValuesFromOption
17
17
 
@@ -20,15 +20,7 @@ module Kontena::Cli::Stacks
20
20
  requires_current_master_token
21
21
 
22
22
  def execute
23
-
24
- if !File.exist?(filename) && filename =~ /\A[a-zA-Z0-9\_\.\-]+\/[a-zA-Z0-9\_\.\-]+(?::.*)?\z/
25
- from_registry = true
26
- else
27
- from_registry = false
28
- require_config_file(filename)
29
- end
30
-
31
- stack = stack_from_yaml(filename, from_registry: from_registry, name: name, values: values)
23
+ stack = stack_from_yaml(filename, name: name, values: values)
32
24
 
33
25
  stack['name'] = name if name
34
26
  spinner "Creating stack #{pastel.cyan(stack['name'])} " do
@@ -25,11 +25,12 @@ module Kontena::Cli::Stacks
25
25
  stack = fetch_stack(name)
26
26
 
27
27
  puts "#{stack['name']}:"
28
+ puts " created: #{stack['created_at']}"
29
+ puts " updated: #{stack['updated_at']}"
28
30
  puts " state: #{stack['state']}"
29
31
  puts " stack: #{stack['stack']}"
30
32
  puts " version: #{stack['version']}"
31
- puts " created_at: #{stack['created_at']}"
32
- puts " updated_at: #{stack['updated_at']}"
33
+ puts " revision: #{stack['revision']}"
33
34
  puts " expose: #{stack['expose'] || '-'}"
34
35
  puts " services:"
35
36
  stack['services'].each do |service|
@@ -43,14 +44,16 @@ module Kontena::Cli::Stacks
43
44
  service = get_service(token, service_id)
44
45
  pad = ' '.freeze
45
46
  puts "#{pad}#{service['name']}:"
47
+ puts "#{pad} created: #{service['created_at']}"
48
+ puts "#{pad} updated: #{service['updated_at']}"
46
49
  puts "#{pad} image: #{service['image']}"
47
- puts "#{pad} status: #{service['state'] }"
50
+ puts "#{pad} revision: #{service['stack_revision']}"
51
+ puts "#{pad} state: #{service['state'] }"
48
52
  if service['health_status']
49
53
  puts "#{pad} health_status:"
50
54
  puts "#{pad} healthy: #{service['health_status']['healthy']}"
51
55
  puts "#{pad} total: #{service['health_status']['total']}"
52
56
  end
53
- puts "#{pad} revision: #{service['revision']}"
54
57
  puts "#{pad} stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
55
58
  puts "#{pad} scaling: #{service['instances'] }"
56
59
  puts "#{pad} strategy: #{service['strategy']}"
@@ -71,6 +74,15 @@ module Kontena::Cli::Stacks
71
74
  end
72
75
  end
73
76
 
77
+ if service['secrets'].to_a.size > 0
78
+ puts "#{pad} secrets: "
79
+ service['secrets'].to_a.each do |s|
80
+ puts "#{pad} - secret: #{s['secret']}"
81
+ puts "#{pad} name: #{s['name']}"
82
+ puts "#{pad} type: #{s['type']}"
83
+ end
84
+ end
85
+
74
86
  unless service['cmd'].to_s.empty?
75
87
  if service['cmd']
76
88
  puts "#{pad} cmd: #{service['cmd'].join(' ')}"
@@ -86,6 +98,20 @@ module Kontena::Cli::Stacks
86
98
  end
87
99
  end
88
100
 
101
+ if service['volumes'].to_a.size > 0
102
+ puts "#{pad} volumes:"
103
+ service['volumes'].to_a.each do |v|
104
+ puts "#{pad} - #{v}"
105
+ end
106
+ end
107
+
108
+ if service['volumes_from'].to_a.size > 0
109
+ puts "#{pad} volumes_from:"
110
+ service['volumes_from'].to_a.each do |v|
111
+ puts "#{pad} - #{v}"
112
+ end
113
+ end
114
+
89
115
  if service['links'].to_a.size > 0
90
116
  puts "#{pad} links: "
91
117
  service['links'].to_a.each do |l|