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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/VERSION +1 -1
- data/bin/kontena +4 -1
- data/kontena-cli.gemspec +1 -1
- data/lib/kontena/callback.rb +1 -1
- data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +1 -1
- data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +5 -5
- data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +1 -1
- data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +25 -0
- data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +1 -1
- data/lib/kontena/cli/common.rb +3 -3
- data/lib/kontena/cli/config.rb +1 -1
- data/lib/kontena/cli/grid_command.rb +2 -0
- data/lib/kontena/cli/grids/common.rb +12 -0
- data/lib/kontena/cli/grids/health_command.rb +69 -0
- data/lib/kontena/cli/helpers/health_helper.rb +53 -0
- data/lib/kontena/cli/localhost_web_server.rb +3 -3
- data/lib/kontena/cli/master/users/invite_command.rb +1 -1
- data/lib/kontena/cli/node_command.rb +2 -0
- data/lib/kontena/cli/nodes/health_command.rb +32 -0
- data/lib/kontena/cli/nodes/list_command.rb +40 -26
- data/lib/kontena/cli/nodes/show_command.rb +0 -1
- data/lib/kontena/cli/plugins/install_command.rb +28 -30
- data/lib/kontena/cli/plugins/search_command.rb +6 -14
- data/lib/kontena/cli/plugins/uninstall_command.rb +7 -11
- data/lib/kontena/cli/services/stats_command.rb +4 -2
- data/lib/kontena/cli/spinner.rb +20 -4
- data/lib/kontena/cli/stacks/show_command.rb +5 -1
- data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +1 -1
- data/lib/kontena/cli/stacks/yaml/reader.rb +1 -0
- data/lib/kontena/cli/vault/export_command.rb +22 -0
- data/lib/kontena/cli/vault/import_command.rb +80 -0
- data/lib/kontena/cli/vault/list_command.rb +4 -0
- data/lib/kontena/cli/vault/read_command.rb +8 -3
- data/lib/kontena/cli/vault/remove_command.rb +2 -1
- data/lib/kontena/cli/vault/update_command.rb +5 -7
- data/lib/kontena/cli/vault_command.rb +5 -1
- data/lib/kontena/client.rb +25 -2
- data/lib/kontena/command.rb +1 -1
- data/lib/kontena/debug_instrumentor.rb +70 -0
- data/lib/kontena/light_prompt.rb +103 -0
- data/lib/kontena/plugin_manager.rb +167 -6
- data/lib/kontena/stacks_cache.rb +1 -1
- data/lib/kontena_cli.rb +23 -6
- data/spec/kontena/cli/grids/health_command_spec.rb +390 -0
- data/spec/kontena/cli/nodes/health_command_spec.rb +206 -0
- data/spec/kontena/cli/nodes/list_command_spec.rb +205 -0
- data/spec/kontena/cli/vault/export_spec.rb +32 -0
- data/spec/kontena/cli/vault/import_spec.rb +69 -0
- data/spec/kontena/client_spec.rb +39 -0
- data/spec/kontena/plugin_manager_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/support/output_helpers.rb +51 -0
- metadata +27 -6
@@ -1,8 +1,10 @@
|
|
1
|
-
require_relative 'vault/
|
1
|
+
require_relative 'vault/export_command'
|
2
|
+
require_relative 'vault/import_command'
|
2
3
|
require_relative 'vault/list_command'
|
3
4
|
require_relative 'vault/read_command'
|
4
5
|
require_relative 'vault/remove_command'
|
5
6
|
require_relative 'vault/update_command'
|
7
|
+
require_relative 'vault/write_command'
|
6
8
|
|
7
9
|
class Kontena::Cli::VaultCommand < Kontena::Command
|
8
10
|
|
@@ -11,6 +13,8 @@ class Kontena::Cli::VaultCommand < Kontena::Command
|
|
11
13
|
subcommand "read", "Read secret", Kontena::Cli::Vault::ReadCommand
|
12
14
|
subcommand "update", "Update secret", Kontena::Cli::Vault::UpdateCommand
|
13
15
|
subcommand ["remove", "rm"], "Remove secret", Kontena::Cli::Vault::RemoveCommand
|
16
|
+
subcommand "export", "Export secrets to STDOUT", Kontena::Cli::Vault::ExportCommand
|
17
|
+
subcommand "import", "Import secrets from a file or STDIN", Kontena::Cli::Vault::ImportCommand
|
14
18
|
|
15
19
|
def execute
|
16
20
|
end
|
data/lib/kontena/client.rb
CHANGED
@@ -23,6 +23,7 @@ module Kontena
|
|
23
23
|
CONTENT_JSON = 'application/json'.freeze
|
24
24
|
JSON_REGEX = /application\/(.+?\+)?json/.freeze
|
25
25
|
CONTENT_TYPE = 'Content-Type'.freeze
|
26
|
+
X_KONTENA_VERSION = 'X-Kontena-Version'.freeze
|
26
27
|
ACCEPT = 'Accept'.freeze
|
27
28
|
AUTHORIZATION = 'Authorization'.freeze
|
28
29
|
|
@@ -46,7 +47,7 @@ module Kontena
|
|
46
47
|
uri = URI.parse(@api_url)
|
47
48
|
@host = uri.host
|
48
49
|
|
49
|
-
@logger = Logger.new(STDOUT)
|
50
|
+
@logger = Logger.new(ENV["DEBUG"] ? STDERR : STDOUT)
|
50
51
|
@logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
|
51
52
|
@logger.progname = 'CLIENT'
|
52
53
|
|
@@ -59,6 +60,10 @@ module Kontena
|
|
59
60
|
write_timeout: ENV["EXCON_WRITE_TIMEOUT"] ? ENV["EXCON_WRITE_TIMEOUT"].to_i : 5,
|
60
61
|
ssl_verify_peer: ignore_ssl_errors? ? false : true
|
61
62
|
}
|
63
|
+
if ENV["DEBUG"]
|
64
|
+
require_relative 'debug_instrumentor'
|
65
|
+
excon_opts[:instrumentor] = Kontena::DebugInstrumentor
|
66
|
+
end
|
62
67
|
|
63
68
|
cert_file = File.join(Dir.home, "/.kontena/certs/#{uri.host}.pem")
|
64
69
|
if File.exist?(cert_file) && File.readable?(cert_file)
|
@@ -135,7 +140,7 @@ module Kontena
|
|
135
140
|
request(path: final_path)
|
136
141
|
true
|
137
142
|
rescue
|
138
|
-
|
143
|
+
logger.debug "Authentication verification exception: #{$!} #{$!.message} #{$!.backtrace}"
|
139
144
|
false
|
140
145
|
end
|
141
146
|
|
@@ -473,6 +478,8 @@ module Kontena
|
|
473
478
|
# @param [Excon::Response]
|
474
479
|
# @return [Hash,String]
|
475
480
|
def parse_response(response)
|
481
|
+
check_version_and_warn(response.headers[X_KONTENA_VERSION])
|
482
|
+
|
476
483
|
if response.headers[CONTENT_TYPE] =~ JSON_REGEX
|
477
484
|
parse_json(response.body)
|
478
485
|
else
|
@@ -480,6 +487,22 @@ module Kontena
|
|
480
487
|
end
|
481
488
|
end
|
482
489
|
|
490
|
+
def check_version_and_warn(server_version)
|
491
|
+
return nil if $VERSION_WARNING_ADDED
|
492
|
+
return nil unless server_version.to_s =~ /^\d+\.\d+\.\d+/
|
493
|
+
|
494
|
+
unless server_version[/^(\d+\.\d+)/, 1] == Kontena::Cli::VERSION[/^(\d+\.\d+)/, 1] # Just compare x.y
|
495
|
+
add_version_warning(server_version)
|
496
|
+
$VERSION_WARNING_ADDED = true
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
def add_version_warning(server_version)
|
501
|
+
at_exit do
|
502
|
+
warn Kontena.pastel.yellow("Warning: Server version is #{server_version}. You are using CLI version #{Kontena::Cli::VERSION}.")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
483
506
|
# Parse json
|
484
507
|
#
|
485
508
|
# @param [String] json
|
data/lib/kontena/command.rb
CHANGED
@@ -169,7 +169,7 @@ class Kontena::Command < Clamp::Command
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def run(arguments)
|
172
|
-
ENV["DEBUG"] && puts("Running #{self} -- callback matcher = '#{self.class.callback_matcher.nil? ? "nil" : self.class.callback_matcher.map(&:to_s).join(' ')}'")
|
172
|
+
ENV["DEBUG"] && STDERR.puts("Running #{self} -- callback matcher = '#{self.class.callback_matcher.nil? ? "nil" : self.class.callback_matcher.map(&:to_s).join(' ')}'")
|
173
173
|
@arguments = arguments
|
174
174
|
|
175
175
|
run_callbacks :before_parse unless help_requested?
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'uri'
|
2
|
+
module Kontena
|
3
|
+
class DebugInstrumentor
|
4
|
+
def self.instrument(name, params = {}, &block)
|
5
|
+
result = []
|
6
|
+
params = params.dup
|
7
|
+
|
8
|
+
direction = name.split('.').last.capitalize
|
9
|
+
|
10
|
+
if direction == 'Request'
|
11
|
+
uri = URI.parse("#{params[:scheme]}://#{params[:host]}:#{params[:port]}")
|
12
|
+
uri.path = params[:path]
|
13
|
+
uri.query = URI.encode_www_form(params[:query]) if params[:query] && !params[:query].empty?
|
14
|
+
str = "#{params[:method].to_s.upcase} #{uri}"
|
15
|
+
str << " (ssl_verify: #{params[:ssl_verify_peer]}) " if params[:scheme] == 'https'
|
16
|
+
result << str
|
17
|
+
end
|
18
|
+
|
19
|
+
if params[:headers]
|
20
|
+
str = "Headers: {"
|
21
|
+
heads = []
|
22
|
+
heads << "Accept: #{params[:headers]['Accept']}" if params[:headers]['Accept']
|
23
|
+
heads << "Content-Type: #{params[:headers]['Content-Type']}" if params[:headers]['Content-Type']
|
24
|
+
heads << "Authorization: #{params[:headers]['Authorization'].split(' ', 2).first}" if params[:headers]['Authorization']
|
25
|
+
str << heads.join(', ')
|
26
|
+
str << "} "
|
27
|
+
result << str
|
28
|
+
end
|
29
|
+
|
30
|
+
if params[:status]
|
31
|
+
str = "Status: "
|
32
|
+
if params[:status] < 299
|
33
|
+
str << Kontena.pastel.green(params[:status])
|
34
|
+
else
|
35
|
+
str << Kontena.pastel.red(params[:status])
|
36
|
+
end
|
37
|
+
result << str
|
38
|
+
end
|
39
|
+
|
40
|
+
if params[:body] && !params[:body].empty?
|
41
|
+
str = "Body: "
|
42
|
+
if ENV["DEBUG"] == "api"
|
43
|
+
str << "\n"
|
44
|
+
str << params[:body]
|
45
|
+
else
|
46
|
+
body = params[:body].inspect.strip
|
47
|
+
str << body[0,80]
|
48
|
+
if body.length > 80
|
49
|
+
str << "...\""
|
50
|
+
end
|
51
|
+
end
|
52
|
+
result << str
|
53
|
+
end
|
54
|
+
|
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
|
64
|
+
|
65
|
+
if block_given?
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'tty-prompt'
|
2
|
+
require 'pastel'
|
3
|
+
|
4
|
+
module Kontena
|
5
|
+
class LightPrompt
|
6
|
+
|
7
|
+
attr_reader :prompt
|
8
|
+
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
class Menu
|
12
|
+
attr_reader :choices, :calls
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@choices = []
|
16
|
+
@calls = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def choice(text, label)
|
20
|
+
choices << [text, label]
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_quit_choice
|
24
|
+
choice('(done)', :done)
|
25
|
+
end
|
26
|
+
|
27
|
+
def remove_choice(value)
|
28
|
+
choices.reject! { |c| c.last == value }
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove_choices(values)
|
32
|
+
values.each { |v| remove_choice(v) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(meth, *args)
|
36
|
+
calls[meth] = args
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to_missing?(meth, privates = false)
|
40
|
+
prompt.respond_to?(meth, privates)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(options={})
|
45
|
+
@prompt = TTY::Prompt.new(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def select(*args, &block)
|
49
|
+
choice_collector = Menu.new
|
50
|
+
yield choice_collector
|
51
|
+
|
52
|
+
prompt.enum_select(*args) do |menu|
|
53
|
+
choice_collector.calls.each do |meth, args|
|
54
|
+
if menu.respond_to?(meth)
|
55
|
+
menu.send(meth, *args)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
choice_collector.choices.each do |choice|
|
59
|
+
menu.choice choice.first, choice.last
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def multi_select(*args, &block)
|
65
|
+
choice_collector = Menu.new
|
66
|
+
yield choice_collector
|
67
|
+
choice_collector.add_quit_choice
|
68
|
+
|
69
|
+
selections = []
|
70
|
+
|
71
|
+
loop do
|
72
|
+
choice_collector.remove_choices(selections)
|
73
|
+
|
74
|
+
answer = prompt.enum_select(*args) do |menu|
|
75
|
+
choice_collector.calls.each do |meth, args|
|
76
|
+
if menu.respond_to?(meth)
|
77
|
+
menu.send(meth, *args)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
choice_collector.choices.each do |choice|
|
81
|
+
menu.choice choice.first, choice.last
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
break if answer == :done
|
86
|
+
selections << answer
|
87
|
+
end
|
88
|
+
|
89
|
+
selections
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def_delegators :prompt, :ask, :yes?, :error
|
94
|
+
|
95
|
+
def method_missing(meth, *args)
|
96
|
+
prompt.send(meth, *args)
|
97
|
+
end
|
98
|
+
|
99
|
+
def respond_to_missing?(meth, privates = false)
|
100
|
+
prompt.respond_to?(meth, privates)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -2,27 +2,174 @@ require 'singleton'
|
|
2
2
|
|
3
3
|
module Kontena
|
4
4
|
class PluginManager
|
5
|
+
|
5
6
|
include Singleton
|
6
7
|
|
7
8
|
CLI_GEM = 'kontena-cli'.freeze
|
8
9
|
MIN_CLI_VERSION = '0.15.99'.freeze
|
9
10
|
|
10
|
-
|
11
|
+
# Initialize plugin manager
|
12
|
+
def init
|
13
|
+
ENV["GEM_HOME"] = install_dir
|
14
|
+
Gem.paths = ENV
|
15
|
+
plugins
|
16
|
+
use_dummy_ui unless ENV["DEBUG"]
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
# Install a plugin
|
21
|
+
# @param plugin_name [String]
|
22
|
+
# @param pre [Boolean] install a prerelease version if available
|
23
|
+
# @param version [String] install a specific version
|
24
|
+
def install_plugin(plugin_name, pre: false, version: nil)
|
25
|
+
require 'rubygems/dependency_installer'
|
26
|
+
require 'rubygems/requirement'
|
27
|
+
|
28
|
+
cmd = Gem::DependencyInstaller.new(
|
29
|
+
document: false,
|
30
|
+
force: true,
|
31
|
+
prerelease: pre,
|
32
|
+
minimal_deps: true
|
33
|
+
)
|
34
|
+
plugin_version = version.nil? ? Gem::Requirement.default : Gem::Requirement.new(version)
|
35
|
+
without_safe { cmd.install(prefix(plugin_name), plugin_version) }
|
36
|
+
cleanup_plugin(plugin_name)
|
37
|
+
cmd.installed_gems
|
38
|
+
end
|
39
|
+
|
40
|
+
# Uninstall a plugin
|
41
|
+
# @param plugin_name [String]
|
42
|
+
def uninstall_plugin(plugin_name)
|
43
|
+
installed = installed(plugin_name)
|
44
|
+
raise "Plugin #{plugin_name} not installed" unless installed
|
45
|
+
|
46
|
+
require 'rubygems/uninstaller'
|
47
|
+
cmd = Gem::Uninstaller.new(
|
48
|
+
installed.name,
|
49
|
+
all: true,
|
50
|
+
executables: true,
|
51
|
+
force: true,
|
52
|
+
install_dir: installed.base_dir
|
53
|
+
)
|
54
|
+
cmd.uninstall
|
55
|
+
end
|
56
|
+
|
57
|
+
# Search rubygems for kontena plugins
|
58
|
+
# @param pattern [String] optional search pattern
|
59
|
+
def search_plugins(pattern = nil)
|
60
|
+
client = Excon.new('https://rubygems.org')
|
61
|
+
response = client.get(
|
62
|
+
path: "/api/v1/search.json?query=#{prefix(pattern)}",
|
63
|
+
headers: {
|
64
|
+
'Content-Type' => 'application/json',
|
65
|
+
'Accept' => 'application/json'
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
JSON.parse(response.body) rescue nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# Retrieve plugin versions from rubygems
|
73
|
+
# @param plugin_name [String]
|
74
|
+
def gem_versions(plugin_name)
|
75
|
+
client = Excon.new('https://rubygems.org')
|
76
|
+
response = client.get(
|
77
|
+
path: "/api/v1/versions/#{prefix(plugin_name)}.json",
|
78
|
+
headers: {
|
79
|
+
'Content-Type' => 'application/json',
|
80
|
+
'Accept' => 'application/json'
|
81
|
+
}
|
82
|
+
)
|
83
|
+
versions = JSON.parse(response.body)
|
84
|
+
versions.map { |version| Gem::Version.new(version["number"]) }.sort.reverse
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get the latest version number from rubygems
|
88
|
+
# @param plugin_name [String]
|
89
|
+
# @param pre [Boolean] include prerelease versions
|
90
|
+
def latest_version(plugin_name, pre: false)
|
91
|
+
return gem_versions(plugin_name).first if pre
|
92
|
+
gem_versions(plugin_name).find { |version| !version.prerelease? }
|
93
|
+
end
|
94
|
+
|
95
|
+
# Find a plugin by name from installed plugins
|
96
|
+
# @param plugin_name [String]
|
97
|
+
def installed(plugin_name)
|
98
|
+
search = prefix(plugin_name)
|
99
|
+
plugins.find {|plugin| plugin.name == search }
|
100
|
+
end
|
101
|
+
|
102
|
+
# Upgrade an installed plugin
|
103
|
+
# @param plugin_name [String]
|
104
|
+
# @param pre [Boolean] upgrade to a prerelease version if available. Will happen always when the installed version is a prerelease version.
|
105
|
+
def upgrade_plugin(plugin_name, pre: false)
|
106
|
+
installed = installed(plugin_name)
|
107
|
+
if installed.version.prerelease?
|
108
|
+
pre = true
|
109
|
+
end
|
110
|
+
|
111
|
+
if installed
|
112
|
+
latest = latest_version(plugin_name, pre: pre)
|
113
|
+
if latest > installed.version
|
114
|
+
install_plugin(plugin_name, version: latest.to_s)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
raise "Plugin #{plugin_name} not installed"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Runs gem cleanup, removes remains from previous versions
|
122
|
+
# @param plugin_name [String]
|
123
|
+
def cleanup_plugin(plugin_name)
|
124
|
+
require 'rubygems/commands/cleanup_command'
|
125
|
+
cmd = Gem::Commands::CleanupCommand.new
|
126
|
+
options = ['--norc']
|
127
|
+
options += ['-q', '--no-verbose'] unless ENV["DEBUG"]
|
128
|
+
cmd.handle_options options
|
129
|
+
without_safe { cmd.execute }
|
130
|
+
rescue Gem::SystemExitException => e
|
131
|
+
return true if e.exit_code == 0
|
132
|
+
raise
|
133
|
+
end
|
11
134
|
|
12
|
-
|
13
|
-
|
135
|
+
# Gem installation directory
|
136
|
+
# @return [String]
|
137
|
+
def install_dir
|
138
|
+
return @install_dir if @install_dir
|
139
|
+
install_dir = File.join(Dir.home, '.kontena', 'gems', RUBY_VERSION)
|
140
|
+
unless File.directory?(install_dir)
|
141
|
+
require 'fileutils'
|
142
|
+
FileUtils.mkdir_p(install_dir, mode: 0700)
|
143
|
+
end
|
144
|
+
@install_dir = install_dir
|
14
145
|
end
|
15
146
|
|
147
|
+
|
16
148
|
# @return [Array<Gem::Specification>]
|
149
|
+
def plugins
|
150
|
+
@plugins ||= load_plugins
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Execute block without SafeYAML. Gem does security internally.
|
156
|
+
def without_safe(&block)
|
157
|
+
SafeYAML::OPTIONS[:default_mode] = :unsafe if Object.const_defined?(:SafeYAML)
|
158
|
+
yield
|
159
|
+
ensure
|
160
|
+
SafeYAML::OPTIONS[:default_mode] = :safe if Object.const_defined?(:SafeYAML)
|
161
|
+
end
|
162
|
+
|
17
163
|
def load_plugins
|
164
|
+
plugins = []
|
18
165
|
Gem::Specification.to_a.each do |spec|
|
19
166
|
spec.require_paths.to_a.each do |require_path|
|
20
167
|
plugin = File.join(spec.gem_dir, require_path, 'kontena_cli_plugin.rb')
|
21
|
-
if File.exist?(plugin) &&
|
168
|
+
if File.exist?(plugin) && !plugins.find{ |p| p.name == spec.name }
|
22
169
|
begin
|
23
170
|
if spec_has_valid_dependency?(spec)
|
24
171
|
load(plugin)
|
25
|
-
|
172
|
+
plugins << spec
|
26
173
|
else
|
27
174
|
plugin_name = spec.name.sub('kontena-plugin-', '')
|
28
175
|
STDERR.puts " [#{Kontena.pastel.red('error')}] Plugin #{Kontena.pastel.cyan(plugin_name)} (#{spec.version}) is not compatible with the current cli version."
|
@@ -39,11 +186,25 @@ module Kontena
|
|
39
186
|
end
|
40
187
|
end
|
41
188
|
end
|
42
|
-
|
189
|
+
plugins
|
43
190
|
rescue => exc
|
44
191
|
STDERR.puts exc.message
|
45
192
|
end
|
46
193
|
|
194
|
+
def prefix(plugin_name)
|
195
|
+
return plugin_name if plugin_name.to_s.start_with?('kontena-plugin-')
|
196
|
+
"kontena-plugin-#{plugin_name}"
|
197
|
+
end
|
198
|
+
|
199
|
+
def dummy_ui
|
200
|
+
Gem::StreamUI.new(StringIO.new, StringIO.new, StringIO.new, false)
|
201
|
+
end
|
202
|
+
|
203
|
+
def use_dummy_ui
|
204
|
+
require 'rubygems/user_interaction'
|
205
|
+
Gem::DefaultUserInteraction.ui = dummy_ui
|
206
|
+
end
|
207
|
+
|
47
208
|
# @param [Gem::Specification] spec
|
48
209
|
# @return [Boolean]
|
49
210
|
def spec_has_valid_dependency?(spec)
|