kontena-cli 1.1.0.rc1 → 1.1.0.rc2
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/kontena/cli/apps/deploy_command.rb +1 -5
- data/lib/kontena/cli/cloud/login_command.rb +9 -1
- data/lib/kontena/cli/common.rb +2 -2
- data/lib/kontena/cli/etcd/health_command.rb +58 -0
- data/lib/kontena/cli/etcd_command.rb +2 -0
- data/lib/kontena/cli/external_registry_command.rb +0 -2
- data/lib/kontena/cli/master/login_command.rb +5 -7
- data/lib/kontena/cli/service_command.rb +2 -2
- data/lib/kontena/cli/services/deploy_command.rb +1 -5
- data/lib/kontena/cli/services/exec_command.rb +84 -0
- data/lib/kontena/cli/services/services_helper.rb +4 -1
- data/lib/kontena/cli/stacks/common.rb +6 -17
- data/lib/kontena/cli/stacks/install_command.rb +2 -10
- data/lib/kontena/cli/stacks/show_command.rb +30 -4
- data/lib/kontena/cli/stacks/upgrade_command.rb +20 -7
- data/lib/kontena/cli/stacks/validate_command.rb +1 -9
- data/lib/kontena/cli/stacks/yaml/opto/service_link_resolver.rb +45 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +15 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_resolver.rb +1 -0
- data/lib/kontena/cli/stacks/yaml/reader.rb +36 -26
- data/lib/kontena/command.rb +5 -0
- data/lib/kontena/main_command.rb +5 -4
- data/lib/kontena_cli.rb +4 -0
- data/spec/fixtures/stack-with-prompted-variables.yml +5 -1
- data/spec/fixtures/stack-with-variables.yml +5 -1
- data/spec/kontena/cli/cloud/login_command_spec.rb +1 -0
- data/spec/kontena/cli/etcd/health_command_spec.rb +87 -0
- data/spec/kontena/cli/master/login_command_spec.rb +8 -17
- data/spec/kontena/cli/services/exec_command_spec.rb +137 -0
- data/spec/kontena/cli/stacks/install_command_spec.rb +5 -5
- data/spec/kontena/cli/stacks/upgrade_command_spec.rb +39 -32
- data/spec/kontena/cli/stacks/yaml/reader_spec.rb +22 -0
- data/spec/support/client_helpers.rb +6 -2
- data/spec/support/output_helpers.rb +23 -0
- metadata +11 -7
- data/lib/kontena/cli/external_registries/delete_command.rb +0 -15
- data/lib/kontena/cli/login_command.rb +0 -12
- data/lib/kontena/cli/register_command.rb +0 -9
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f7edb62c595acf6b8f5aaea89084034682684ff6
|
|
4
|
+
data.tar.gz: c90522985a940d60902b7f817b5e1c1e9c26ebec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f213b43e9dc53072014b7ded6f3700a4ff3158f1865c7c7c73aa63fd123af5372f8c7c9bf120dde7ae481104b43eef59e8e991e22cb76edc2472b9e1086e9146
|
|
7
|
+
data.tar.gz: 2d2d45f3431164ab8a56ce97b77d5296f6e03788c2e2f9dc0cefbecf2b2672219f377a09c7078a7512e1fead10dff3f721970ca32e4ed764571013d5bbde11b1
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.0.
|
|
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?
|
|
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
|
data/lib/kontena/cli/common.rb
CHANGED
|
@@ -92,12 +92,12 @@ module Kontena
|
|
|
92
92
|
|
|
93
93
|
def warning(msg)
|
|
94
94
|
warning = pastel.yellow('warn')
|
|
95
|
-
|
|
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
|
-
|
|
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, '
|
|
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
|
-
|
|
73
|
-
|
|
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?
|
|
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 "
|
|
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
|
|
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,
|
|
63
|
-
reader = Kontena::Cli::Stacks::YAML::Reader.new(filename,
|
|
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,
|
|
72
|
-
reader = reader_from_yaml(filename,
|
|
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, '
|
|
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 "
|
|
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}
|
|
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|
|