kontena-cli 1.4.0 → 1.4.1.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/VERSION +1 -1
- data/bin/kontena +2 -1
- data/kontena-cli.gemspec +1 -1
- data/lib/kontena/cli/certificate/common.rb +16 -0
- data/lib/kontena/cli/certificate/export_command.rb +28 -0
- data/lib/kontena/cli/certificate/import_command.rb +61 -0
- data/lib/kontena/cli/certificate/show_command.rb +5 -2
- data/lib/kontena/cli/certificate_command.rb +3 -1
- data/lib/kontena/cli/common.rb +5 -1
- data/lib/kontena/cli/config.rb +23 -5
- data/lib/kontena/cli/external_registries/add_command.rb +2 -0
- data/lib/kontena/cli/external_registries/list_command.rb +1 -1
- data/lib/kontena/cli/helpers/exec_helper.rb +12 -4
- data/lib/kontena/cli/master/config/import_command.rb +1 -1
- data/lib/kontena/cli/master/login_command.rb +1 -1
- data/lib/kontena/cli/stacks/common.rb +2 -1
- data/lib/kontena/cli/stacks/registry/show_command.rb +1 -1
- data/lib/kontena/cli/stacks/service_generator.rb +1 -0
- data/lib/kontena/cli/stacks/yaml/opto.rb +1 -0
- data/lib/kontena/cli/stacks/yaml/opto/certificates_resolver.rb +37 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +1 -1
- data/lib/kontena/cli/stacks/yaml/reader.rb +5 -2
- data/lib/kontena/cli/stacks/yaml/validations.rb +2 -1
- data/lib/kontena/cli/vault/import_command.rb +1 -1
- data/lib/kontena/client.rb +1 -1
- data/lib/kontena/command.rb +7 -5
- data/lib/kontena/plugin_manager.rb +1 -1
- data/lib/kontena/plugin_manager/cleaner.rb +1 -1
- data/lib/kontena/scripts/completer.rb +1 -1
- data/lib/kontena/stacks_cache.rb +2 -2
- data/lib/kontena_cli.rb +6 -2
- data/spec/fixtures/certificates/test/ca-key.pem +10 -0
- data/spec/fixtures/certificates/test/ca.pem +10 -0
- data/spec/fixtures/certificates/test/ca.srl +1 -0
- data/spec/fixtures/certificates/test/cert.pem +8 -0
- data/spec/fixtures/certificates/test/csr.pem +7 -0
- data/spec/fixtures/certificates/test/key.pem +10 -0
- data/spec/fixtures/certificates/test/real-cert.pem +30 -0
- data/spec/fixtures/docker-compose_v2.yml +1 -0
- data/spec/fixtures/docker-compose_v2_with_variables.yml +12 -0
- data/spec/fixtures/kontena_v3_with_compose_variables.yml +11 -0
- data/spec/fixtures/stack-with-anchors.yml +13 -0
- data/spec/kontena/cli/certificates/export_command_spec.rb +49 -0
- data/spec/kontena/cli/certificates/import_command_spec.rb +70 -0
- data/spec/kontena/cli/certificates/show_command_spec.rb +57 -0
- data/spec/kontena/cli/cloud/login_command_spec.rb +7 -14
- data/spec/kontena/cli/helpers/exec_helper_spec.rb +38 -0
- data/spec/kontena/cli/master/login_command_spec.rb +12 -24
- data/spec/kontena/cli/master/use_command_spec.rb +1 -1
- data/spec/kontena/cli/nodes/remove_command_spec.rb +1 -1
- data/spec/kontena/cli/registry/{create_spec.rb → create_command_spec.rb} +0 -0
- data/spec/kontena/cli/stacks/upgrade_command_spec.rb +1 -1
- data/spec/kontena/cli/stacks/yaml/opto/certificates_resolver_spec.rb +81 -0
- data/spec/kontena/cli/stacks/yaml/reader_spec.rb +22 -2
- data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +17 -0
- data/spec/kontena/command_spec.rb +54 -0
- data/spec/kontena/config_spec.rb +17 -2
- data/spec/kontena/main_command_spec.rb +13 -0
- data/spec/spec_helper.rb +10 -17
- metadata +43 -11
- data/spec/kontena/cli/main_command_spec.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b214db2a1e9aa6a1bcdc8987786facfac926a094bc617ae1ed2786c90e206c2e
|
4
|
+
data.tar.gz: bd38e299c9bad45f7d54990e761036a33a3608ca067166fa2991583c1cc0ef5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13ee888f1151a74792b424fc796b89d5d2ff2319635bc4801bd11017227698f861cd16c2ba087330689a3ebc107fa2432364f08948f6cd55947f77a5977634f2
|
7
|
+
data.tar.gz: 70471db05d252ea9e9bc01be0a07513f83ae840342a619f4fe69cea5292f1cac5fc7bbc6df9465577a66700d0dc97ce8ef3dc101bdff42d951bafaac5b0e1fce
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.1.pre1
|
data/bin/kontena
CHANGED
@@ -12,7 +12,8 @@ if ARGV[0] == 'complete'
|
|
12
12
|
ARGV.delete_at(0)
|
13
13
|
require 'kontena/scripts/completer'
|
14
14
|
else
|
15
|
-
ENV['DEBUG']
|
15
|
+
ENV['DEBUG'] = "true" if ARGV.any? { |arg| arg == '-D' || arg == '--debug'}
|
16
|
+
ENV['DEBUG'] = "false" if ARGV.any? { |arg| arg == '--no-debug' }
|
16
17
|
require 'kontena_cli'
|
17
18
|
Kontena::PluginManager.init unless ENV['NO_PLUGINS']
|
18
19
|
Kontena::MainCommand.run
|
data/kontena-cli.gemspec
CHANGED
@@ -32,6 +32,6 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_runtime_dependency "opto", "1.8.7"
|
33
33
|
spec.add_runtime_dependency "semantic", "~> 1.5"
|
34
34
|
spec.add_runtime_dependency "liquid", "~> 4.0.0"
|
35
|
-
spec.add_runtime_dependency "tty-table", "~> 0.
|
35
|
+
spec.add_runtime_dependency "tty-table", "~> 0.9.0"
|
36
36
|
spec.add_runtime_dependency "kontena-websocket-client", "~> 0.1.1"
|
37
37
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kontena::Cli::Certificate
|
2
|
+
module Common
|
3
|
+
def show_certificate(cert)
|
4
|
+
puts "#{cert['id']}:"
|
5
|
+
puts " subject: #{cert['subject']}"
|
6
|
+
puts " valid until: #{Time.parse(cert['valid_until']).utc.strftime("%FT%TZ")}"
|
7
|
+
if cert['alt_names'] && !cert['alt_names'].empty?
|
8
|
+
puts " alt names:"
|
9
|
+
cert['alt_names'].each do |alt_name|
|
10
|
+
puts " - #{alt_name}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
puts " auto renewable: #{cert['auto_renewable']}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kontena::Cli::Certificate
|
2
|
+
class ExportCommand < Kontena::Command
|
3
|
+
include Kontena::Cli::Common
|
4
|
+
include Kontena::Cli::GridOptions
|
5
|
+
|
6
|
+
parameter "SUBJECT", "Certificate subject"
|
7
|
+
|
8
|
+
requires_current_master
|
9
|
+
requires_current_master_token
|
10
|
+
requires_current_grid
|
11
|
+
|
12
|
+
option ['--certificate', '--cert'], :flag, "Output certificate"
|
13
|
+
option ['--chain'], :flag, "Output chain"
|
14
|
+
option ['--private-key', '--key'], :flag, "Output private key"
|
15
|
+
|
16
|
+
def bundle?
|
17
|
+
![certificate?, chain?, private_key?].any?
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
certificate = client.get("certificates/#{current_grid}/#{self.subject}/export")
|
22
|
+
|
23
|
+
puts certificate['certificate'] if certificate? || bundle?
|
24
|
+
puts certificate['chain'] if chain? || bundle?
|
25
|
+
puts certificate['private_key'] if private_key? || bundle?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require_relative './common'
|
3
|
+
|
4
|
+
module Kontena::Cli::Certificate
|
5
|
+
class ImportCommand < Kontena::Command
|
6
|
+
include Kontena::Cli::Common
|
7
|
+
include Kontena::Cli::GridOptions
|
8
|
+
include Common
|
9
|
+
|
10
|
+
# @raise [ArgumentError]
|
11
|
+
def open_file(path)
|
12
|
+
File.open(path)
|
13
|
+
rescue Errno::ENOENT
|
14
|
+
raise ArgumentError, "File not found: #{path}"
|
15
|
+
end
|
16
|
+
|
17
|
+
parameter 'CERT_FILE', "Path to PEM-encoded X.509 certificate file" do |path|
|
18
|
+
open_file(path)
|
19
|
+
end
|
20
|
+
option '--subject', 'SUBJECT', "Import cert specific subject"
|
21
|
+
option ['--private-key', '--key'], 'KEY_FILE', "Path to private key file", :required => true, :attribute_name => :key_file do |path|
|
22
|
+
open_file(path)
|
23
|
+
end
|
24
|
+
option ['--chain'], 'CHAIN_FILE', "Path to CA cert chain file", :multivalued => true, :attribute_name => :chain_file_list do |path|
|
25
|
+
open_file(path)
|
26
|
+
end
|
27
|
+
|
28
|
+
requires_current_master
|
29
|
+
requires_current_master_token
|
30
|
+
requires_current_grid
|
31
|
+
|
32
|
+
def load_certificate
|
33
|
+
OpenSSL::X509::Certificate.new(self.cert_file)
|
34
|
+
rescue OpenSSL::OpenSSLError => exc
|
35
|
+
exit_with_error "Invalid certificate at #{self.cert_file.path}: #{exc.class}: #{exc.message}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def certificate_subject(cert)
|
39
|
+
cert.subject.to_a.each do |name, data|
|
40
|
+
return data if name == 'CN'
|
41
|
+
end
|
42
|
+
|
43
|
+
exit_with_error "No CN in certificate subject: #{cert.subject}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute
|
47
|
+
cert = load_certificate
|
48
|
+
subject = self.subject || self.certificate_subject(cert)
|
49
|
+
|
50
|
+
certificate = spinner "Importing certificate from #{cert_file.path}..." do
|
51
|
+
client.put("certificates/#{current_grid}/#{subject}",
|
52
|
+
certificate: cert.to_pem,
|
53
|
+
private_key: self.key_file.read(),
|
54
|
+
chain: chain_file_list.map{|chain_file| chain_file.read() },
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
show_certificate(certificate)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require_relative '../services/services_helper'
|
2
|
+
require_relative './common'
|
2
3
|
|
3
4
|
module Kontena::Cli::Certificate
|
4
5
|
class ShowCommand < Kontena::Command
|
5
6
|
include Kontena::Cli::Common
|
6
7
|
include Kontena::Cli::GridOptions
|
8
|
+
include Common
|
7
9
|
|
8
10
|
parameter "SUBJECT", "Certificate subject"
|
9
11
|
|
@@ -12,8 +14,9 @@ module Kontena::Cli::Certificate
|
|
12
14
|
requires_current_grid
|
13
15
|
|
14
16
|
def execute
|
15
|
-
|
16
|
-
|
17
|
+
cert = client.get("certificates/#{current_grid}/#{self.subject}")
|
18
|
+
|
19
|
+
show_certificate(cert)
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
@@ -3,13 +3,15 @@ class Kontena::Cli::CertificateCommand < Kontena::Command
|
|
3
3
|
|
4
4
|
subcommand ["list", "ls"], "List certificates", load_subcommand('certificate/list_command')
|
5
5
|
subcommand "show", "Show certificate details", load_subcommand('certificate/show_command')
|
6
|
+
subcommand "export", "Export certificate to file", load_subcommand('certificate/export_command')
|
6
7
|
subcommand "register", "Register to LetsEncrypt", load_subcommand('certificate/register_command')
|
7
8
|
subcommand "authorize", "Create DNS authorization for domain", load_subcommand('certificate/authorize_command')
|
8
9
|
subcommand "request", "Request certificate for domain", load_subcommand('certificate/request_command')
|
9
10
|
subcommand "get", "Get certificate for domain", load_subcommand('certificate/get_command')
|
11
|
+
subcommand "import", "Import certificate from file", load_subcommand('certificate/import_command')
|
10
12
|
subcommand ["remove", "rm"], "Remove certificate for domain", load_subcommand('certificate/remove_command')
|
11
13
|
|
12
14
|
|
13
15
|
def execute
|
14
16
|
end
|
15
|
-
end
|
17
|
+
end
|
data/lib/kontena/cli/common.rb
CHANGED
@@ -40,6 +40,10 @@ module Kontena
|
|
40
40
|
Kontena::Cli::Config.instance
|
41
41
|
end
|
42
42
|
|
43
|
+
def debug?
|
44
|
+
Kontena.debug?
|
45
|
+
end
|
46
|
+
|
43
47
|
# Read from STDIN. If stdin is a console, use prompt to ask.
|
44
48
|
# @param [String] message
|
45
49
|
# @param [Symbol] mode (prompt method: :ask, :multiline, etc)
|
@@ -100,7 +104,7 @@ module Kontena
|
|
100
104
|
def vputs(msg = nil)
|
101
105
|
if running_verbose?
|
102
106
|
puts msg
|
103
|
-
elsif
|
107
|
+
elsif debug? && msg
|
104
108
|
logger.debug msg
|
105
109
|
end
|
106
110
|
end
|
data/lib/kontena/cli/config.rb
CHANGED
@@ -53,21 +53,39 @@ module Kontena
|
|
53
53
|
|
54
54
|
# Craft a regular looking configuration based on ENV variables
|
55
55
|
def load_settings_from_env
|
56
|
+
load_cloud_settings_from_env
|
57
|
+
load_master_settings_from_env
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_master_settings_from_env
|
56
61
|
return nil unless ENV['KONTENA_URL']
|
57
|
-
|
62
|
+
|
63
|
+
debug { 'Loading master configuration from ENV' }
|
58
64
|
servers << Server.new(
|
59
65
|
url: ENV['KONTENA_URL'],
|
60
66
|
name: 'default',
|
61
|
-
token: Token.new(
|
67
|
+
token: Token.new(
|
68
|
+
access_token: ENV['KONTENA_TOKEN'],
|
69
|
+
parent_type: :master, parent_name: 'default'
|
70
|
+
),
|
62
71
|
grid: ENV['KONTENA_GRID'],
|
63
72
|
parent_type: :master,
|
64
73
|
parent_name: 'default'
|
65
74
|
)
|
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
|
-
))
|
69
75
|
|
70
76
|
self.current_master = 'default'
|
77
|
+
end
|
78
|
+
|
79
|
+
def load_cloud_settings_from_env
|
80
|
+
return unless ENV['KONTENA_CLOUD_TOKEN']
|
81
|
+
|
82
|
+
debug { 'Loading cloud configuration from ENV' }
|
83
|
+
accounts << Account.new(kontena_account_data.merge(
|
84
|
+
token: Token.new(
|
85
|
+
access_token: ENV['KONTENA_CLOUD_TOKEN'],
|
86
|
+
parent_type: :account, parent_name: 'default'
|
87
|
+
)
|
88
|
+
))
|
71
89
|
self.current_account = 'kontena'
|
72
90
|
end
|
73
91
|
|
@@ -14,6 +14,8 @@ module Kontena::Cli::ExternalRegistries
|
|
14
14
|
require_current_grid
|
15
15
|
token = require_token
|
16
16
|
|
17
|
+
self.url = "https://#{self.url}" unless self.url.start_with?('http')
|
18
|
+
|
17
19
|
data = { username: username, password: password, email: email, url: url }
|
18
20
|
spinner "Adding #{url.colorize(:cyan)} to external registries " do
|
19
21
|
client(token).post("grids/#{current_grid}/external_registries", data)
|
@@ -6,7 +6,7 @@ module Kontena::Cli::Helpers
|
|
6
6
|
|
7
7
|
websocket_log_level = if ENV["DEBUG"] == 'websocket'
|
8
8
|
Logger::DEBUG
|
9
|
-
elsif
|
9
|
+
elsif Kontena.debug?
|
10
10
|
Logger::INFO
|
11
11
|
else
|
12
12
|
Logger::WARN
|
@@ -27,7 +27,7 @@ module Kontena::Cli::Helpers
|
|
27
27
|
# @param tty [Boolean] read stdin in raw mode, sending tty escapes for remote pty
|
28
28
|
# @raise [ArgumentError] not a tty
|
29
29
|
# @yield [data]
|
30
|
-
# @yieldparam data [String] data from stdin
|
30
|
+
# @yieldparam data [String] unicode data from stdin
|
31
31
|
# @raise [ArgumentError] not a tty
|
32
32
|
# @return EOF on stdin (!tty)
|
33
33
|
def read_stdin(tty: nil)
|
@@ -38,11 +38,18 @@ module Kontena::Cli::Helpers
|
|
38
38
|
# we do not expect EOF on a TTY, ^D sends a tty escape to close the pty instead
|
39
39
|
loop do
|
40
40
|
# raises EOFError, SyscallError or IOError
|
41
|
-
|
41
|
+
chunk = io.readpartial(1024)
|
42
|
+
|
43
|
+
# STDIN.raw does not use the ruby external_encoding, it returns binary strings (ASCII-8BIT encoding)
|
44
|
+
# however, we use websocket text frames with JSON, which expects unicode strings encodable as UTF-8, and does not handle arbitrary binary data
|
45
|
+
# assume all stdin input is using ruby's external_encoding... the JSON.dump will fail if not.
|
46
|
+
chunk.force_encoding(Encoding.default_external)
|
47
|
+
|
48
|
+
yield chunk
|
42
49
|
end
|
43
50
|
}
|
44
51
|
else
|
45
|
-
# line-buffered
|
52
|
+
# line-buffered, using the default external_encoding (probably UTF-8)
|
46
53
|
while line = STDIN.gets
|
47
54
|
yield line
|
48
55
|
end
|
@@ -106,6 +113,7 @@ module Kontena::Cli::Helpers
|
|
106
113
|
})
|
107
114
|
end
|
108
115
|
read_stdin(tty: tty) do |stdin|
|
116
|
+
logger.debug "websocket exec stdin with encoding=#{stdin.encoding}: #{stdin.inspect}"
|
109
117
|
websocket_exec_write(ws, 'stdin' => stdin)
|
110
118
|
end
|
111
119
|
websocket_exec_write(ws, 'stdin' => nil) # EOF
|
@@ -159,7 +159,7 @@ module Kontena::Cli::Master
|
|
159
159
|
elsif response.kind_of?(String) && response.length > 1
|
160
160
|
exit_with_error response
|
161
161
|
else
|
162
|
-
exit_with_error "Invalid response to authentication request : HTTP#{client.last_response.status} #{client.last_response.body if
|
162
|
+
exit_with_error "Invalid response to authentication request : HTTP#{client.last_response.status} #{client.last_response.body if debug?}"
|
163
163
|
end
|
164
164
|
end
|
165
165
|
end
|
@@ -95,7 +95,7 @@ module Kontena::Cli::Stacks
|
|
95
95
|
where.prepend InstanceMethods
|
96
96
|
|
97
97
|
where.option '--values-from', '[FILE]', 'Read variable values from a YAML file', multivalued: true do |filename|
|
98
|
-
values_from_file.merge!(::YAML.safe_load(File.read(filename)))
|
98
|
+
values_from_file.merge!(::YAML.safe_load(File.read(filename), [], [], true, filename))
|
99
99
|
filename
|
100
100
|
end
|
101
101
|
|
@@ -110,6 +110,7 @@ module Kontena::Cli::Stacks
|
|
110
110
|
where.option '-v', "VARIABLE=VALUE", "Set stack variable values, example: -v domain=example.com. Can be used multiple times.", multivalued: true, attribute_name: :var_option do |var_pair|
|
111
111
|
var_name, var_value = var_pair.split('=', 2)
|
112
112
|
values_from_value_options.merge!(::YAML.safe_load(::YAML.dump(var_name => var_value)))
|
113
|
+
var_pair
|
113
114
|
end
|
114
115
|
end
|
115
116
|
|
@@ -15,7 +15,7 @@ module Kontena::Cli::Stacks::Registry
|
|
15
15
|
def execute
|
16
16
|
require 'semantic'
|
17
17
|
unless versions?
|
18
|
-
stack = ::YAML.safe_load(stacks_client.show(stack_name.stack_name, stack_name.version))
|
18
|
+
stack = ::YAML.safe_load(stacks_client.show(stack_name.stack_name, stack_name.version), [], [], true)
|
19
19
|
puts "#{stack['stack']}:"
|
20
20
|
puts " #{"latest_" unless stack_name.version}version: #{stack['version']}"
|
21
21
|
puts " expose: #{stack['expose'] || '-'}"
|
@@ -69,6 +69,7 @@ module Kontena::Cli::Stacks
|
|
69
69
|
data['stop_signal'] = options['stop_signal'] if options['stop_signal']
|
70
70
|
data['stop_grace_period'] = options['stop_grace_period'] if options['stop_grace_period']
|
71
71
|
data['read_only'] = options['read_only'] || false
|
72
|
+
data['entrypoint'] = options['entrypoint'] if options['entrypoint']
|
72
73
|
data
|
73
74
|
end
|
74
75
|
|
@@ -12,4 +12,5 @@ require_relative 'opto/vault_resolver'
|
|
12
12
|
require_relative 'opto/prompt_resolver'
|
13
13
|
require_relative 'opto/service_instances_resolver'
|
14
14
|
require_relative 'opto/vault_cert_prompt_resolver'
|
15
|
+
require_relative 'opto/certificates_resolver'
|
15
16
|
require_relative 'opto/service_link_resolver'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Kontena::Cli::Stacks::YAML::Opto::Resolvers
|
2
|
+
class Certificates < ::Opto::Resolver
|
3
|
+
include Kontena::Cli::Common
|
4
|
+
|
5
|
+
def resolve
|
6
|
+
return nil unless current_master && current_grid
|
7
|
+
message = hint || 'Select SSL certificates'
|
8
|
+
certificates = get_certificates
|
9
|
+
if certificates.size > 0
|
10
|
+
prompt.multi_select(message) do |menu|
|
11
|
+
menu.default(*default_indexes(certificates)) if option.default
|
12
|
+
certificates.each do |s|
|
13
|
+
menu.choice s['subject']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<Hash>] certificates
|
20
|
+
def get_certificates
|
21
|
+
client.get("grids/#{current_grid}/certificates")['certificates']
|
22
|
+
rescue
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param certificates [Array<Hash>]
|
27
|
+
# @return [Array<Integer>]
|
28
|
+
def default_indexes(certificates)
|
29
|
+
indexes = []
|
30
|
+
option.default.to_a.each do |subject|
|
31
|
+
index = certificates.index { |s| s['subject'] == subject }
|
32
|
+
indexes << index.to_i + 1 if index
|
33
|
+
end
|
34
|
+
indexes
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -9,7 +9,7 @@ module Kontena::Cli::Stacks::YAML::Opto::Resolvers
|
|
9
9
|
s['name'].match(/(ssl|cert)/i)
|
10
10
|
}
|
11
11
|
if secrets.size > 0
|
12
|
-
prompt.multi_select(
|
12
|
+
prompt.multi_select(message) do |menu|
|
13
13
|
menu.default(*default_indexes(secrets)) if option.default
|
14
14
|
secrets.each do |s|
|
15
15
|
menu.choice s['name']
|
@@ -83,7 +83,7 @@ module Kontena::Cli::Stacks
|
|
83
83
|
substitutions: default_envs,
|
84
84
|
warnings: false
|
85
85
|
)
|
86
|
-
)
|
86
|
+
), [], [], true, file
|
87
87
|
)
|
88
88
|
rescue Psych::SyntaxError => ex
|
89
89
|
raise ex, "Error while parsing #{file} : #{ex.message}"
|
@@ -104,7 +104,7 @@ module Kontena::Cli::Stacks
|
|
104
104
|
use_opto: true,
|
105
105
|
raise_on_unknown: true
|
106
106
|
)
|
107
|
-
)
|
107
|
+
), [], [], true, file
|
108
108
|
)
|
109
109
|
rescue Psych::SyntaxError => ex
|
110
110
|
raise ex, "Error while parsing #{file} : #{ex.message}"
|
@@ -350,6 +350,9 @@ module Kontena::Cli::Stacks
|
|
350
350
|
|
351
351
|
def from_external_file(filename, service_name)
|
352
352
|
external_reader = FileLoader.new(filename, loader).reader
|
353
|
+
variables.to_a(with_value: true).each do |var|
|
354
|
+
external_reader.variables.build_option(var)
|
355
|
+
end
|
353
356
|
outcome = external_reader.execute(service_name)
|
354
357
|
errors.concat external_reader.errors unless external_reader.errors.empty? || errors.include?(external_reader.errors)
|
355
358
|
notifications.concat external_reader.notifications unless external_reader.notifications.empty? || notifications.include?(external_reader.notifications)
|