kontena-cli 1.3.0.pre1 → 1.3.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
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,14 +1,15 @@
1
1
  require 'clamp'
2
2
  require 'kontena/cli/subcommand_loader'
3
- require 'kontena/cli/common'
4
3
  require 'kontena/util'
5
4
  require 'kontena/cli/bytes_helper'
6
5
  require 'kontena/cli/grid_options'
6
+ require 'excon/errors'
7
7
 
8
8
  class Kontena::Command < Clamp::Command
9
9
 
10
10
  option ['-D', '--debug'], :flag, "Enable debug", environment_variable: 'DEBUG' do
11
11
  ENV['DEBUG'] ||= 'true'
12
+ Kontena.reset_logger
12
13
  end
13
14
 
14
15
  attr_accessor :arguments
@@ -182,7 +183,7 @@ class Kontena::Command < Clamp::Command
182
183
  end
183
184
 
184
185
  def run(arguments)
185
- ENV["DEBUG"] && $stderr.puts("Running #{self} -- callback matcher = '#{self.class.callback_matcher.nil? ? "nil" : self.class.callback_matcher.map(&:to_s).join(' ')}'")
186
+ Kontena.logger.debug { "Running #{self.class.name} with #{arguments.inspect} -- callback matcher = '#{self.class.callback_matcher.nil? ? "nil" : self.class.callback_matcher.map(&:to_s).join(' ')}'" }
186
187
  @arguments = arguments
187
188
 
188
189
  run_callbacks :before_parse unless help_requested?
@@ -218,7 +219,8 @@ class Kontena::Command < Clamp::Command
218
219
  end
219
220
  rescue Kontena::Errors::StandardError => ex
220
221
  raise ex if ENV['DEBUG']
221
- abort(" [#{Kontena.pastel.red('error')}] #{ex.class.name} : #{ex.message}")
222
+ Kontena.logger.error(ex)
223
+ abort(" [#{Kontena.pastel.red('error')}] #{ex.status} : #{ex.message}")
222
224
  rescue Errno::EPIPE
223
225
  # If user is piping the command outputs to some other command that might exit before CLI has outputted everything
224
226
  abort
@@ -226,7 +228,8 @@ class Kontena::Command < Clamp::Command
226
228
  raise
227
229
  rescue => ex
228
230
  raise ex if ENV['DEBUG']
229
- abort(" [#{Kontena.pastel.red('error')}] #{ex.class.name} : #{ex.message}\n Rerun the command with environment DEBUG=true set to get the full exception")
231
+ Kontena.logger.error(ex)
232
+ abort(" [#{Kontena.pastel.red('error')}] #{ex.class.name} : #{ex.message}\n See #{Kontena.log_target} or run the command again with environment DEBUG=true set to see the full exception")
230
233
  end
231
234
  end
232
235
 
@@ -22,6 +22,7 @@ module Kontena
22
22
  heads << "Accept: #{params[:headers]['Accept']}" if params[:headers]['Accept']
23
23
  heads << "Content-Type: #{params[:headers]['Content-Type']}" if params[:headers]['Content-Type']
24
24
  heads << "Authorization: #{params[:headers]['Authorization'].split(' ', 2).first}" if params[:headers]['Authorization']
25
+ heads << "X-Kontena-Version: #{params[:headers]['X-Kontena-Version']}" if params[:headers]['X-Kontena-Version']
25
26
  str << heads.join(', ')
26
27
  str << "} "
27
28
  result << str
@@ -50,17 +51,17 @@ module Kontena
50
51
  end
51
52
  end
52
53
  result << str
54
+ elsif params[:error]
55
+ result << params[:error]
53
56
  end
54
57
 
55
- if $stderr.tty?
56
- if direction == 'Request'
57
- $stderr.puts(Kontena.pastel.blue("[API Client #{direction}]: #{result.join(" | ")}"))
58
- else
59
- $stderr.puts(Kontena.pastel.magenta("[API Client #{direction}]: #{result.join(" | ")}"))
60
- end
61
- else
62
- $stderr.puts("[API Client #{direction}]: #{result.join(" | ")}")
63
- end
58
+ color = case direction
59
+ when 'Request' then :blue
60
+ when 'Response' then :magenta
61
+ else :red
62
+ end
63
+
64
+ Kontena.logger.debug("CLIENT") { Kontena.pastel.send(color, "[#{direction}]: #{result.join(" | ")}") }
64
65
 
65
66
  if block_given?
66
67
  yield
@@ -1,9 +1,6 @@
1
1
  require 'kontena/command'
2
2
 
3
3
  class Kontena::MainCommand < Kontena::Command
4
- include Kontena::Util
5
- include Kontena::Cli::Common
6
-
7
4
  option ['-v', '--version'], :flag, "Output Kontena CLI version #{Kontena::Cli::VERSION}" do
8
5
  build_tags = [ 'ruby' + RUBY_VERSION ]
9
6
  build_tags << RUBY_PLATFORM
@@ -44,6 +41,7 @@ class Kontena::MainCommand < Kontena::Command
44
41
 
45
42
  def subcommand_missing(name)
46
43
  if known_plugin_subcommand?(name)
44
+ extend Kontena::Cli::Common
47
45
  exit_with_error "The '#{name}' plugin has not been installed. Use: kontena plugin install #{name}"
48
46
  else
49
47
  super(name)
@@ -159,6 +159,10 @@ module Kontena
159
159
  SafeYAML::OPTIONS[:default_mode] = :safe if Object.const_defined?(:SafeYAML)
160
160
  end
161
161
 
162
+ def plugin_debug?
163
+ @plugin_debug ||= ENV['DEBUG'] == 'plugin'
164
+ end
165
+
162
166
  def load_plugins
163
167
  plugins = []
164
168
  Gem::Specification.to_a.each do |spec|
@@ -167,21 +171,25 @@ module Kontena
167
171
  if File.exist?(plugin) && !plugins.find{ |p| p.name == spec.name }
168
172
  begin
169
173
  if spec_has_valid_dependency?(spec)
174
+
170
175
  loaded_features_before = $LOADED_FEATURES.dup
171
176
  load_path_before = $LOAD_PATH.dup
172
177
 
173
- ENV["DEBUG"] && $stderr.puts("Activating plugin #{spec.name}")
178
+ Kontena.logger.debug { "Activating plugin #{spec.name}" } if plugin_debug?
174
179
  spec.activate
175
180
  spec.activate_dependencies
176
181
 
177
- ENV["DEBUG"] && $stderr.puts("Loading plugin #{spec.name}")
182
+ Kontena.logger.debug { "Loading plugin #{spec.name}" }
178
183
  require(plugin)
184
+ Kontena.logger.debug { "Loaded plugin #{spec.name}" } if plugin_debug?
179
185
 
180
- if ENV['DEBUG'] == 'plugin'
186
+ if plugin_debug?
181
187
  added_features = ($LOADED_FEATURES - loaded_features_before).map {|feat| "- #{feat}"}
182
188
  added_paths = ($LOAD_PATH - load_path_before).map {|feat| "- #{feat}"}
183
- $stderr.puts "Plugin manager loaded features for #{spec.name}: \n#{added_features.join("\n")}" unless added_features.empty?
184
- $stderr.puts "Plugin manager load paths added for #{spec.name}: \n#{added_paths.join("\n")}" unless added_paths.empty?
189
+ Kontena.logger.debug { "Plugin manager loaded features for #{spec.name}:" } unless added_features.empty?
190
+ added_features.each { |feat| Kontena.logger.debug { feat } }
191
+ Kontena.logger.debug { "Plugin manager load paths added for #{spec.name}:" } unless added_paths.empty?
192
+ added_paths.each { |path| Kontena.logger.debug { path } }
185
193
  end
186
194
 
187
195
  plugins << spec
@@ -192,7 +200,7 @@ module Kontena
192
200
  end
193
201
  rescue ScriptError, StandardError => ex
194
202
  warn " [#{Kontena.pastel.red('error')}] Failed to load plugin: #{spec.name}\n\tRerun the command with environment DEBUG=true set to get the full exception."
195
- ENV['DEBUG'] && $stderr.puts("#{ex.class.name} : #{ex.message}\n#{ex.backtrace.join("\n ")}")
203
+ Kontena.logger.error(ex)
196
204
  end
197
205
  end
198
206
  end
@@ -200,7 +208,7 @@ module Kontena
200
208
  plugins
201
209
  rescue => ex
202
210
  $stderr.puts Kontena.pastel.red(ex.message)
203
- ENV['DEBUG'] && $stderr.puts("#{ex.class.name} : #{ex.message}\n#{ex.backtrace.join("\n ")}")
211
+ Kontena.logger.error(ex)
204
212
  end
205
213
 
206
214
  def prefix(plugin_name)
@@ -1,10 +1,6 @@
1
- require_relative 'stacks_client'
2
- require_relative 'cli/common'
3
- require_relative 'cli/stacks/common'
4
- require 'yaml'
5
- require 'uri'
6
-
7
1
  module Kontena
2
+ autoload :StacksClient, 'kontena/stacks_client'
3
+
8
4
  class StacksCache
9
5
  class CachedStack
10
6
 
@@ -12,6 +8,8 @@ module Kontena
12
8
  attr_accessor :version
13
9
 
14
10
  def initialize(stack, version = nil)
11
+ require "safe_yaml"
12
+ SafeYAML::OPTIONS[:default_mode] = :safe
15
13
  unless version
16
14
  stack, version = stack.split(':', 2)
17
15
  end
@@ -59,6 +57,8 @@ module Kontena
59
57
  end
60
58
 
61
59
  class RegistryClientFactory
60
+ require 'kontena/cli/common'
61
+ require 'kontena/cli/stacks/common'
62
62
  include Kontena::Cli::Common
63
63
  include Kontena::Cli::Stacks::Common
64
64
  end
@@ -69,7 +69,7 @@ module Kontena
69
69
  end
70
70
 
71
71
  def dputs(msg)
72
- ENV["DEBUG"] && $stderr.puts(msg)
72
+ Kontena.logger.debug { msg }
73
73
  end
74
74
 
75
75
  def cache(stack, version = nil)
@@ -7,6 +7,19 @@ module Kontena
7
7
  ACCEPT_YAML = { 'Accept' => 'application/yaml' }
8
8
  CT_YAML = { 'Content-Type' => 'application/yaml' }
9
9
 
10
+ def raise_unless_token
11
+ unless token && token['access_token']
12
+ raise Kontena::Errors::StandardError.new(401, "Stack registry write operations require authentication")
13
+ end
14
+ end
15
+
16
+ def raise_unless_read_token
17
+ return false unless options[:read_requires_token]
18
+ unless token && token['access_token']
19
+ raise Kontena::Errors::StandardError.new(401, "Stack registry requires authentication")
20
+ end
21
+ end
22
+
10
23
  def full_uri(stack_name, version = nil)
11
24
  URI.join(api_url, path_to(stack_name, version)).to_s
12
25
  end
@@ -16,29 +29,35 @@ module Kontena
16
29
  end
17
30
 
18
31
  def push(stack_name, version, data)
19
- post('/stack/', data, {}, CT_YAML)
32
+ raise_unless_token
33
+ post('/stack/', data, {}, CT_YAML, true)
20
34
  end
21
35
 
22
36
  def show(stack_name, stack_version = nil)
23
- get("#{path_to(stack_name, stack_version)}", {}, ACCEPT_JSON)
37
+ raise_unless_read_token
38
+ get("#{path_to(stack_name, stack_version)}", nil, ACCEPT_JSON, options[:read_requires_token])
24
39
  end
25
40
 
26
41
  def versions(stack_name)
27
- get("#{path_to(stack_name, nil)}/versions", {}, ACCEPT_JSON)['versions']
42
+ raise_unless_read_token
43
+ get("#{path_to(stack_name, nil)}/versions", nil, ACCEPT_JSON, options[:read_requires_token])['versions']
28
44
  end
29
45
 
30
46
  def pull(stack_name, version = nil)
31
- get(path_to(stack_name, version), {}, ACCEPT_YAML)
47
+ raise_unless_read_token
48
+ get(path_to(stack_name, version), nil, ACCEPT_YAML, options[:read_requires_token])
32
49
  rescue StandardError => ex
33
50
  ex.message << " : #{path_to(stack_name, version)}"
34
51
  raise ex, ex.message
35
52
  end
36
53
 
37
54
  def search(query)
38
- get('/search', { q: query }, {}, ACCEPT_JSON)['stacks']
55
+ raise_unless_read_token
56
+ get('/search', { q: query }, ACCEPT_JSON, options[:read_requires_token])['stacks']
39
57
  end
40
58
 
41
59
  def destroy(stack_name, version = nil)
60
+ raise_unless_token
42
61
  delete(path_to(stack_name, version), {})
43
62
  end
44
63
  end
data/lib/kontena/util.rb CHANGED
@@ -1,9 +1,33 @@
1
1
  module Kontena
2
2
  module Util
3
3
  def self.included(base)
4
- base.extend(ClassMethods)
4
+ base.extend(ClassMethods)
5
5
  end
6
6
 
7
+ def symbolize_keys(obj)
8
+ case obj
9
+ when Hash
10
+ obj.map { |k,v| [k.to_sym, symbolize_keys(v)] }.to_h
11
+ when Array
12
+ obj.map { |v| symbolize_keys(v) }
13
+ else
14
+ obj
15
+ end
16
+ end
17
+ module_function :symbolize_keys
18
+
19
+ def symbolize_keys!(obj)
20
+ case obj
21
+ when Hash
22
+ obj.keys.each { |k| obj[k.to_sym] = symbolize_keys!(obj.delete(k)) }
23
+ when Array
24
+ obj.map! { |v| symbolize_keys!(v) }
25
+ else
26
+ end
27
+ obj
28
+ end
29
+ module_function :symbolize_keys!
30
+
7
31
  # @param [String] cmd
8
32
  def which(cmd)
9
33
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
@@ -30,26 +54,30 @@ module Kontena
30
54
 
31
55
  def time_ago(time)
32
56
  now = Time.now.to_i
33
- time = DateTime.parse(time).to_time.to_i
57
+ time = time.kind_of?(Integer) ? time : DateTime.parse(time).to_time.to_i
34
58
  diff = now - time
35
- if diff > 60 * 60 * 24
36
- "#{diff / 60 / 60 / 24} days"
37
- elsif diff > 60 * 60
38
- "#{diff / 60 / 60} hours"
39
- elsif diff > 60
40
- "#{diff / 60} minutes"
59
+ seconds_to_human(diff) + ' ago'
60
+ end
61
+
62
+ def time_until(seconds)
63
+ 'in ' + seconds_to_human(seconds)
64
+ end
65
+
66
+ def seconds_to_human(seconds)
67
+ if seconds > 60 * 60 * 24
68
+ result = "#{seconds / 60 / 60 / 24} days"
69
+ elsif seconds > 60 * 60
70
+ result = "#{seconds / 60 / 60} hours"
71
+ elsif seconds > 60
72
+ result = "#{seconds / 60} minutes"
41
73
  else
42
- "#{diff} seconds"
74
+ result = "#{seconds} seconds"
43
75
  end
76
+ result.start_with?('1 ') ? result[0..-2] : result
44
77
  end
45
78
 
46
79
  def longest_string_in_array(array)
47
- longest = 0
48
- array.each do |item|
49
- longest = item.length if item.length > longest
50
- end
51
-
52
- longest
80
+ array.max_by(&:length).length
53
81
  end
54
82
 
55
83
  module_function(:which)
data/lib/kontena_cli.rb CHANGED
@@ -1,4 +1,26 @@
1
+ require 'logger'
2
+
3
+ $KONTENA_START_TIME = Time.now.to_f
4
+ at_exit do
5
+ Kontena.logger.debug { "Execution took #{(Time.now.to_f - $KONTENA_START_TIME).round(3)} seconds" }
6
+ Kontena.logger.debug { "#{$!.class.name}" + ($!.respond_to?(:status) ? " status #{$!.status}" : "") } if $!
7
+ end
8
+
1
9
  module Kontena
10
+ module Cli
11
+ autoload :Config, 'kontena/cli/config'
12
+ autoload :Spinner, 'kontena/cli/spinner'
13
+ autoload :Common, 'kontena/cli/common'
14
+ autoload :TableGenerator, 'kontena/cli/table_generator'
15
+ end
16
+
17
+ autoload :Command, 'kontena/command'
18
+ autoload :Client, 'kontena/client'
19
+ autoload :StacksCache, 'kontena/stacks_cache'
20
+ autoload :PluginManager, 'kontena/plugin_manager'
21
+ autoload :MainCommand, 'kontena/main_command'
22
+ autoload :Errors, 'kontena/errors'
23
+
2
24
  # Run a kontena command like it was launched from the command line. Re-raises any exceptions,
3
25
  # except a SystemExit with status 0, which is considered a success.
4
26
  #
@@ -12,16 +34,17 @@ module Kontena
12
34
  else
13
35
  command = cmdline
14
36
  end
15
- ENV["DEBUG"] && puts("Running Kontena.run(#{command.inspect}")
37
+ logger.debug { "Running Kontena.run(#{command.inspect}" }
16
38
  result = Kontena::MainCommand.new(File.basename(__FILE__)).run(command)
17
- ENV["DEBUG"] && puts("Command completed, result: #{result.inspect} status: 0")
39
+ logger.debug { "Command completed, result: #{result.inspect} status: 0" }
18
40
  result
19
41
  rescue SystemExit => ex
20
- ENV["DEBUG"] && $stderr.puts("Command caused SystemExit, result: #{result.inspect} status: #{ex.status}")
42
+ logger.debug { "Command caused SystemExit, status: #{ex.status}" }
21
43
  return true if ex.status.zero?
22
44
  raise ex
23
45
  rescue => ex
24
- ENV["DEBUG"] && $stderr.puts("Command raised #{ex.class.name} with message: #{ex.message}\n#{ex.backtrace.join("\n ")}")
46
+ logger.error { "Command #{cmdline.inspect} exception" }
47
+ logger.error { ex }
25
48
  raise ex
26
49
  end
27
50
 
@@ -37,6 +60,29 @@ module Kontena
37
60
  false
38
61
  end
39
62
 
63
+ def self.log_target
64
+ return @log_target if @log_target
65
+
66
+ @log_target = ENV['LOG_TARGET']
67
+
68
+ if ENV["DEBUG"]
69
+ @log_target ||= $stderr
70
+ elsif @log_target.nil?
71
+ @log_target = File.join(home, 'kontena.log')
72
+ end
73
+ end
74
+
75
+ def self.reset_logger
76
+ @log_target, @logger = nil
77
+ end
78
+
79
+ def self.home
80
+ return @home if @home
81
+ @home = File.join(Dir.home, '.kontena')
82
+ Dir.mkdir(@home, 0700) unless File.directory?(@home)
83
+ @home
84
+ end
85
+
40
86
  # @return [String] x.y
41
87
  def self.minor_version
42
88
  Kontena::Cli::VERSION.split('.')[0..1].join('.')
@@ -59,7 +105,9 @@ module Kontena
59
105
  end
60
106
 
61
107
  def self.pastel
62
- @pastel ||= Pastel.new(enabled: !simple_terminal?)
108
+ return @pastel if @pastel
109
+ require 'pastel'
110
+ @pastel = Pastel.new(enabled: !simple_terminal?)
63
111
  end
64
112
 
65
113
  def self.prompt
@@ -96,6 +144,23 @@ module Kontena
96
144
  File.join(Kontena.root, 'lib/kontena/cli', *joinables)
97
145
  end
98
146
  end
147
+
148
+ def self.logger
149
+ return @logger if @logger
150
+ if log_target.respond_to?(:tty?) && log_target.tty?
151
+ logger = Logger.new(log_target)
152
+ require 'kontena/cli/log_formatters/compact'
153
+ logger.formatter = Kontena::Cli::LogFormatter::Compact.new
154
+ else
155
+ logger = Logger.new(log_target, 1, 1_048_576)
156
+ require 'kontena/cli/log_formatters/strip_color'
157
+ logger.formatter = Kontena::Cli::LogFormatter::StripColor.new
158
+ end
159
+ logger.level = ENV["DEBUG"] ? Logger::DEBUG : Logger::INFO
160
+ logger.progname = 'CLI'
161
+ @logger = logger
162
+ end
163
+
99
164
  end
100
165
 
101
166
  # Monkeypatching string to mimick 'colorize' gem
@@ -115,13 +180,5 @@ end
115
180
 
116
181
  require 'ruby_dig'
117
182
  require 'shellwords'
118
- require "safe_yaml"
119
- SafeYAML::OPTIONS[:default_mode] = :safe
120
183
  require 'kontena/cli/version'
121
- require 'kontena/cli/common'
122
- require 'kontena/command'
123
- require 'kontena/client'
124
- require 'kontena/stacks_cache'
125
- require 'kontena/plugin_manager'
126
- require 'kontena/main_command'
127
- require 'kontena/cli/spinner'
184
+ Kontena.logger.debug { "Kontena CLI #{Kontena::Cli::VERSION} (ruby-#{RUBY_VERSION}+#{RUBY_PLATFORM})" }