kontena-cli 1.3.0.pre1 → 1.3.0.pre2

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/kontena +2 -1
  4. data/lib/kontena/callback.rb +1 -1
  5. data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +1 -2
  6. data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +2 -3
  7. data/lib/kontena/callbacks/master/deploy/01_show_logo_before_deploy.rb +1 -2
  8. data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +2 -2
  9. data/lib/kontena/callbacks/master/deploy/40_install_ssl_certificate_after_deploy.rb +2 -2
  10. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +9 -9
  11. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +2 -2
  12. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +1 -2
  13. data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +1 -2
  14. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +2 -3
  15. data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +2 -2
  16. data/lib/kontena/cli/apps/common.rb +0 -1
  17. data/lib/kontena/cli/apps/init_command.rb +2 -0
  18. data/lib/kontena/cli/apps/kontena_yml_generator.rb +2 -1
  19. data/lib/kontena/cli/apps/list_command.rb +10 -2
  20. data/lib/kontena/cli/apps/yaml/reader.rb +2 -1
  21. data/lib/kontena/cli/apps/yaml/service_extender.rb +0 -1
  22. data/lib/kontena/cli/cloud/login_command.rb +51 -7
  23. data/lib/kontena/cli/cloud/master/list_command.rb +14 -11
  24. data/lib/kontena/cli/common.rb +36 -83
  25. data/lib/kontena/cli/config.rb +46 -29
  26. data/lib/kontena/cli/containers/list_command.rb +30 -41
  27. data/lib/kontena/cli/etcd/list_command.rb +12 -7
  28. data/lib/kontena/cli/external_registries/list_command.rb +14 -8
  29. data/lib/kontena/cli/grids/list_command.rb +18 -10
  30. data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +7 -5
  31. data/lib/kontena/cli/grids/users/list_command.rb +9 -7
  32. data/lib/kontena/cli/localhost_web_server.rb +3 -3
  33. data/lib/kontena/cli/log_formatters/compact.rb +65 -0
  34. data/lib/kontena/cli/log_formatters/strip_color.rb +13 -0
  35. data/lib/kontena/cli/master/config/import_command.rb +2 -1
  36. data/lib/kontena/cli/master/config/set_command.rb +1 -1
  37. data/lib/kontena/cli/master/list_command.rb +16 -10
  38. data/lib/kontena/cli/master/token/list_command.rb +23 -12
  39. data/lib/kontena/cli/master/user/invite_command.rb +1 -1
  40. data/lib/kontena/cli/master/user/list_command.rb +17 -6
  41. data/lib/kontena/cli/nodes/labels/list_command.rb +3 -0
  42. data/lib/kontena/cli/nodes/list_command.rb +58 -37
  43. data/lib/kontena/cli/nodes/show_command.rb +1 -1
  44. data/lib/kontena/cli/plugins/install_command.rb +2 -2
  45. data/lib/kontena/cli/plugins/list_command.rb +19 -5
  46. data/lib/kontena/cli/plugins/uninstall_command.rb +1 -1
  47. data/lib/kontena/cli/services/containers_command.rb +7 -0
  48. data/lib/kontena/cli/services/envs/list_command.rb +6 -4
  49. data/lib/kontena/cli/services/list_command.rb +47 -36
  50. data/lib/kontena/cli/services/services_helper.rb +9 -16
  51. data/lib/kontena/cli/services/stats_command.rb +2 -1
  52. data/lib/kontena/cli/spinner.rb +3 -5
  53. data/lib/kontena/cli/stacks/common.rb +4 -4
  54. data/lib/kontena/cli/stacks/list_command.rb +42 -33
  55. data/lib/kontena/cli/stacks/registry/search_command.rb +6 -0
  56. data/lib/kontena/cli/stacks/registry/show_command.rb +2 -0
  57. data/lib/kontena/cli/stacks/registry_command.rb +1 -2
  58. data/lib/kontena/cli/stacks/validate_command.rb +1 -0
  59. data/lib/kontena/cli/stacks/yaml/reader.rb +3 -2
  60. data/lib/kontena/cli/stacks/yaml/service_extender.rb +0 -1
  61. data/lib/kontena/cli/stacks/yaml/validations.rb +1 -1
  62. data/lib/kontena/cli/table_generator.rb +125 -0
  63. data/lib/kontena/cli/vault/export_command.rb +7 -4
  64. data/lib/kontena/cli/vault/import_command.rb +3 -0
  65. data/lib/kontena/cli/vault/list_command.rb +23 -10
  66. data/lib/kontena/cli/volumes/create_command.rb +8 -4
  67. data/lib/kontena/cli/volumes/list_command.rb +15 -7
  68. data/lib/kontena/client.rb +44 -33
  69. data/lib/kontena/command.rb +7 -4
  70. data/lib/kontena/debug_instrumentor.rb +10 -9
  71. data/lib/kontena/main_command.rb +1 -3
  72. data/lib/kontena/plugin_manager.rb +15 -7
  73. data/lib/kontena/stacks_cache.rb +7 -7
  74. data/lib/kontena/stacks_client.rb +24 -5
  75. data/lib/kontena/util.rb +43 -15
  76. data/lib/kontena_cli.rb +71 -14
  77. data/spec/kontena/cli/cloud/login_command_spec.rb +42 -0
  78. data/spec/kontena/cli/containers/list_command_spec.rb +1 -2
  79. data/spec/kontena/cli/nodes/list_command_spec.rb +153 -126
  80. data/spec/kontena/cli/registry/create_spec.rb +22 -0
  81. data/spec/kontena/cli/services/stats_command_spec.rb +22 -0
  82. data/spec/kontena/cli/table_generator_spec.rb +118 -0
  83. data/spec/kontena/cli/version_command_spec.rb +2 -2
  84. data/spec/kontena/client_spec.rb +4 -3
  85. data/spec/support/client_helpers.rb +3 -3
  86. data/spec/support/output_helpers.rb +54 -8
  87. metadata +11 -2
@@ -1,26 +1,21 @@
1
- require 'tty-prompt'
2
- require 'pastel'
3
- require 'uri'
4
- require 'io/console'
5
-
6
- require 'kontena/cli/config'
7
- require 'kontena/cli/spinner'
1
+ require 'forwardable'
8
2
 
9
3
  module Kontena
10
4
  module Cli
11
5
  module Common
12
-
13
- def logger
14
- return @logger if @logger
15
- @logger = Logger.new(ENV["DEBUG"] ? $stderr : $stdout)
16
- @logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
17
- @logger.progname = 'COMMON'
18
- @logger
19
- end
20
-
21
- def pastel
22
- @pastel ||= Pastel.new(enabled: $stdout.tty?)
23
- end
6
+ extend Forwardable
7
+
8
+ def_delegators :Kontena, :pastel, :prompt, :logger
9
+ def_delegators :prompt, :ask, :yes?
10
+ def_delegators :config,
11
+ :current_grid=, :require_current_grid, :current_master,
12
+ :current_master=, :require_current_master, :require_current_account,
13
+ :current_account
14
+ def_delegator Kontena::Cli::Spinner, :spin, :spinner
15
+ def_delegator Kontena::Cli::Config, :instance, :config
16
+ def_delegator Kontena::Cli::Config, :instance, :settings
17
+ def_delegator :config, :config_filename, :settings_filename
18
+ def_delegator :client, :server_version, :api_url_version
24
19
 
25
20
  # Read from STDIN. If stdin is a console, use prompt to ask.
26
21
  # @param [String] message
@@ -43,6 +38,10 @@ module Kontena
43
38
  self.respond_to?(:verbose?) && self.verbose?
44
39
  end
45
40
 
41
+ def running_quiet?
42
+ self.respond_to?(:quiet?) && self.quiet?
43
+ end
44
+
46
45
  # Puts that puts even when self.silent?
47
46
  def sputs(*msgs)
48
47
  ::Kernel.puts(*msgs)
@@ -87,9 +86,19 @@ module Kontena
87
86
  def vspinner(msg, &block)
88
87
  return vfakespinner(msg) unless block_given?
89
88
 
90
- if running_verbose?
89
+ if running_verbose? && $stdout.tty?
91
90
  spinner(msg, &block)
92
91
  else
92
+ logger.debug { msg }
93
+ yield
94
+ end
95
+ end
96
+
97
+ def spin_if(obj_or_proc, message, &block)
98
+ if (obj_or_proc.respond_to?(:call) && obj_or_proc.call) || obj_or_proc
99
+ spinner(message, &block)
100
+ else
101
+ logger.debug { message }
93
102
  yield
94
103
  end
95
104
  end
@@ -97,7 +106,7 @@ module Kontena
97
106
  # Like vspinner but without actually running any block
98
107
  def vfakespinner(msg, success: true)
99
108
  if !running_verbose?
100
- logger.debug msg
109
+ logger.debug { msg }
101
110
  return
102
111
  end
103
112
  puts " [#{ success ? 'done'.colorize(:green) : 'fail'.colorize(:red)}] #{msg}"
@@ -113,10 +122,7 @@ module Kontena
113
122
  $stderr.puts " [#{error}] #{msg}"
114
123
  exit code
115
124
  end
116
-
117
- def config
118
- Kontena::Cli::Config.instance
119
- end
125
+ module_function :exit_with_error
120
126
 
121
127
  def require_api_url
122
128
  config.require_current_master.url
@@ -148,20 +154,8 @@ module Kontena
148
154
  logger.debug "Refreshing failed: #{ex.class.name} : #{ex.message}"
149
155
  end
150
156
 
151
- def require_current_master
152
- config.require_current_master
153
- end
154
-
155
- def require_current_account
156
- config.require_current_account
157
- end
158
-
159
- def current_account
160
- config.current_account
161
- end
162
-
163
157
  def kontena_account
164
- @kontena_account ||= config.find_account(ENV['KONTENA_ACCOUNT'] || 'kontena')
158
+ @kontena_account ||= config.current_account
165
159
  end
166
160
 
167
161
  def cloud_auth?
@@ -171,10 +165,6 @@ module Kontena
171
165
  true
172
166
  end
173
167
 
174
- def api_url_version
175
- client.server_version
176
- end
177
-
178
168
  def cloud_client
179
169
  @cloud_client ||= Kontena::Client.new(kontena_account.url, kontena_account.token, prefix: '/')
180
170
  end
@@ -184,11 +174,13 @@ module Kontena
184
174
  end
185
175
 
186
176
  def client(token = nil, api_url = nil)
177
+ return @client if @client
178
+
187
179
  if token.kind_of?(String)
188
180
  token = Kontena::Cli::Config::Token.new(access_token: token)
189
181
  end
190
182
 
191
- @client ||= Kontena::Client.new(
183
+ @client = Kontena::Client.new(
192
184
  api_url || require_current_master.url,
193
185
  token || require_current_master.token
194
186
  )
@@ -198,26 +190,10 @@ module Kontena
198
190
  @client = nil
199
191
  end
200
192
 
201
- def settings_filename
202
- config.config_filename
203
- end
204
-
205
- def settings
206
- config
207
- end
208
-
209
193
  def api_url
210
194
  config.require_current_master.url
211
195
  end
212
196
 
213
- def current_grid=(grid)
214
- config.current_grid=(grid)
215
- end
216
-
217
- def require_current_grid
218
- config.require_current_grid
219
- end
220
-
221
197
  def clear_current_grid
222
198
  current_master.delete_field(:grid) if require_current_master.respond_to?(:grid)
223
199
  config.write
@@ -231,31 +207,11 @@ module Kontena
231
207
  config.find_server_index(require_current_master.name)
232
208
  end
233
209
 
234
- def current_master
235
- config.current_master
236
- end
237
-
238
- def current_master=(master_alias)
239
- config.current_master = master_alias
240
- end
241
-
242
210
  def error(message = "Error")
243
211
  prompt.error(message)
244
212
  exit(1)
245
213
  end
246
214
 
247
- def ask(question = "")
248
- prompt.ask(question)
249
- end
250
-
251
- def yes?(question = "")
252
- prompt.yes?(question)
253
- end
254
-
255
- def prompt
256
- ::Kontena.prompt
257
- end
258
-
259
215
  def confirm_command(name, message = nil)
260
216
  if self.respond_to?(:force?) && self.force?
261
217
  return
@@ -289,10 +245,6 @@ module Kontena
289
245
  config.add_server(master_info.merge('name' => server_name))
290
246
  end
291
247
 
292
- def spinner(msg, &block)
293
- Kontena::Cli::Spinner.spin(msg, &block)
294
- end
295
-
296
248
  def any_key_to_continue_with_timeout(timeout=9)
297
249
  return nil if running_silent?
298
250
  return nil unless $stdout.tty?
@@ -352,6 +304,7 @@ module Kontena
352
304
  def display_logo
353
305
  puts File.read(File.expand_path('../../../../LOGO', __FILE__))
354
306
  end
307
+ module_function :display_logo
355
308
  end
356
309
  end
357
310
  end
@@ -1,8 +1,8 @@
1
1
  require 'ostruct'
2
2
  require 'singleton'
3
3
  require 'forwardable'
4
- require 'json'
5
4
  require 'logger'
5
+ autoload :JSON, 'json'
6
6
 
7
7
  module Kontena
8
8
  module Cli
@@ -13,10 +13,23 @@ module Kontena
13
13
  class Config < OpenStruct
14
14
  include Singleton
15
15
 
16
+ module Fields
17
+ def keys
18
+ @table.keys
19
+ end
20
+
21
+ def values_at(*fields)
22
+ (fields.first.is_a?(Array) ? fields.first : fields).map { |field| self[field] }
23
+ end
24
+ end
25
+
26
+ include Fields
27
+
16
28
  attr_accessor :logger
17
29
  attr_accessor :current_server
18
30
  attr_reader :current_account
19
31
 
32
+
20
33
  def self.reset_instance
21
34
  Singleton.send :__init__, self
22
35
  self
@@ -26,20 +39,22 @@ module Kontena
26
39
 
27
40
  def initialize
28
41
  super
29
- @logger = Logger.new(ENV["DEBUG"] ? $stderr : $stdout)
30
- @logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
31
- @logger.progname = 'CONFIG'
42
+ @logger = Kontena.logger
32
43
  load_settings_from_env || load_settings_from_config_file
33
44
 
34
- logger.debug "Configuration loaded with #{servers.count} servers."
35
- logger.debug "Current master: #{current_server || '(not selected)'}"
36
- logger.debug "Current grid: #{current_grid || '(not selected)'}"
45
+ debug { "Configuration loaded with #{servers.count} servers." }
46
+ debug { "Current master: #{current_server || '(not selected)'}" }
47
+ debug { "Current grid: #{current_grid || '(not selected)'}" }
48
+ end
49
+
50
+ def debug(&block)
51
+ Kontena.logger.add(Logger::DEBUG, nil, 'CONFIG', &block)
37
52
  end
38
53
 
39
54
  # Craft a regular looking configuration based on ENV variables
40
55
  def load_settings_from_env
41
56
  return nil unless ENV['KONTENA_URL']
42
- logger.debug 'Loading configuration from ENV'
57
+ debug { 'Loading configuration from ENV' }
43
58
  servers << Server.new(
44
59
  url: ENV['KONTENA_URL'],
45
60
  name: 'default',
@@ -48,11 +63,9 @@ module Kontena
48
63
  parent_type: :master,
49
64
  parent_name: 'default'
50
65
  )
51
- accounts << Account.new(
52
- url: ENV['AUTH_API_URL'] || 'https://auth.kontena.io',
53
- name: 'kontena',
54
- token: Token.new(access_token: ENV['KONTENA_ACCOUNT_TOKEN'], parent_type: :account, parent_name: 'default')
55
- )
66
+ accounts << Account.new(kontena_account_data.merge(
67
+ token: Token.new(access_token: ENV['KONTENA_CLOUD_TOKEN'], parent_type: :account, parent_name: 'default')
68
+ ))
56
69
 
57
70
  self.current_master = 'default'
58
71
  self.current_account = 'kontena'
@@ -84,7 +97,7 @@ module Kontena
84
97
  if servers.find { |s| s['name'] == server.name}
85
98
  server.name = "#{server.name}-2"
86
99
  server.name.succ! until servers.find { |s| s['name'] == server.name }.nil?
87
- logger.debug "Renamed server to #{server.name} because a duplicate was found in config"
100
+ debug { "Renamed server to #{server.name} because a duplicate was found in config" }
88
101
  end
89
102
  servers << server
90
103
  end
@@ -115,22 +128,23 @@ module Kontena
115
128
  accounts.delete_at(master_index) if master_index
116
129
  accounts << Account.new(master_account_data)
117
130
 
118
- self.current_account = settings['current_account'] || 'kontena'
131
+ self.current_account = ENV['KONTENA_CLOUD'] || settings['current_account'] || 'kontena'
119
132
  end
120
133
 
121
134
  def kontena_account_data
122
135
  {
123
136
  name: 'kontena',
124
- url: 'https://cloud-api.kontena.io',
125
- stacks_url: 'https://stacks.kontena.io',
126
- token_endpoint: 'https://cloud-api.kontena.io/oauth2/token',
127
- authorization_endpoint: 'https://cloud.kontena.io/login/oauth/authorize',
128
- userinfo_endpoint: 'https://cloud-api.kontena.io/user',
129
- token_post_content_type: 'application/x-www-form-urlencoded',
130
- code_requires_basic_auth: false,
131
- token_method: 'post',
132
- scope: 'user',
133
- client_id: nil
137
+ url: ENV['KONTENA_CLOUD_URL'] || 'https://cloud-api.kontena.io',
138
+ stacks_url: ENV['KONTENA_STACK_REGISTRY_URL'] || 'https://stacks.kontena.io',
139
+ token_endpoint: ENV['AUTH_TOKEN_ENDPOINT'] || 'https://cloud-api.kontena.io/oauth2/token',
140
+ authorization_endpoint: ENV['AUTH_AUTHORIZE_ENDPOINT'] || 'https://cloud.kontena.io/login/oauth/authorize',
141
+ userinfo_endpoint: ENV['AUTH_USERINFO_ENDPOINT'] || 'https://cloud-api.kontena.io/user',
142
+ token_post_content_type: ENV['AUTH_TOKEN_POST_CONTENT_TYPE'] || 'application/x-www-form-urlencoded',
143
+ code_requires_basic_auth: ENV['AUTH_CODE_REQUIRES_BASIC_AUTH'].to_s == true,
144
+ token_method: ENV['AUTH_TOKEN_METHOD'] || 'post',
145
+ scope: ENV['AUTH_USERINFO_SCOPE'] || 'user',
146
+ client_id: nil,
147
+ stacks_read_authentication: ENV['KONTENA_STACK_REGISTRY_READ_AUTHENTICATION'].to_s == 'true'
134
148
  }
135
149
  end
136
150
 
@@ -157,7 +171,7 @@ module Kontena
157
171
  #
158
172
  # @return [Hash]
159
173
  def default_settings
160
- logger.debug 'Configuration file not found, using default settings.'
174
+ debug { 'Configuration file not found, using default settings.' }
161
175
  {
162
176
  'current_server' => 'default',
163
177
  'servers' => []
@@ -169,7 +183,7 @@ module Kontena
169
183
  # @param [Hash] settings_hash
170
184
  # @return [Hash] migrated_settings_hash
171
185
  def migrate_legacy_settings(settings)
172
- logger.debug "Migrating from legacy style configuration"
186
+ debug { "Migrating from legacy style configuration" }
173
187
  {
174
188
  'current_server' => 'default',
175
189
  'servers' => [
@@ -186,7 +200,7 @@ module Kontena
186
200
  #
187
201
  # @return [Hash] config_data
188
202
  def parse_config_file
189
- logger.debug "Loading configuration from #{config_filename}"
203
+ debug { "Loading configuration from #{config_filename}" }
190
204
  settings = JSON.load(File.read(config_filename))
191
205
  if settings.has_key?('server')
192
206
  settings = migrate_legacy_settings(settings)
@@ -437,7 +451,7 @@ module Kontena
437
451
  # Does nothing if using settings from environment variables.
438
452
  def write
439
453
  return nil if ENV['KONTENA_URL']
440
- logger.debug "Writing configuration to #{config_filename}"
454
+ debug { "Writing configuration to #{config_filename}" }
441
455
  File.write(config_filename, to_json)
442
456
  end
443
457
 
@@ -468,6 +482,7 @@ module Kontena
468
482
  end
469
483
 
470
484
  class Account < OpenStruct
485
+ include Fields
471
486
  include TokenSerializer
472
487
  include ConfigurationInstance
473
488
 
@@ -484,6 +499,7 @@ module Kontena
484
499
  end
485
500
 
486
501
  class Server < OpenStruct
502
+ include Fields
487
503
  include TokenSerializer
488
504
  include ConfigurationInstance
489
505
 
@@ -494,6 +510,7 @@ module Kontena
494
510
  end
495
511
 
496
512
  class Token < OpenStruct
513
+ include Fields
497
514
  include ConfigurationInstance
498
515
 
499
516
  # Hash representation of token data
@@ -3,56 +3,45 @@ module Kontena::Cli::Containers
3
3
  include Kontena::Util
4
4
  include Kontena::Cli::Common
5
5
  include Kontena::Cli::GridOptions
6
+ include Kontena::Cli::TableGenerator::Helper
6
7
 
7
- option ['--all', '-a'], :flag, 'Show all containers'
8
+ option ['-a', '--all'], :flag, 'Show all containers'
9
+
10
+ requires_current_master
11
+ requires_current_master_token
12
+
13
+ NON_STOP_STATES = ['paused', 'restarting', 'oom_killed', 'dead', 'running']
14
+
15
+ def fields
16
+ return ['id'] if quiet?
17
+ { container_id: 'id', image: 'image', command: 'cmd', created: 'created_at', status: 'state' }
18
+ end
8
19
 
9
20
  def execute
10
- require_api_url
11
- token = require_token
12
-
13
- params = '?'
14
- params << 'all=1' if all?
15
- result = client(token).get("containers/#{current_grid}#{params}")
16
- containers = result['containers']
17
- id_column = longest_string_in_array(containers.map {|c| "#{c['node']['name']}/#{c['name']}"})
18
- image_column = longest_string_in_array(containers.map {|c| c['image'] })
19
- columns = "%-#{id_column + 2}s %-#{image_column + 2}s %-30s %-20s %-10s"
20
- puts columns % [ 'CONTAINER ID', 'IMAGE', 'COMMAND', 'CREATED', 'STATUS']
21
- result['containers'].reverse.each do |container|
22
- puts columns % [
23
- "#{container['node']['name']}/#{container['name']}",
24
- container['image'],
25
- "\"#{container['cmd'].to_a.join(' ')[0..26]}\"",
26
- "#{time_ago(container['created_at'])} ago",
27
- container_status(container)
28
- ]
21
+ result = spin_if(!quiet?, "Retrieving container list") do
22
+ Array(client.get("containers/#{current_grid}#{'?all=1' if all?}")['containers'])
29
23
  end
30
- end
31
24
 
32
- def longest_string_in_array(array)
33
- longest = 0
34
- array.each do |item|
35
- longest = item.length if item.length > longest
25
+ print_table(result.reverse) do |row|
26
+ row['id'] = container_id(row)
27
+ row['created_at'] = time_ago(row['created_at'])
28
+ row['cmd'] = truncate_cmd(row)
29
+ row['state'] = container_state(row)
36
30
  end
31
+ end
37
32
 
38
- longest
33
+ def container_id(row)
34
+ "#{row['node']['name']}/#{row['name']}"
39
35
  end
40
36
 
41
- def container_status(container)
42
- s = container['state']
43
- if s['paused']
44
- 'paused'.freeze
45
- elsif s['restarting']
46
- 'restarting'.freeze
47
- elsif s['oom_killed']
48
- 'oom_killed'.freeze
49
- elsif s['dead']
50
- 'dead'.freeze
51
- elsif s['running']
52
- 'running'.freeze
53
- else
54
- 'stopped'.freeze
55
- end
37
+ def truncate_cmd(row)
38
+ cmd = row['cmd'].nil? ? '' : row['cmd'].join(' ')
39
+ cmd = "#{cmd[0..24]}#{pastel.cyan('..')}" if cmd.length > 26
40
+ "\"#{cmd}\""
41
+ end
42
+
43
+ def container_state(row)
44
+ NON_STOP_STATES.find { |state| row.fetch('state', {})[state] == true } || pastel.cyan('stopped')
56
45
  end
57
46
  end
58
47
  end