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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/kontena +2 -1
- data/lib/kontena/callback.rb +1 -1
- data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +1 -2
- data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +2 -3
- data/lib/kontena/callbacks/master/deploy/01_show_logo_before_deploy.rb +1 -2
- data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +2 -2
- data/lib/kontena/callbacks/master/deploy/40_install_ssl_certificate_after_deploy.rb +2 -2
- data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +9 -9
- data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +2 -2
- data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +1 -2
- data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +1 -2
- data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +2 -3
- data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +2 -2
- data/lib/kontena/cli/apps/common.rb +0 -1
- data/lib/kontena/cli/apps/init_command.rb +2 -0
- data/lib/kontena/cli/apps/kontena_yml_generator.rb +2 -1
- data/lib/kontena/cli/apps/list_command.rb +10 -2
- data/lib/kontena/cli/apps/yaml/reader.rb +2 -1
- data/lib/kontena/cli/apps/yaml/service_extender.rb +0 -1
- data/lib/kontena/cli/cloud/login_command.rb +51 -7
- data/lib/kontena/cli/cloud/master/list_command.rb +14 -11
- data/lib/kontena/cli/common.rb +36 -83
- data/lib/kontena/cli/config.rb +46 -29
- data/lib/kontena/cli/containers/list_command.rb +30 -41
- data/lib/kontena/cli/etcd/list_command.rb +12 -7
- data/lib/kontena/cli/external_registries/list_command.rb +14 -8
- data/lib/kontena/cli/grids/list_command.rb +18 -10
- data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +7 -5
- data/lib/kontena/cli/grids/users/list_command.rb +9 -7
- data/lib/kontena/cli/localhost_web_server.rb +3 -3
- data/lib/kontena/cli/log_formatters/compact.rb +65 -0
- data/lib/kontena/cli/log_formatters/strip_color.rb +13 -0
- data/lib/kontena/cli/master/config/import_command.rb +2 -1
- data/lib/kontena/cli/master/config/set_command.rb +1 -1
- data/lib/kontena/cli/master/list_command.rb +16 -10
- data/lib/kontena/cli/master/token/list_command.rb +23 -12
- data/lib/kontena/cli/master/user/invite_command.rb +1 -1
- data/lib/kontena/cli/master/user/list_command.rb +17 -6
- data/lib/kontena/cli/nodes/labels/list_command.rb +3 -0
- data/lib/kontena/cli/nodes/list_command.rb +58 -37
- data/lib/kontena/cli/nodes/show_command.rb +1 -1
- data/lib/kontena/cli/plugins/install_command.rb +2 -2
- data/lib/kontena/cli/plugins/list_command.rb +19 -5
- data/lib/kontena/cli/plugins/uninstall_command.rb +1 -1
- data/lib/kontena/cli/services/containers_command.rb +7 -0
- data/lib/kontena/cli/services/envs/list_command.rb +6 -4
- data/lib/kontena/cli/services/list_command.rb +47 -36
- data/lib/kontena/cli/services/services_helper.rb +9 -16
- data/lib/kontena/cli/services/stats_command.rb +2 -1
- data/lib/kontena/cli/spinner.rb +3 -5
- data/lib/kontena/cli/stacks/common.rb +4 -4
- data/lib/kontena/cli/stacks/list_command.rb +42 -33
- data/lib/kontena/cli/stacks/registry/search_command.rb +6 -0
- data/lib/kontena/cli/stacks/registry/show_command.rb +2 -0
- data/lib/kontena/cli/stacks/registry_command.rb +1 -2
- data/lib/kontena/cli/stacks/validate_command.rb +1 -0
- data/lib/kontena/cli/stacks/yaml/reader.rb +3 -2
- data/lib/kontena/cli/stacks/yaml/service_extender.rb +0 -1
- data/lib/kontena/cli/stacks/yaml/validations.rb +1 -1
- data/lib/kontena/cli/table_generator.rb +125 -0
- data/lib/kontena/cli/vault/export_command.rb +7 -4
- data/lib/kontena/cli/vault/import_command.rb +3 -0
- data/lib/kontena/cli/vault/list_command.rb +23 -10
- data/lib/kontena/cli/volumes/create_command.rb +8 -4
- data/lib/kontena/cli/volumes/list_command.rb +15 -7
- data/lib/kontena/client.rb +44 -33
- data/lib/kontena/command.rb +7 -4
- data/lib/kontena/debug_instrumentor.rb +10 -9
- data/lib/kontena/main_command.rb +1 -3
- data/lib/kontena/plugin_manager.rb +15 -7
- data/lib/kontena/stacks_cache.rb +7 -7
- data/lib/kontena/stacks_client.rb +24 -5
- data/lib/kontena/util.rb +43 -15
- data/lib/kontena_cli.rb +71 -14
- data/spec/kontena/cli/cloud/login_command_spec.rb +42 -0
- data/spec/kontena/cli/containers/list_command_spec.rb +1 -2
- data/spec/kontena/cli/nodes/list_command_spec.rb +153 -126
- data/spec/kontena/cli/registry/create_spec.rb +22 -0
- data/spec/kontena/cli/services/stats_command_spec.rb +22 -0
- data/spec/kontena/cli/table_generator_spec.rb +118 -0
- data/spec/kontena/cli/version_command_spec.rb +2 -2
- data/spec/kontena/client_spec.rb +4 -3
- data/spec/support/client_helpers.rb +3 -3
- data/spec/support/output_helpers.rb +54 -8
- metadata +11 -2
@@ -17,7 +17,7 @@ module Kontena::Cli::Nodes
|
|
17
17
|
puts " agent version: #{node['agent_version']}"
|
18
18
|
puts " docker version: #{node['docker_version']}"
|
19
19
|
puts " connected: #{node['connected'] ? 'yes': 'no'}"
|
20
|
-
puts " last connect: #{node['
|
20
|
+
puts " last connect: #{node['connected_at']}"
|
21
21
|
puts " last seen: #{node['last_seen_at']}"
|
22
22
|
puts " public ip: #{node['public_ip']}"
|
23
23
|
puts " private ip: #{node['private_ip']}"
|
@@ -19,7 +19,7 @@ module Kontena::Cli::Plugins
|
|
19
19
|
Kontena::PluginManager.instance.upgrade_plugin(name, pre: pre?)
|
20
20
|
rescue => ex
|
21
21
|
$stderr.puts pastel.red("#{ex.class.name} : #{ex.message}")
|
22
|
-
|
22
|
+
logger.error(ex)
|
23
23
|
spin.fail!
|
24
24
|
end
|
25
25
|
end
|
@@ -33,7 +33,7 @@ module Kontena::Cli::Plugins
|
|
33
33
|
Kontena::PluginManager.instance.install_plugin(name, pre: pre?, version: version)
|
34
34
|
rescue => ex
|
35
35
|
$stderr.puts pastel.red("#{ex.class.name} : #{ex.message}")
|
36
|
-
|
36
|
+
logger.error(ex)
|
37
37
|
spin.fail!
|
38
38
|
end
|
39
39
|
end
|
@@ -2,14 +2,28 @@ require_relative 'common'
|
|
2
2
|
|
3
3
|
module Kontena::Cli::Plugins
|
4
4
|
class ListCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::TableGenerator::Helper
|
5
7
|
include Common
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
banner "List installed plugins"
|
10
|
+
|
11
|
+
def fields
|
12
|
+
quiet? ? [:name] : %i(name version description)
|
13
|
+
end
|
14
|
+
|
15
|
+
def plugins
|
16
|
+
Kontena::PluginManager.instance.plugins.map do |plugin|
|
17
|
+
{
|
18
|
+
name: short_name(plugin.name),
|
19
|
+
version: plugin.version,
|
20
|
+
description: plugin.description
|
21
|
+
}
|
12
22
|
end
|
13
23
|
end
|
24
|
+
|
25
|
+
def execute
|
26
|
+
print_table(plugins)
|
27
|
+
end
|
14
28
|
end
|
15
29
|
end
|
@@ -15,7 +15,7 @@ module Kontena::Cli::Plugins
|
|
15
15
|
Kontena::PluginManager.instance.uninstall_plugin(name)
|
16
16
|
rescue => ex
|
17
17
|
$stderr.puts pastel.red("#{ex.class.name} : #{ex.message}")
|
18
|
-
|
18
|
+
logger.error(ex)
|
19
19
|
spin.fail
|
20
20
|
end
|
21
21
|
end
|
@@ -7,12 +7,19 @@ module Kontena::Cli::Services
|
|
7
7
|
include ServicesHelper
|
8
8
|
|
9
9
|
parameter "NAME", "Service name"
|
10
|
+
option ['-q', '--quiet'], :flag, "Output the identifying column only"
|
10
11
|
|
11
12
|
def execute
|
12
13
|
require_api_url
|
13
14
|
token = require_token
|
14
15
|
|
15
16
|
result = client(token).get("services/#{parse_service_id(name)}/containers")
|
17
|
+
|
18
|
+
if quiet?
|
19
|
+
puts result['containers'].map { |c| "#{c['node']['name']}/#{c['name']}" }.join("\n")
|
20
|
+
exit 0
|
21
|
+
end
|
22
|
+
|
16
23
|
result['containers'].each do |container|
|
17
24
|
puts "#{container['name']}:"
|
18
25
|
puts " rev: #{container['deploy_rev']}"
|
@@ -5,15 +5,17 @@ module Kontena::Cli::Services::Envs
|
|
5
5
|
include Kontena::Cli::Common
|
6
6
|
include Kontena::Cli::GridOptions
|
7
7
|
include Kontena::Cli::Services::ServicesHelper
|
8
|
+
include Kontena::Cli::TableGenerator::Helper
|
8
9
|
|
9
10
|
parameter "NAME", "Service name"
|
10
11
|
|
12
|
+
requires_current_master
|
13
|
+
requires_current_master_token
|
14
|
+
|
11
15
|
def execute
|
12
|
-
|
13
|
-
token = require_token
|
14
|
-
service = client(token).get("services/#{parse_service_id(name)}")
|
16
|
+
service = client.get("services/#{parse_service_id(name)}")
|
15
17
|
service["env"].sort.each do |env|
|
16
|
-
puts env
|
18
|
+
puts quiet? ? env.split('=', 2).first : env
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -4,53 +4,64 @@ module Kontena::Cli::Services
|
|
4
4
|
class ListCommand < Kontena::Command
|
5
5
|
include Kontena::Cli::Common
|
6
6
|
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Cli::TableGenerator::Helper
|
7
8
|
include ServicesHelper
|
8
9
|
|
9
|
-
option ["-q", "--quiet"], :flag, "Show only service names"
|
10
10
|
option '--stack', 'STACK', 'Stack name'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
requires_current_master
|
13
|
+
requires_current_master_token
|
14
|
+
|
15
|
+
def services
|
16
|
+
client.get("grids/#{current_grid}/services#{"?stack=#{stack}" if stack}")['services'].sort_by{|s| s['updated_at'] }.reverse
|
17
|
+
end
|
18
|
+
|
19
|
+
def fields
|
20
|
+
quiet? ? ['name'] : {' ' => 'health_icon', name: 'name', instances: 'instances', stateful: 'stateful', state: 'state', "exposed ports" => 'ports' }
|
21
|
+
end
|
15
22
|
|
16
|
-
|
17
|
-
|
23
|
+
def service_port(port)
|
24
|
+
"#{port['ip']}:#{port['node_port']}->#{port['container_port']}/#{port['protocol']}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def stack_id(service)
|
18
28
|
if quiet?
|
19
|
-
|
20
|
-
puts "#{service.dig('stack', 'id')}/#{service['name']}"
|
21
|
-
end
|
29
|
+
service.fetch('stack', {}).fetch('id', 'null')
|
22
30
|
else
|
23
|
-
|
24
|
-
puts "%-60s %-10s %-8s %-10s %-50s" % titles
|
25
|
-
services.each do |service|
|
26
|
-
print_service_row(service)
|
27
|
-
end
|
31
|
+
service.fetch('stack', {}).fetch('name', nil)
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
else
|
43
|
-
|
35
|
+
def service_name(service)
|
36
|
+
stack_id = stack_id(service)
|
37
|
+
return service['name'] if stack_id == 'null'
|
38
|
+
[ stack_id(service), service['name'] ].compact.join('/')
|
39
|
+
end
|
40
|
+
|
41
|
+
def state_color(state)
|
42
|
+
case state
|
43
|
+
when 'running' then :green
|
44
|
+
when 'initialized' then :cyan
|
45
|
+
when 'stopped' then :red
|
46
|
+
else :blue
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute
|
51
|
+
print_table(services) do |row|
|
52
|
+
row['name'] = service_name(row)
|
53
|
+
next if quiet?
|
54
|
+
row['health_icon'] = health_status_icon(health_status(row))
|
55
|
+
row['stateful'] = row['stateful'] ? pastel.green('yes') : 'no'
|
56
|
+
row['ports'] = row['ports'].map(&method(:service_port)).join(',')
|
57
|
+
row['state'] = pastel.send(state_color(row['state']), row['state'])
|
58
|
+
|
59
|
+
instances = [row['instance_counts']['running'], row['instances']]
|
60
|
+
if instances.first < instances.last
|
61
|
+
instances[0] = pastel.cyan(instances[0].to_s)
|
62
|
+
end
|
63
|
+
row['instances'] = instances.join(' / ')
|
44
64
|
end
|
45
|
-
vars = [
|
46
|
-
health_status_icon(health),
|
47
|
-
name,
|
48
|
-
instances,
|
49
|
-
stateful,
|
50
|
-
service['state'],
|
51
|
-
ports
|
52
|
-
]
|
53
|
-
puts "%s %-58s %-10.10s %-8s %-10s %-50s" % vars
|
54
65
|
end
|
55
66
|
end
|
56
67
|
end
|
@@ -357,23 +357,16 @@ module Kontena
|
|
357
357
|
# @param [Array<String>] port_options
|
358
358
|
# @return [Array<Hash>]
|
359
359
|
def parse_ports(port_options)
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
node_port = port_elements[-2]
|
366
|
-
ip = port_elements[-3] || '0.0.0.0'
|
367
|
-
if node_port.nil? || container_port.nil?
|
368
|
-
raise ArgumentError.new("Invalid port value #{p}")
|
369
|
-
end
|
360
|
+
port_regex = Regexp.new(/\A(?<ip>\d+\.\d+\.\d+\.\d+)?:?(?<node_port>\d+)\:(?<container_port>\d+)\/?(?<protocol>\w+)?\z/)
|
361
|
+
port_options.map do |p|
|
362
|
+
match_data = port_regex.match(p.to_s)
|
363
|
+
raise ArgumentError, "Invalid port value #{p}" unless match_data
|
364
|
+
|
370
365
|
{
|
371
|
-
ip:
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
}
|
376
|
-
}
|
366
|
+
ip: '0.0.0.0',
|
367
|
+
protocol: 'tcp'
|
368
|
+
}.merge(match_data.names.map { |name| [name.to_sym, match_data[name]] }.to_h.reject { |_,v| v.nil? })
|
369
|
+
end
|
377
370
|
end
|
378
371
|
|
379
372
|
# @param [Array<String>] link_options
|
data/lib/kontena/cli/spinner.rb
CHANGED
@@ -69,7 +69,7 @@ module Kontena
|
|
69
69
|
end
|
70
70
|
rescue Exception => ex
|
71
71
|
Kernel.puts "* #{msg}.. fail"
|
72
|
-
|
72
|
+
Kontena.logger.error(ex)
|
73
73
|
raise ex
|
74
74
|
end
|
75
75
|
exit(status) if status
|
@@ -156,13 +156,11 @@ module Kontena
|
|
156
156
|
rescue SpinAbort
|
157
157
|
spin_thread.kill
|
158
158
|
Kernel.puts "\r [" + "fail".colorize(:red) + "] #{msg} "
|
159
|
-
|
160
|
-
$stderr.puts "Spin aborted through fail!"
|
161
|
-
end
|
159
|
+
Kontena.logger.debug { "Spin aborted through fail!" }
|
162
160
|
rescue Exception => ex
|
163
161
|
spin_thread.kill
|
164
162
|
Kernel.puts "\r [" + "fail".colorize(:red) + "] #{msg} "
|
165
|
-
|
163
|
+
Kontena.logger.error(ex)
|
166
164
|
raise ex
|
167
165
|
ensure
|
168
166
|
unless Thread.main['spinner_msgs'].empty?
|
@@ -3,6 +3,9 @@ require_relative '../services/services_helper'
|
|
3
3
|
require_relative 'service_generator_v2'
|
4
4
|
require_relative '../../stacks_client'
|
5
5
|
|
6
|
+
require "safe_yaml"
|
7
|
+
SafeYAML::OPTIONS[:default_mode] = :safe
|
8
|
+
|
6
9
|
module Kontena::Cli::Stacks
|
7
10
|
module Common
|
8
11
|
include Kontena::Cli::Services::ServicesHelper
|
@@ -153,10 +156,7 @@ module Kontena::Cli::Stacks
|
|
153
156
|
end
|
154
157
|
|
155
158
|
def stacks_client
|
156
|
-
|
157
|
-
Kontena.run!(%w(cloud login)) unless cloud_auth?
|
158
|
-
config.reset_instance
|
159
|
-
@stacks_client = Kontena::StacksClient.new(kontena_account.stacks_url, kontena_account.token)
|
159
|
+
@stacks_client ||= Kontena::StacksClient.new(current_account.stacks_url, current_account.token, read_requires_token: current_account.stacks_read_authentication)
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
@@ -4,6 +4,7 @@ module Kontena::Cli::Stacks
|
|
4
4
|
class ListCommand < Kontena::Command
|
5
5
|
include Kontena::Cli::Common
|
6
6
|
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Cli::TableGenerator::Helper
|
7
8
|
include Common
|
8
9
|
|
9
10
|
banner "Lists all installed stacks on a grid in Kontena Master"
|
@@ -11,46 +12,54 @@ module Kontena::Cli::Stacks
|
|
11
12
|
requires_current_master
|
12
13
|
requires_current_master_token
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
HEALTH_ICONS = {
|
16
|
+
unhealthy: Kontena.pastel.red('⊗').freeze,
|
17
|
+
partial: Kontena.pastel.yellow('⊙').freeze,
|
18
|
+
healthy: Kontena.pastel.green('⊛').freeze,
|
19
|
+
default: Kontena.pastel.dim('⊝').freeze
|
20
|
+
}
|
17
21
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
titles = ['NAME', 'STACK', 'SERVICES', 'STATE', 'EXPOSED PORTS']
|
22
|
-
puts "%-30s %-40s %-10s %-10s %-50s" % titles
|
22
|
+
def stacks
|
23
|
+
client.get("grids/#{current_grid}/stacks")['stacks']
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
color = :green
|
36
|
-
else
|
37
|
-
icon = '⊝'.freeze
|
38
|
-
color = :dim
|
39
|
-
end
|
26
|
+
def fields
|
27
|
+
return ['name'] if quiet?
|
28
|
+
{
|
29
|
+
' ' => 'health_icon',
|
30
|
+
name: 'name',
|
31
|
+
stack: 'stack',
|
32
|
+
services: 'services_count',
|
33
|
+
state: 'state',
|
34
|
+
'exposed ports' => 'ports'
|
35
|
+
}
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
]
|
38
|
+
def execute
|
39
|
+
print_table(stacks) do |row|
|
40
|
+
next if quiet?
|
41
|
+
row['health_icon'] = health_icon(stack_health(row))
|
42
|
+
row['stack'] = "#{row['stack']}:#{row['version']}"
|
43
|
+
row['services_count'] = row['services'].size
|
44
|
+
row['ports'] = stack_ports(row).join(',')
|
45
|
+
row['state'] = pastel.send(state_color(row['state']), row['state'])
|
46
|
+
end
|
47
|
+
end
|
49
48
|
|
50
|
-
|
49
|
+
def state_color(state)
|
50
|
+
case state
|
51
|
+
when 'running' then :green
|
52
|
+
when 'deploying', 'initialized' then :blue
|
53
|
+
when 'stopped' then :red
|
54
|
+
when 'partially_running' then :yellow
|
55
|
+
else :clear
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
59
|
+
def health_icon(health)
|
60
|
+
HEALTH_ICONS.fetch(health) { HEALTH_ICONS[:default] }
|
61
|
+
end
|
62
|
+
|
54
63
|
# @param [Hash] stack
|
55
64
|
# @return [Array<String>]
|
56
65
|
def stack_ports(stack)
|
@@ -9,8 +9,14 @@ module Kontena::Cli::Stacks::Registry
|
|
9
9
|
|
10
10
|
parameter "[QUERY]", "Query string"
|
11
11
|
|
12
|
+
option ['-q', '--quiet'], :flag, "Output the identifying column only"
|
13
|
+
|
12
14
|
def execute
|
13
15
|
results = stacks_client.search(query.to_s)
|
16
|
+
if quiet?
|
17
|
+
puts results.map { |s| s['stack'] }.join("\n")
|
18
|
+
exit 0
|
19
|
+
end
|
14
20
|
exit_with_error 'Nothing found' if results.empty?
|
15
21
|
titles = ['NAME', 'VERSION', 'DESCRIPTION']
|
16
22
|
columns = "%-40s %-10s %-40s"
|
@@ -14,6 +14,8 @@ module Kontena::Cli::Stacks::Registry
|
|
14
14
|
|
15
15
|
def execute
|
16
16
|
require 'semantic'
|
17
|
+
require "safe_yaml"
|
18
|
+
SafeYAML::OPTIONS[:default_mode] = :safe
|
17
19
|
unless versions?
|
18
20
|
stack = ::YAML.safe_load(stacks_client.show(stack_name, stack_version))
|
19
21
|
puts "#{stack['stack']}:"
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module Kontena::Cli::Stacks
|
2
2
|
class RegistryCommand < Kontena::Command
|
3
|
-
|
4
3
|
subcommand "push", "Push a stack into the stacks registry", load_subcommand('stacks/registry/push_command')
|
5
4
|
subcommand "pull", "Pull a stack from the stacks registry", load_subcommand('stacks/registry/pull_command')
|
6
|
-
subcommand "search", "Search for stacks in the stacks registry", load_subcommand('stacks/registry/search_command')
|
5
|
+
subcommand ["search"], "Search for stacks in the stacks registry", load_subcommand('stacks/registry/search_command')
|
7
6
|
subcommand "show", "Show info about a stack in the stacks registry", load_subcommand('stacks/registry/show_command')
|
8
7
|
subcommand ["remove", "rm"], "Remove a stack (or version) from the stacks registry", load_subcommand('stacks/registry/remove_command')
|
9
8
|
end
|