kontena-cli 1.4.0.pre6 → 1.4.0.pre7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/VERSION +1 -1
- data/bin/kontena +1 -1
- data/kontena-cli.gemspec +3 -3
- data/lib/kontena/cli/certificate/authorize_command.rb +67 -6
- data/lib/kontena/cli/certificate/get_command.rb +7 -0
- data/lib/kontena/cli/certificate/list_command.rb +75 -0
- data/lib/kontena/cli/certificate/register_command.rb +13 -2
- data/lib/kontena/cli/certificate/request_command.rb +20 -0
- data/lib/kontena/cli/certificate/show_command.rb +19 -0
- data/lib/kontena/cli/certificate_command.rb +4 -1
- data/lib/kontena/cli/cloud/master/add_command.rb +1 -1
- data/lib/kontena/cli/common.rb +21 -33
- data/lib/kontena/cli/etcd/health_command.rb +21 -27
- data/lib/kontena/cli/helpers/exec_helper.rb +15 -6
- data/lib/kontena/cli/helpers/health_helper.rb +12 -0
- data/lib/kontena/cli/helpers/log_helper.rb +2 -2
- data/lib/kontena/cli/helpers/time_helper.rb +29 -0
- data/lib/kontena/cli/master/init_cloud_command.rb +19 -0
- data/lib/kontena/cli/master/list_command.rb +1 -1
- data/lib/kontena/cli/master/ssh_command.rb +3 -1
- data/lib/kontena/cli/master/use_command.rb +1 -2
- data/lib/kontena/cli/node_command.rb +1 -0
- data/lib/kontena/cli/nodes/health_command.rb +28 -13
- data/lib/kontena/cli/nodes/list_command.rb +19 -3
- data/lib/kontena/cli/nodes/show_command.rb +4 -2
- data/lib/kontena/cli/nodes/ssh_command.rb +5 -2
- data/lib/kontena/cli/nodes/update_command.rb +2 -0
- data/lib/kontena/cli/plugins/install_command.rb +11 -8
- data/lib/kontena/cli/plugins/list_command.rb +5 -3
- data/lib/kontena/cli/plugins/search_command.rb +4 -2
- data/lib/kontena/cli/plugins/show_command.rb +17 -0
- data/lib/kontena/cli/plugins/uninstall_command.rb +9 -13
- data/lib/kontena/cli/registry/create_command.rb +1 -1
- data/lib/kontena/cli/services/create_command.rb +6 -0
- data/lib/kontena/cli/services/services_helper.rb +33 -6
- data/lib/kontena/cli/services/update_command.rb +6 -0
- data/lib/kontena/cli/stacks/build_command.rb +3 -3
- data/lib/kontena/cli/stacks/common.rb +105 -90
- data/lib/kontena/cli/stacks/deploy_command.rb +7 -3
- data/lib/kontena/cli/stacks/install_command.rb +39 -6
- data/lib/kontena/cli/stacks/list_command.rb +36 -4
- data/lib/kontena/cli/stacks/logs_command.rb +9 -2
- data/lib/kontena/cli/stacks/registry/pull_command.rb +2 -2
- data/lib/kontena/cli/stacks/registry/push_command.rb +20 -9
- data/lib/kontena/cli/stacks/registry/remove_command.rb +4 -4
- data/lib/kontena/cli/stacks/registry/show_command.rb +4 -4
- data/lib/kontena/cli/stacks/remove_command.rb +27 -1
- data/lib/kontena/cli/stacks/service_generator.rb +12 -2
- data/lib/kontena/cli/stacks/show_command.rb +35 -5
- data/lib/kontena/cli/stacks/stack_name.rb +71 -0
- data/lib/kontena/cli/stacks/upgrade_command.rb +127 -14
- data/lib/kontena/cli/stacks/validate_command.rb +38 -10
- data/lib/kontena/cli/stacks/yaml/custom_validators/certificates_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/opto/prompt_resolver.rb +1 -2
- data/lib/kontena/cli/stacks/yaml/reader.rb +211 -185
- data/lib/kontena/cli/stacks/yaml/service_extender.rb +6 -12
- data/lib/kontena/cli/stacks/yaml/stack_file_loader.rb +97 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/file_loader.rb +41 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/registry_loader.rb +24 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/uri_loader.rb +23 -0
- data/lib/kontena/cli/stacks/yaml/validations.rb +16 -0
- data/lib/kontena/cli/stacks/yaml/validator_v3.rb +25 -8
- data/lib/kontena/client.rb +2 -2
- data/lib/kontena/command.rb +11 -0
- data/lib/kontena/main_command.rb +3 -1
- data/lib/kontena/plugin_manager.rb +11 -198
- data/lib/kontena/plugin_manager/cleaner.rb +33 -0
- data/lib/kontena/plugin_manager/common.rb +86 -0
- data/lib/kontena/plugin_manager/installer.rb +54 -0
- data/lib/kontena/plugin_manager/loader.rb +93 -0
- data/lib/kontena/plugin_manager/rubygems_client.rb +42 -23
- data/lib/kontena/plugin_manager/uninstaller.rb +34 -0
- data/lib/kontena/util.rb +24 -0
- data/lib/kontena_cli.rb +1 -0
- data/omnibus/config/projects/kontena.rb +7 -1
- data/omnibus/config/software/{kontena.rb → kontena-cli.rb} +2 -0
- data/spec/fixtures/api/node.json +2 -1
- data/spec/fixtures/stack-internal-extend.yml +6 -1
- data/spec/fixtures/stack-with-dependencies-dep-1-1.yml +8 -0
- data/spec/fixtures/stack-with-dependencies-dep-1.yml +17 -0
- data/spec/fixtures/stack-with-dependencies-dep-2.yml +8 -0
- data/spec/fixtures/stack-with-dependencies-dep-3.yml +5 -0
- data/spec/fixtures/stack-with-dependencies-dep_2-removed.yml +17 -0
- data/spec/fixtures/stack-with-dependencies-dep_3-added.yml +25 -0
- data/spec/fixtures/stack-with-dependencies.yml +22 -0
- data/spec/fixtures/stack-with-variables.yml +3 -0
- data/spec/kontena/cli/etcd/health_command_spec.rb +45 -33
- data/spec/kontena/cli/helpers/exec_helper_spec.rb +2 -1
- data/spec/kontena/cli/master/init_cloud_command_spec.rb +14 -0
- data/spec/kontena/cli/nodes/health_command_spec.rb +74 -10
- data/spec/kontena/cli/nodes/list_command_spec.rb +381 -232
- data/spec/kontena/cli/nodes/show_command_spec.rb +31 -0
- data/spec/kontena/cli/nodes/ssh_command_spec.rb +18 -3
- data/spec/kontena/cli/plugins/install_command_spec.rb +1 -1
- data/spec/kontena/cli/stacks/build_command_spec.rb +6 -12
- data/spec/kontena/cli/stacks/common_spec.rb +42 -69
- data/spec/kontena/cli/stacks/install_command_spec.rb +57 -31
- data/spec/kontena/cli/stacks/list_command_spec.rb +44 -0
- data/spec/kontena/cli/stacks/logs_command_spec.rb +12 -1
- data/spec/kontena/cli/stacks/remove_command_spec.rb +39 -0
- data/spec/kontena/cli/stacks/show_command_spec.rb +16 -0
- data/spec/kontena/cli/stacks/stack_name_spec.rb +21 -0
- data/spec/kontena/cli/stacks/upgrade_command_spec.rb +73 -56
- data/spec/kontena/cli/stacks/validate_command_spec.rb +81 -0
- data/spec/kontena/cli/stacks/yaml/custom_validators/affinities_validator_spec.rb +22 -0
- data/spec/kontena/cli/stacks/yaml/reader_spec.rb +173 -169
- data/spec/kontena/cli/stacks/yaml/service_extender_spec.rb +12 -3
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/file_loader_spec.rb +47 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/registry_loader_spec.rb +53 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/uri_loader_spec.rb +53 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader_spec.rb +104 -0
- data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +19 -0
- data/spec/kontena/plugin_manager/cleaner_spec.rb +20 -0
- data/spec/kontena/plugin_manager/common_spec.rb +39 -0
- data/spec/kontena/plugin_manager/installer_spec.rb +50 -0
- data/spec/kontena/plugin_manager/loader_spec.rb +5 -0
- data/spec/kontena/plugin_manager/rubygems_client_spec.rb +11 -25
- data/spec/kontena/plugin_manager/uninstaller_spec.rb +19 -0
- data/spec/kontena/plugin_manager_spec.rb +7 -7
- metadata +64 -97
- data/lib/kontena/cli/app_command.rb +0 -22
- data/lib/kontena/cli/apps/build_command.rb +0 -28
- data/lib/kontena/cli/apps/common.rb +0 -172
- data/lib/kontena/cli/apps/config_command.rb +0 -25
- data/lib/kontena/cli/apps/deploy_command.rb +0 -137
- data/lib/kontena/cli/apps/docker_compose_generator.rb +0 -61
- data/lib/kontena/cli/apps/docker_helper.rb +0 -80
- data/lib/kontena/cli/apps/dockerfile_generator.rb +0 -16
- data/lib/kontena/cli/apps/init_command.rb +0 -89
- data/lib/kontena/cli/apps/kontena_yml_generator.rb +0 -105
- data/lib/kontena/cli/apps/list_command.rb +0 -59
- data/lib/kontena/cli/apps/logs_command.rb +0 -37
- data/lib/kontena/cli/apps/monitor_command.rb +0 -93
- data/lib/kontena/cli/apps/remove_command.rb +0 -74
- data/lib/kontena/cli/apps/restart_command.rb +0 -39
- data/lib/kontena/cli/apps/scale_command.rb +0 -33
- data/lib/kontena/cli/apps/service_generator.rb +0 -114
- data/lib/kontena/cli/apps/service_generator_v2.rb +0 -27
- data/lib/kontena/cli/apps/show_command.rb +0 -23
- data/lib/kontena/cli/apps/start_command.rb +0 -40
- data/lib/kontena/cli/apps/stop_command.rb +0 -40
- data/lib/kontena/cli/apps/yaml/custom_validators/affinities_validator.rb +0 -19
- data/lib/kontena/cli/apps/yaml/custom_validators/build_validator.rb +0 -22
- data/lib/kontena/cli/apps/yaml/custom_validators/extends_validator.rb +0 -20
- data/lib/kontena/cli/apps/yaml/custom_validators/hooks_validator.rb +0 -54
- data/lib/kontena/cli/apps/yaml/custom_validators/secrets_validator.rb +0 -22
- data/lib/kontena/cli/apps/yaml/reader.rb +0 -213
- data/lib/kontena/cli/apps/yaml/service_extender.rb +0 -77
- data/lib/kontena/cli/apps/yaml/validations.rb +0 -71
- data/lib/kontena/cli/apps/yaml/validator.rb +0 -38
- data/lib/kontena/cli/apps/yaml/validator_v2.rb +0 -53
- data/spec/fixtures/app.json +0 -42
- data/spec/fixtures/health.yml +0 -26
- data/spec/fixtures/kontena-build.yml +0 -16
- data/spec/fixtures/kontena-internal-extend.yml +0 -8
- data/spec/fixtures/kontena-invalid.yml +0 -4
- data/spec/fixtures/kontena-with-env-file.yml +0 -18
- data/spec/fixtures/kontena-with-variables.yml +0 -19
- data/spec/fixtures/kontena.yml +0 -17
- data/spec/fixtures/kontena_build_v2.yml +0 -26
- data/spec/fixtures/kontena_numeric_version.yml +0 -9
- data/spec/fixtures/kontena_v2.yml +0 -35
- data/spec/fixtures/mysql.yml +0 -3
- data/spec/fixtures/wordpress-scaled.yml +0 -3
- data/spec/fixtures/wordpress.yml +0 -2
- data/spec/kontena/cli/app/build_command_spec.rb +0 -55
- data/spec/kontena/cli/app/common_spec.rb +0 -110
- data/spec/kontena/cli/app/config_command_spec.rb +0 -78
- data/spec/kontena/cli/app/deploy_command_spec.rb +0 -217
- data/spec/kontena/cli/app/docker_helper_spec.rb +0 -155
- data/spec/kontena/cli/app/init_command_spec.rb +0 -109
- data/spec/kontena/cli/app/logs_command_spec.rb +0 -131
- data/spec/kontena/cli/app/scale_spec.rb +0 -51
- data/spec/kontena/cli/app/service_generator_spec.rb +0 -384
- data/spec/kontena/cli/app/service_generator_v2_spec.rb +0 -73
- data/spec/kontena/cli/app/yaml/reader_spec.rb +0 -457
- data/spec/kontena/cli/app/yaml/service_extender_spec.rb +0 -127
- data/spec/kontena/cli/app/yaml/validator_spec.rb +0 -380
- data/spec/kontena/cli/app/yaml/validator_v2_spec.rb +0 -301
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'kontena/plugin_manager'
|
2
|
+
|
3
|
+
module Kontena::Cli::Plugins
|
4
|
+
class ShowCommand < Kontena::Command
|
5
|
+
parameter 'NAME', 'Plugin name' do |name|
|
6
|
+
"kontena-plugin-#{name}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute
|
10
|
+
require 'yaml'
|
11
|
+
plug = Gem::Specification.find { |g| g.name == name }
|
12
|
+
out = {}
|
13
|
+
out[:path] = plug.gem_dir
|
14
|
+
puts out.to_yaml
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,26 +1,22 @@
|
|
1
|
-
require '
|
1
|
+
require 'kontena/plugin_manager'
|
2
2
|
|
3
3
|
module Kontena::Cli::Plugins
|
4
4
|
class UninstallCommand < Kontena::Command
|
5
5
|
include Kontena::Util
|
6
6
|
include Kontena::Cli::Common
|
7
|
+
include Kontena::PluginManager::Common
|
7
8
|
|
8
9
|
parameter 'NAME', 'Plugin name'
|
9
10
|
|
10
|
-
|
11
|
+
def uninstaller
|
12
|
+
Kontena::PluginManager::Uninstaller.new(name)
|
13
|
+
end
|
11
14
|
|
12
15
|
def execute
|
13
|
-
exit_with_error "Plugin #{
|
14
|
-
|
15
|
-
|
16
|
-
begin
|
17
|
-
Kontena::PluginManager.instance.uninstall_plugin(name)
|
18
|
-
rescue => ex
|
19
|
-
$stderr.puts pastel.red("#{ex.class.name} : #{ex.message}")
|
20
|
-
logger.error(ex)
|
21
|
-
spin.fail
|
22
|
-
end
|
16
|
+
exit_with_error "Plugin #{name} has not been installed" unless installed?(name)
|
17
|
+
spinner "Uninstalling plugin #{pastel.cyan(name)}" do
|
18
|
+
uninstaller.uninstall
|
23
19
|
end
|
24
20
|
end
|
25
21
|
end
|
26
|
-
end
|
22
|
+
end
|
@@ -14,7 +14,7 @@ module Kontena::Cli::Registry
|
|
14
14
|
option '--s3-region', 'S3_REGION', 'S3 region', default: 'eu-west-1'
|
15
15
|
option '--s3-encrypt', :flag, 'Encrypt S3 objects', default: false
|
16
16
|
option '--s3-secure', :flag, 'Use secure connection in S3', default: true
|
17
|
-
option '--s3-v4auth', :flag, 'Use v4auth on S3', default:
|
17
|
+
option '--s3-v4auth', :flag, 'Use v4auth on S3', default: true
|
18
18
|
option '--azure-account-name', 'AZURE_ACCOUNT_NAME', 'Azure account name'
|
19
19
|
option '--azure-container-name', 'AZURE_CONTAINER_NAME', 'Azure container name'
|
20
20
|
|
@@ -16,9 +16,13 @@ module Kontena::Cli::Services
|
|
16
16
|
option ["-v", "--volume"], "VOLUME", "Add a volume or bind mount it from the host", multivalued: true
|
17
17
|
option "--volumes-from", "VOLUMES_FROM", "Mount volumes from another container", multivalued: true
|
18
18
|
option ["-a", "--affinity"], "AFFINITY", "Set service affinity", multivalued: true
|
19
|
+
option "--cpus", "CPUS", "Number of CPUs" do |cpus|
|
20
|
+
Float(cpus)
|
21
|
+
end
|
19
22
|
option ["-c", "--cpu-shares"], "CPU_SHARES", "CPU shares (relative weight)"
|
20
23
|
option ["-m", "--memory"], "MEMORY", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)"
|
21
24
|
option ["--memory-swap"], "MEMORY_SWAP", "Total memory usage (memory + swap), set \'-1\' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)"
|
25
|
+
option ["--shm-size"], "SHM_SIZE", "Size of /dev/shm (format: <number><optional unit>, where unit = b, k, m or g)"
|
22
26
|
option "--cmd", "CMD", "Command to execute"
|
23
27
|
option "--instances", "INSTANCES", "How many instances should be deployed"
|
24
28
|
option ["-u", "--user"], "USER", "Username who executes first process inside container"
|
@@ -69,6 +73,8 @@ module Kontena::Cli::Services
|
|
69
73
|
data[:volumes_from] = volumes_from_list unless volumes_from_list.empty?
|
70
74
|
data[:memory] = parse_memory(memory) if memory
|
71
75
|
data[:memory_swap] = parse_memory(memory_swap) if memory_swap
|
76
|
+
data[:shm_size] = parse_memory(shm_size) if shm_size
|
77
|
+
data[:cpus] = cpus if cpus
|
72
78
|
data[:cpu_shares] = cpu_shares if cpu_shares
|
73
79
|
data[:affinity] = affinity_list unless affinity_list.empty?
|
74
80
|
data[:env] = env_list unless env_list.empty?
|
@@ -100,6 +100,15 @@ module Kontena
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
if service['certificates'].to_a.size > 0
|
104
|
+
puts " certificates: "
|
105
|
+
service['certificates'].to_a.each do |c|
|
106
|
+
puts " - subject: #{c['subject']}"
|
107
|
+
puts " name: #{c['name']}"
|
108
|
+
puts " type: #{c['type']}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
103
112
|
if service['env'].to_a.size > 0
|
104
113
|
puts " env: "
|
105
114
|
service['env'].to_a.each do |e|
|
@@ -161,6 +170,14 @@ module Kontena
|
|
161
170
|
end
|
162
171
|
end
|
163
172
|
|
173
|
+
unless service['cpus'].to_s.empty?
|
174
|
+
puts " cpus: #{service['cpus']}"
|
175
|
+
end
|
176
|
+
|
177
|
+
unless service['cpu_shares'].to_s.empty?
|
178
|
+
puts " cpu_shares: #{service['cpu_shares']}"
|
179
|
+
end
|
180
|
+
|
164
181
|
unless service['memory'].to_s.empty?
|
165
182
|
puts " memory: #{int_to_filesize(service['memory'])}"
|
166
183
|
end
|
@@ -169,6 +186,10 @@ module Kontena
|
|
169
186
|
puts " memory_swap: #{int_to_filesize(service['memory_swap'])}"
|
170
187
|
end
|
171
188
|
|
189
|
+
unless service['shm_size'].to_s.empty?
|
190
|
+
puts " shm_size: #{int_to_filesize(service['shm_size'])}"
|
191
|
+
end
|
192
|
+
|
172
193
|
unless service['pid'].to_s.empty?
|
173
194
|
puts " pid: #{service['pid']}"
|
174
195
|
end
|
@@ -361,13 +382,19 @@ module Kontena
|
|
361
382
|
def parse_ports(port_options)
|
362
383
|
port_regex = Regexp.new(/\A(?<ip>\d+\.\d+\.\d+\.\d+)?:?(?<node_port>\d+)\:(?<container_port>\d+)\/?(?<protocol>\w+)?\z/)
|
363
384
|
port_options.map do |p|
|
364
|
-
|
365
|
-
|
385
|
+
if p.kind_of?(Hash)
|
386
|
+
raise ArgumentError, "Missing or invalid node port" unless p['node_port'].to_i > 0
|
387
|
+
raise ArgumentError, "Missing or invalid container port" unless p['container_port'].to_i > 0
|
388
|
+
{ ip: p['ip'] || '0.0.0.0', protocol: p['protocol'] || 'tcp', node_port: p['node_port'].to_i, container_port: p['container_port'].to_i }
|
389
|
+
else
|
390
|
+
match_data = port_regex.match(p.to_s)
|
391
|
+
raise ArgumentError, "Invalid port value #{p}" unless match_data
|
366
392
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
393
|
+
{
|
394
|
+
ip: '0.0.0.0',
|
395
|
+
protocol: 'tcp'
|
396
|
+
}.merge(match_data.names.map { |name| [name.to_sym, match_data[name]] }.to_h.reject { |_,v| v.nil? })
|
397
|
+
end
|
371
398
|
end
|
372
399
|
end
|
373
400
|
|
@@ -14,9 +14,13 @@ module Kontena::Cli::Services
|
|
14
14
|
option ["-e", "--env"], "ENV", "Set environment variables", multivalued: true
|
15
15
|
option ["-l", "--link"], "LINK", "Add link to another service in the form of name:alias", multivalued: true
|
16
16
|
option ["-a", "--affinity"], "AFFINITY", "Set service affinity", multivalued: true
|
17
|
+
option "--cpus", "CPUS", "Number of CPUs" do |cpus|
|
18
|
+
Float(cpus)
|
19
|
+
end
|
17
20
|
option ["-c", "--cpu-shares"], "CPU_SHARES", "CPU shares (relative weight)"
|
18
21
|
option ["-m", "--memory"], "MEMORY", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)"
|
19
22
|
option ["--memory-swap"], "MEMORY_SWAP", "Total memory usage (memory + swap), set \'-1\' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)"
|
23
|
+
option ["--shm-size"], "SHM_SIZE", "Size of /dev/shm (format: <number><optional unit>, where unit = b, k, m or g)"
|
20
24
|
option "--cmd", "CMD", "Command to execute"
|
21
25
|
option "--instances", "INSTANCES", "How many instances should be deployed"
|
22
26
|
option ["-u", "--user"], "USER", "Username who executes first process inside container"
|
@@ -60,6 +64,8 @@ module Kontena::Cli::Services
|
|
60
64
|
data[:links] = parse_links(link_list) unless link_list.empty?
|
61
65
|
data[:memory] = parse_memory(memory) if memory
|
62
66
|
data[:memory_swap] = parse_memory(memory_swap) if memory_swap
|
67
|
+
data[:shm_size] = parse_memory(shm_size) if shm_size
|
68
|
+
data[:cpus] = cpus if cpus
|
63
69
|
data[:cpu_shares] = cpu_shares if cpu_shares
|
64
70
|
data[:affinity] = affinity_list unless affinity_list.empty?
|
65
71
|
data[:env] = env_list unless env_list.empty?
|
@@ -8,7 +8,7 @@ module Kontena::Cli::Stacks
|
|
8
8
|
|
9
9
|
banner "Build images listed in a stack file and push them to your image registry"
|
10
10
|
|
11
|
-
option ['-f', '--file'], 'FILE', 'Specify an alternate Kontena compose file', attribute_name: :
|
11
|
+
option ['-f', '--file'], 'FILE', 'Specify an alternate Kontena compose file', attribute_name: :source, default: 'kontena.yml'
|
12
12
|
|
13
13
|
option ['--no-cache'], :flag, 'Do not use cache when building the image', default: false
|
14
14
|
option ['--no-push'], :flag, 'Do not push images to registry', default: false
|
@@ -26,8 +26,8 @@ module Kontena::Cli::Stacks
|
|
26
26
|
requires_current_master_token
|
27
27
|
|
28
28
|
def execute
|
29
|
-
|
30
|
-
|
29
|
+
set_env_variables(stack_name, current_grid)
|
30
|
+
|
31
31
|
services = stack['services']
|
32
32
|
|
33
33
|
unless service_list.empty?
|
@@ -2,32 +2,72 @@ require_relative 'yaml/reader'
|
|
2
2
|
require_relative '../services/services_helper'
|
3
3
|
require_relative 'service_generator_v2'
|
4
4
|
require_relative '../../stacks_client'
|
5
|
+
require_relative 'yaml/stack_file_loader'
|
5
6
|
require 'yaml'
|
6
7
|
|
7
8
|
module Kontena::Cli::Stacks
|
8
9
|
module Common
|
9
10
|
include Kontena::Cli::Services::ServicesHelper
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
# @return [StackFileLoader] a loader for the stack origin defined through command-line options
|
13
|
+
def loader
|
14
|
+
@loader ||= loader_class.for(source)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [YAML::Reader] a YAML reader for the target file
|
18
|
+
def reader
|
19
|
+
@reader ||= loader.reader
|
20
|
+
end
|
21
|
+
|
22
|
+
# Stack name read from -n parameter or the stack file
|
23
|
+
# @return [String]
|
24
|
+
def stack_name
|
25
|
+
@stack_name ||= (self.respond_to?(:name) && self.name) ? self.name : loader.stack_name.stack
|
26
|
+
end
|
27
|
+
|
28
|
+
# An accessor to the YAML Reader outcome. Passes parent name, values from command line and
|
29
|
+
# the stackname to the reader.
|
30
|
+
#
|
31
|
+
# @return [Hash]
|
32
|
+
def stack
|
33
|
+
@stack ||= reader.execute(
|
34
|
+
name: stack_name,
|
35
|
+
parent_name: self.respond_to?(:parent_name) ? self.parent_name : nil,
|
36
|
+
values: (self.respond_to?(:values_from_options) ? self.values_from_options : {})
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Class] an accessor to StackFileLoader constant, for testing purposes
|
41
|
+
def loader_class
|
42
|
+
::Kontena::Cli::Stacks::YAML::StackFileLoader
|
43
|
+
end
|
44
|
+
|
45
|
+
module RegistryNameParam
|
46
|
+
def stack_name
|
47
|
+
@stack_name ||= Kontena::Cli::Stacks::StackName.new(source)
|
48
|
+
end
|
13
49
|
|
14
50
|
def self.included(where)
|
15
|
-
where.parameter "STACK_NAME", "Stack name, for example user/stackname or user/stackname:version"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
51
|
+
where.parameter "STACK_NAME", "Stack name, for example user/stackname or user/stackname:version", attribute_name: :source
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module StackNameParam
|
56
|
+
# Include to add a STACK_NAME parameter
|
57
|
+
def self.included(where)
|
58
|
+
where.parameter "STACK_NAME", "Stack name, for example user/stackname or user/stackname:version", attribute_name: :source
|
21
59
|
end
|
22
60
|
end
|
23
61
|
|
24
62
|
module StackFileOrNameParam
|
63
|
+
# Include to add a stack file parameter
|
25
64
|
def self.included(where)
|
26
|
-
where.parameter "[FILE]", "Kontena stack file, registry stack name (user/stack or user/stack:version) or URL", default: "kontena.yml", attribute_name: :
|
65
|
+
where.parameter "[FILE]", "Kontena stack file, registry stack name (user/stack or user/stack:version) or URL", default: "kontena.yml", attribute_name: :source
|
27
66
|
end
|
28
67
|
end
|
29
68
|
|
30
69
|
module StackNameOption
|
70
|
+
# Include to add a stack name parameter
|
31
71
|
def self.included(where)
|
32
72
|
where.option ['-n', '--name'], 'NAME', 'Define stack name (by default comes from stack file)'
|
33
73
|
end
|
@@ -35,102 +75,73 @@ module Kontena::Cli::Stacks
|
|
35
75
|
|
36
76
|
module StackValuesToOption
|
37
77
|
attr_accessor :values
|
78
|
+
# Include to add --values-to variable value dumping feature
|
38
79
|
def self.included(where)
|
39
80
|
where.option '--values-to', '[FILE]', 'Output variable values as YAML to file'
|
40
81
|
end
|
41
82
|
|
42
|
-
|
43
|
-
|
44
|
-
|
83
|
+
# Writes a YAML file from the values received from YAML::Reader to a file defined through
|
84
|
+
# the --values-to option
|
85
|
+
def dump_variables
|
86
|
+
File.write(values_to, ::YAML.dump(reader.variable_values, without_defaults: true, without_vault: true))
|
45
87
|
end
|
46
88
|
end
|
47
89
|
|
48
90
|
module StackValuesFromOption
|
49
|
-
|
91
|
+
# Include to add --values-from option to read variable values from a YAML file
|
92
|
+
# and the -v variable=value option that can be used to pass variable values
|
93
|
+
# directly from command line
|
50
94
|
def self.included(where)
|
95
|
+
where.prepend InstanceMethods
|
96
|
+
|
51
97
|
where.option '--values-from', '[FILE]', 'Read variable values from YAML' do |filename|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
98
|
+
values_from_file.merge!(::YAML.safe_load(File.read(filename)))
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
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|
|
103
|
+
var_name, var_value = var_pair.split('=', 2)
|
104
|
+
values_from_value_options.merge!(::YAML.safe_load(::YAML.dump(var_name => var_value)))
|
57
105
|
end
|
58
106
|
end
|
59
|
-
end
|
60
107
|
|
61
|
-
|
62
|
-
|
63
|
-
|
108
|
+
module InstanceMethods
|
109
|
+
def values_from_file
|
110
|
+
@values_from_file ||= {}
|
111
|
+
end
|
64
112
|
|
65
|
-
|
66
|
-
|
67
|
-
if reader.stack_name.nil?
|
68
|
-
exit_with_error "Stack MUST have stack name in YAML top level field 'stack'! Aborting."
|
69
|
-
end
|
70
|
-
set_env_variables(name || reader.stack_name, current_grid)
|
71
|
-
reader
|
72
|
-
end
|
73
|
-
|
74
|
-
def stack_from_reader(reader)
|
75
|
-
outcome = reader.execute
|
76
|
-
|
77
|
-
hint_on_validation_notifications(outcome[:notifications]) unless outcome[:notifications].empty?
|
78
|
-
abort_on_validation_errors(outcome[:errors]) unless outcome[:errors].empty?
|
79
|
-
kontena_services = generate_services(outcome[:services])
|
80
|
-
kontena_volumes = generate_volumes(outcome[:volumes])
|
81
|
-
stack = {
|
82
|
-
'name' => outcome[:name],
|
83
|
-
'stack' => outcome[:stack],
|
84
|
-
'expose' => outcome[:expose],
|
85
|
-
'version' => outcome[:version],
|
86
|
-
'source' => reader.raw_content,
|
87
|
-
'registry' => outcome[:registry],
|
88
|
-
'services' => kontena_services,
|
89
|
-
'volumes' => kontena_volumes,
|
90
|
-
'variables' => outcome[:variables]
|
91
|
-
}
|
92
|
-
stack
|
93
|
-
end
|
94
|
-
|
95
|
-
def stack_from_yaml(filename, name: nil, values: nil, defaults: nil)
|
96
|
-
reader = reader_from_yaml(filename, name: name, values: values, defaults: defaults)
|
97
|
-
stack_from_reader(reader)
|
98
|
-
end
|
99
|
-
|
100
|
-
def stack_read_and_dump(filename, name: nil, values: nil, defaults: nil)
|
101
|
-
reader = reader_from_yaml(filename, name: name, values: values, defaults: defaults)
|
102
|
-
stack = stack_from_reader(reader)
|
103
|
-
dump_variables(reader) if values_to
|
104
|
-
stack
|
105
|
-
end
|
106
|
-
|
107
|
-
def require_config_file(filename)
|
108
|
-
exit_with_error("File #{filename} does not exist") unless File.exists?(filename)
|
109
|
-
end
|
110
|
-
|
111
|
-
def generate_volumes(yaml_volumes)
|
112
|
-
return [] unless yaml_volumes
|
113
|
-
yaml_volumes.map do |name, config|
|
114
|
-
if config['external'].is_a?(TrueClass)
|
115
|
-
config['external'] = name
|
116
|
-
elsif config['external']['name']
|
117
|
-
config['external'] = config['external']['name']
|
113
|
+
def values_from_value_options
|
114
|
+
@values_from_value_options ||= {}
|
118
115
|
end
|
119
|
-
config.merge('name' => name)
|
120
|
-
end
|
121
|
-
end
|
122
116
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
117
|
+
def values_from_options
|
118
|
+
@values_from_options ||= values_from_file.merge(values_from_value_options)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Transforms a hash
|
122
|
+
# dependency_values_from_options('foo.bar' => 1, 'foo')
|
123
|
+
# => { 'bar' => 1 }
|
124
|
+
# Used for dependency variable injection
|
125
|
+
def dependency_values_from_options(name)
|
126
|
+
name_with_dot = name.to_s + '.'
|
127
|
+
values_from_options.each_with_object({}) do |kv_pair, obj|
|
128
|
+
key = kv_pair.first.to_s
|
129
|
+
value = kv_pair.last
|
130
|
+
next unless key.start_with?(name_with_dot)
|
131
|
+
obj[key.sub(name_with_dot, '')] = value
|
132
|
+
end
|
133
|
+
end
|
128
134
|
end
|
129
135
|
end
|
130
136
|
|
131
|
-
|
137
|
+
# Sets environment variables from parameters
|
138
|
+
# @param stack [String] current stack name
|
139
|
+
# @param grid [String] current grid name
|
140
|
+
# @param platform [String] current platform name, defaults to param grid value
|
141
|
+
def set_env_variables(stack, grid, platform = grid)
|
132
142
|
ENV['STACK'] = stack
|
133
143
|
ENV['GRID'] = grid
|
144
|
+
ENV['PLATFORM'] = platform
|
134
145
|
end
|
135
146
|
|
136
147
|
# @return [String]
|
@@ -139,20 +150,24 @@ module Kontena::Cli::Stacks
|
|
139
150
|
end
|
140
151
|
|
141
152
|
def display_notifications(messages, color = :yellow)
|
142
|
-
$stderr.puts(
|
153
|
+
$stderr.puts(pastel.send(color, messages.to_yaml.gsub(/^---$/, '')))
|
143
154
|
end
|
144
155
|
|
145
|
-
def hint_on_validation_notifications(
|
146
|
-
|
147
|
-
|
156
|
+
def hint_on_validation_notifications(notifications, filename = nil)
|
157
|
+
return if notifications.nil? || notifications.empty?
|
158
|
+
$stderr.puts pastel.yellow("#{"(#{filename}) " if filename}YAML contains the following unsupported options and they were rejected:")
|
159
|
+
display_notifications(notifications)
|
148
160
|
end
|
149
161
|
|
150
|
-
def abort_on_validation_errors(errors)
|
151
|
-
|
162
|
+
def abort_on_validation_errors(errors, filename = nil)
|
163
|
+
return if errors.nil? || errors.empty?
|
164
|
+
$stderr.puts pastel.red("#{"(#{filename}) " if filename} YAML validation failed! Aborting.")
|
152
165
|
display_notifications(errors, :red)
|
153
166
|
abort
|
154
167
|
end
|
155
168
|
|
169
|
+
# An accessor to stack registry client
|
170
|
+
# @return [Kontena::StacksClient]
|
156
171
|
def stacks_client
|
157
172
|
@stacks_client ||= Kontena::StacksClient.new(current_account.stacks_url, current_account.token, read_requires_token: current_account.stacks_read_authentication)
|
158
173
|
end
|