kontena-cli 1.0.2 → 1.0.3.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e12d72f9f29547dfcfa19d475d01f78b2e9398f
4
- data.tar.gz: c705ed180718c7bf37ceb1f6b42d71a422ebea0d
3
+ metadata.gz: 1fea7cc00f263ca36c6b676cb044a5a3648dc0b8
4
+ data.tar.gz: d7aae3f41c4f9dab103e01114bfff4401088292f
5
5
  SHA512:
6
- metadata.gz: 26378859f0abaa499a9e958743c1d26cd08adb0ab8e9d2cf145d254b9e7283d4f99861dbab39204fcdfc2fc405f0a611ec5d40013af62019c8a84ff1450064fb
7
- data.tar.gz: c63b8f577000b8b29234e1c402d590ffba2d985afc2931d52e4dd5c5f89488ae3254efee3a84e379deae209e447d151b8df035f8ee25d658ffaddcd7127a1678
6
+ metadata.gz: 92c78f93962b972872fc150b600cccc704711e97956e63d4f2dc9a74784c1b0ee007b26902f0df27dd26bfebcd5a93ede3ae0a5535f3fad9d156dfcc8898a060
7
+ data.tar.gz: 5a562d665b421e8c78af8c73e8ad7a9c4cad963ef3804f815f170e31f5dcb6b0be9dd648cdea90769fd86932c27e72d0548815d7d2aab887d64c2a455aba0784
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.3.rc1
data/kontena-cli.gemspec CHANGED
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_runtime_dependency "retriable", "~> 2.1.0"
32
32
  spec.add_runtime_dependency "opto", "~> 1.5.3"
33
33
  spec.add_runtime_dependency "semantic", "~> 1.5"
34
+ spec.add_runtime_dependency "safe_yaml", "~> 1.0"
34
35
  end
@@ -25,12 +25,12 @@ module Kontena::Cli::Apps
25
25
  end
26
26
 
27
27
  if File.exist?('Procfile')
28
- procfile = ::YAML.load(File.read('Procfile'))
28
+ procfile = ::YAML.safe_load(File.read('Procfile'))
29
29
  else
30
30
  procfile = {}
31
31
  end
32
32
 
33
- app_env = create_env_file(app_json['env']) if app_json['env']
33
+ app_env = create_env_file(app_json['env']) if app_json['env']
34
34
  addons = app_json['addons'] || []
35
35
 
36
36
  if File.exist?(docker_compose_file)
@@ -45,7 +45,7 @@ module Kontena::Cli::Apps
45
45
  end
46
46
 
47
47
  def yml_services(file)
48
- yml = ::YAML.load(file)
48
+ yml = ::YAML.safe_load(file)
49
49
  if yml['version'] == '2'
50
50
  yml['services']
51
51
  else
@@ -29,7 +29,7 @@ module Kontena::Cli::Apps
29
29
  result[:name] = yaml['name']
30
30
  result[:errors] = errors
31
31
  result[:notifications] = notifications
32
- result[:services] = parse_services(service_name) unless errors.count > 0
32
+ result[:services] = errors.count == 0 ? parse_services(service_name) : {}
33
33
  end
34
34
  result
35
35
  end
@@ -52,7 +52,7 @@ module Kontena::Cli::Apps
52
52
  interpolate(content)
53
53
  replace_dollar_dollars(content)
54
54
  begin
55
- @yaml = ::YAML.load(content)
55
+ @yaml = ::YAML.safe_load(content)
56
56
  rescue Psych::SyntaxError => e
57
57
  raise "Error while parsing #{file}".colorize(:red)+ " "+e.message
58
58
  end
@@ -41,7 +41,7 @@ module Kontena::Cli::Master::Config
41
41
  JSON.parse(data)
42
42
  when 'yaml', 'yml'
43
43
  require 'yaml'
44
- YAML.load(data)
44
+ YAML.safe_load(data)
45
45
  else
46
46
  exit_with_error "Unknown input format '#{self.format}'"
47
47
  end
@@ -15,7 +15,7 @@ module Kontena::Cli::Services
15
15
  require_api_url
16
16
 
17
17
  query_params = {}
18
- query_params[:container] = "#{name}-#{instance}" if instance
18
+ query_params[:container] = parse_container_name(name, instance) if instance
19
19
 
20
20
  show_logs("services/#{parse_service_id(name)}/container_logs", query_params) do |log|
21
21
  show_log(log)
@@ -283,6 +283,17 @@ module Kontena
283
283
  end
284
284
  end
285
285
 
286
+ # Parses container name based on service name and instance number
287
+ # @param [String] service_name
288
+ # @param [Integer] instance_number
289
+ def parse_container_name(service_name, instance_number)
290
+ base = service_name.gsub('/', '-')
291
+ unless service_name.include?('/')
292
+ base = "null-#{base}"
293
+ end
294
+ "#{base}-#{instance_number}"
295
+ end
296
+
286
297
  # @param [Array<String>] port_options
287
298
  # @return [Array<Hash>]
288
299
  def parse_ports(port_options)
@@ -15,12 +15,14 @@ module Kontena::Cli::Stacks
15
15
 
16
16
  def execute
17
17
  require_config_file(filename)
18
- services = Kontena::Cli::Stacks::YAML::Reader.new(filename).execute[:services]
18
+ stack = stack_from_yaml(filename)
19
+ services = stack['services']
20
+
19
21
  unless service_list.empty?
20
- services.select! { |name, _| service_list.include?(name) }
22
+ services.select! { |service| service_list.include?(service['name']) }
21
23
  end
22
24
 
23
- if services.none?{ |name, service| service['build'] }
25
+ if services.none?{ |service| service['build'] }
24
26
  abort 'Not found any service with a build option'.colorize(:red)
25
27
  end
26
28
  build_docker_images(services, no_cache?, no_pull?)
@@ -31,7 +33,7 @@ module Kontena::Cli::Stacks
31
33
  # @param [Boolean] no_cache
32
34
  # @param [Boolean] no_pull
33
35
  def build_docker_images(services, no_cache = false, no_pull = false)
34
- services.each do |name, service|
36
+ services.each do |service|
35
37
  if service['build']
36
38
  dockerfile = service['build']['dockerfile'] || 'Dockerfile'
37
39
  abort("'#{service['image']}' is not valid Docker image name") unless validate_image_name(service['image'])
@@ -48,7 +50,7 @@ module Kontena::Cli::Stacks
48
50
 
49
51
  # @param [Hash] services
50
52
  def push_docker_images(services)
51
- services.each do |name, service|
53
+ services.each do |service|
52
54
  if service['build']
53
55
  puts "Pushing image #{service['image'].colorize(:cyan)}"
54
56
  push_docker_image(service['image'])
@@ -15,7 +15,7 @@ module Kontena::Cli::Stacks::Registry
15
15
  def execute
16
16
  require 'semantic'
17
17
  unless versions?
18
- stack = ::YAML.load(stacks_client.show(stack_name, stack_version))
18
+ stack = ::YAML.safe_load(stacks_client.show(stack_name, stack_version))
19
19
  puts "#{stack['stack']}:"
20
20
  puts " #{"latest_" unless stack_version}version: #{stack['version']}"
21
21
  puts " expose: #{stack['expose'] || '-'}"
@@ -44,7 +44,7 @@ module Kontena::Cli::Stacks
44
44
  return @variables if @variables
45
45
  if yaml && yaml.has_key?('variables')
46
46
  variables_yaml = yaml['variables'].to_yaml
47
- variables_hash = ::YAML.load(replace_dollar_dollars(interpolate(variables_yaml, use_opto: false)))
47
+ variables_hash = ::YAML.safe_load(replace_dollar_dollars(interpolate(variables_yaml, use_opto: false)))
48
48
  @variables = Opto::Group.new(variables_hash, defaults: { from: :env, to: :env })
49
49
  else
50
50
  @variables = Opto::Group.new(defaults: { from: :env, to: :env })
@@ -75,14 +75,14 @@ module Kontena::Cli::Stacks
75
75
  result[:expose] = yaml['expose']
76
76
  result[:errors] = errors unless skip_validation?
77
77
  result[:notifications] = notifications
78
- result[:services] = parse_services(service_name) unless errors.count > 0
78
+ result[:services] = errors.count == 0 ? parse_services(service_name) : {}
79
79
  result[:variables] = variables.to_h(values_only: true).reject { |k,_| variables.option(k).to.has_key?(:vault) } unless skip_variables?
80
80
  end
81
81
  result
82
82
  end
83
83
 
84
84
  def stack_name
85
- yaml = ::YAML.load(raw_content)
85
+ yaml = ::YAML.safe_load(raw_content)
86
86
  yaml['stack'].split('/').last.split(':').first if yaml['stack']
87
87
  end
88
88
 
@@ -101,9 +101,9 @@ module Kontena::Cli::Stacks
101
101
 
102
102
  def load_yaml(interpolate = true)
103
103
  if interpolate
104
- @yaml = ::YAML.load(replace_dollar_dollars(interpolate(raw_content)))
104
+ @yaml = ::YAML.safe_load(replace_dollar_dollars(interpolate(raw_content)))
105
105
  else
106
- @yaml = ::YAML.load(raw_content)
106
+ @yaml = ::YAML.safe_load(raw_content)
107
107
  end
108
108
  rescue Psych::SyntaxError => e
109
109
  raise "Error while parsing #{file}".colorize(:red)+ " "+e.message
@@ -72,7 +72,7 @@ class Helper
72
72
 
73
73
  def yml_services
74
74
  if File.exist?('kontena.yml')
75
- yaml = YAML.load(File.read('kontena.yml'))
75
+ yaml = YAML.safe_load(File.read('kontena.yml'))
76
76
  services = yaml['services']
77
77
  services.keys
78
78
  end
@@ -23,7 +23,7 @@ module Kontena
23
23
  end
24
24
 
25
25
  def load
26
- YAML.load(read)
26
+ YAML.safe_load(read)
27
27
  end
28
28
 
29
29
  def write(content)
@@ -78,7 +78,7 @@ module Kontena
78
78
  else
79
79
  dputs "Retrieving #{stack.stack}:#{stack.version} from registry"
80
80
  content = client.pull(stack.stack, stack.version)
81
- yaml = ::YAML.load(content)
81
+ yaml = ::YAML.safe_load(content)
82
82
  new_stack = CachedStack.new(yaml['stack'], yaml['version'])
83
83
  if new_stack.cached?
84
84
  dputs "Already cached"
data/lib/kontena_cli.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  module Kontena
2
2
  # Run a kontena command like it was launched from the command line.
3
- #
3
+ #
4
4
  # @example
5
5
  # Kontena.run("grid list --help")
6
6
  #
7
- # @param [String] command_line
7
+ # @param [String] command_line
8
8
  # @return [Fixnum] exit_code
9
9
  def self.run(cmdline = "", returning: :status)
10
10
  ENV["DEBUG"] && puts("Running Kontena.run(#{cmdline.inspect}, returning: #{returning}")
@@ -19,7 +19,7 @@ module Kontena
19
19
  ENV["DEBUG"] && puts("Command raised #{$!} with message: #{$!.message}\n #{$!.backtrace.join(" \n")}")
20
20
  returning == :status ? 1 : nil
21
21
  end
22
-
22
+
23
23
 
24
24
  def self.version
25
25
  "kontena-cli/#{Kontena::Cli::VERSION}"
@@ -61,6 +61,8 @@ end
61
61
 
62
62
  require 'ruby_dig'
63
63
  require 'shellwords'
64
+ require "safe_yaml"
65
+ SafeYAML::OPTIONS[:default_mode] = :safe
64
66
  require_relative 'kontena/cli/version'
65
67
  require_relative 'kontena/cli/common'
66
68
  require_relative 'kontena/command'
@@ -0,0 +1,12 @@
1
+ version: '2'
2
+ services:
3
+ wordpress:
4
+ image: wordpress:4.1
5
+ ports:
6
+ - 80:80
7
+ depends_on:
8
+ - mysql
9
+ networks:
10
+ - front
11
+ mysql:
12
+ image: mysql:5.6
@@ -6,7 +6,7 @@ variables:
6
6
  required: true
7
7
  min_length: 10
8
8
  empty_is_nil: true
9
- from:
9
+ from:
10
10
  env: WORDPRESS_DB_PASSWORD # first try from local env
11
11
  random_string: # if prompt returned nil, generate a random string
12
12
  length: 10
@@ -19,10 +19,10 @@ variables:
19
19
  random_string:
20
20
  length: 16
21
21
  charset: hex
22
- to:
22
+ to:
23
23
  env: test_var
24
24
  TEST_ENV_VAR: # the default from/to is to set/read env of the option name
25
- type: :string
25
+ type: string
26
26
 
27
27
  services:
28
28
  wordpress:
@@ -33,7 +33,7 @@ services:
33
33
  stateful: true
34
34
  environment:
35
35
  - WORDPRESS_DB_PASSWORD=${STACK}_secret
36
- secrets:
36
+ secrets:
37
37
  - secret: WP_ADMIN_PASSWORD
38
38
  name: WORDPRESS_PASSWORD
39
39
  type: env
@@ -49,7 +49,7 @@ services:
49
49
  service: mysql
50
50
  image: ${MYSQL_IMAGE}
51
51
  stateful: true
52
- secrets:
52
+ secrets:
53
53
  - secret: WP_MYSQL_ROOT_PW
54
54
  name: MYSQL_PASSWORD
55
55
  type: env
@@ -106,7 +106,7 @@ describe Kontena::Cli::Apps::DeployCommand do
106
106
  allow(subject).to receive(:current_dir).and_return("kontena-test")
107
107
  services['wordpress']['environment'] = ['MYSQL_ADMIN_PASSWORD=password']
108
108
  services['wordpress']['env_file'] = %w(/path/to/env_file .env)
109
- allow(YAML).to receive(:load).and_return(services)
109
+ allow(YAML).to receive(:safe_load).and_return(services)
110
110
 
111
111
  expect(File).to receive(:readlines).with('/path/to/env_file').and_return(env_vars)
112
112
  expect(File).to receive(:readlines).with('.env').and_return(dot_env)
@@ -127,7 +127,7 @@ describe Kontena::Cli::Apps::DeployCommand do
127
127
  allow(subject).to receive(:current_dir).and_return("kontena-test")
128
128
  services['wordpress']['environment'] = ['MYSQL_ADMIN_PASSWORD=password']
129
129
  services['wordpress']['env_file'] = '/path/to/env_file'
130
- allow(YAML).to receive(:load).and_return(services)
130
+ allow(YAML).to receive(:safe_load).and_return(services)
131
131
 
132
132
  expect(File).to receive(:readlines).with('/path/to/env_file').and_return(env_vars)
133
133
 
@@ -145,7 +145,7 @@ describe Kontena::Cli::Apps::DeployCommand do
145
145
  it 'merges external links to links' do
146
146
  allow(subject).to receive(:current_dir).and_return("kontena-test")
147
147
  services['wordpress']['external_links'] = ['loadbalancer:loadbalancer']
148
- allow(YAML).to receive(:load).and_return(services)
148
+ allow(YAML).to receive(:safe_load).and_return(services)
149
149
  data = {
150
150
  'name' => 'kontena-test-wordpress',
151
151
  'image' => 'wordpress:latest',
@@ -159,6 +159,16 @@ module Kontena::Cli::Services
159
159
  end
160
160
  end
161
161
 
162
+ describe '#parse_container_name' do
163
+ it 'parses stack services id properly' do
164
+ expect(subject.parse_container_name('foo/mysql', 1)).to eq('foo-mysql-1')
165
+ end
166
+
167
+ it 'parses stackless services id properly' do
168
+ expect(subject.parse_container_name('mysql', 1)).to eq('null-mysql-1')
169
+ end
170
+ end
171
+
162
172
  describe '#parse_image' do
163
173
  it 'adds :default tag if no tag exist' do
164
174
  expect(subject.parse_image('nginx')).to eq('nginx:latest')
@@ -0,0 +1,60 @@
1
+ require_relative "../../../spec_helper"
2
+ require "kontena/cli/stacks/build_command"
3
+
4
+ describe Kontena::Cli::Stacks::BuildCommand do
5
+
6
+ let(:subject) do
7
+ described_class.new(File.basename($0))
8
+ end
9
+
10
+ describe '#execute' do
11
+ let(:stack) do
12
+ {
13
+ 'name' => 'stack-a',
14
+ 'stack' => 'user/stack-a',
15
+ 'version' => '1.0.0',
16
+ 'services' => [
17
+ service
18
+ ]
19
+ }
20
+ end
21
+
22
+ let(:service) do
23
+ {
24
+ 'name' => 'test',
25
+ 'image' => 'registry.kontena.local/test:latest',
26
+ 'build' => {
27
+ 'context' => File.expand_path('.')
28
+ }
29
+ }
30
+ end
31
+
32
+ describe '#execute' do
33
+ before(:each) do
34
+ allow(subject).to receive(:require_config_file).with('kontena.yml').and_return(true)
35
+ allow(subject).to receive(:stack_from_yaml).with('kontena.yml').and_return(stack)
36
+ allow(subject).to receive(:system).and_return(true)
37
+ end
38
+
39
+ it 'requires config file' do
40
+ expect(subject).to receive(:require_config_file).with('kontena.yml').and_return(true)
41
+ subject.run([])
42
+ end
43
+
44
+ it 'reads stack file' do
45
+ expect(subject).to receive(:stack_from_yaml).with('kontena.yml').and_return(stack)
46
+ subject.run([])
47
+ end
48
+
49
+ it 'builds docker image' do
50
+ expect(subject).to receive(:system).with('docker', 'build', '-t', 'registry.kontena.local/test:latest', '--pull', File.expand_path('.'))
51
+ subject.run([])
52
+ end
53
+
54
+ it 'pushes docker image' do
55
+ expect(subject).to receive(:system).with('docker', 'push', 'registry.kontena.local/test:latest')
56
+ subject.run([])
57
+ end
58
+ end
59
+ end
60
+ end
@@ -141,6 +141,23 @@ describe Kontena::Cli::Stacks::YAML::Reader do
141
141
  expect(service_extender).to receive(:extend_from).with(kontena_yml['services']['base'])
142
142
  subject.execute
143
143
  end
144
+
145
+ it 'merges validation errors' do
146
+ allow(File).to receive(:read)
147
+ .with(absolute_yaml_path('docker-compose_v2.yml'))
148
+ .and_return(fixture('docker-compose-invalid.yml'))
149
+ outcome = subject.execute
150
+ expect(outcome[:errors]).to eq([{
151
+ 'docker-compose_v2.yml' =>[
152
+ {
153
+ 'wordpress' => {
154
+ 'networks' => 'key not expected'
155
+ }
156
+ }
157
+ ]
158
+ }])
159
+ end
160
+
144
161
  end
145
162
 
146
163
  context 'variable interpolation' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kontena-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-15 00:00:00.000000000 Z
11
+ date: 2016-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '1.5'
167
+ - !ruby/object:Gem::Dependency
168
+ name: safe_yaml
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.0'
167
181
  description: Kontena command line tool
168
182
  email:
169
183
  - info@kontena.io
@@ -440,6 +454,7 @@ files:
440
454
  - lib/kontena/util.rb
441
455
  - lib/kontena_cli.rb
442
456
  - spec/fixtures/app.json
457
+ - spec/fixtures/docker-compose-invalid.yml
443
458
  - spec/fixtures/docker-compose.yml
444
459
  - spec/fixtures/docker-compose_v2.yml
445
460
  - spec/fixtures/health.yml
@@ -507,6 +522,7 @@ files:
507
522
  - spec/kontena/cli/services/services_helper_spec.rb
508
523
  - spec/kontena/cli/services/unlink_command_spec.rb
509
524
  - spec/kontena/cli/services/update_command_spec.rb
525
+ - spec/kontena/cli/stacks/build_command_spec.rb
510
526
  - spec/kontena/cli/stacks/deploy_command_spec.rb
511
527
  - spec/kontena/cli/stacks/install_command_spec.rb
512
528
  - spec/kontena/cli/stacks/list_command_spec.rb
@@ -544,9 +560,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
544
560
  version: 2.0.0
545
561
  required_rubygems_version: !ruby/object:Gem::Requirement
546
562
  requirements:
547
- - - ">="
563
+ - - ">"
548
564
  - !ruby/object:Gem::Version
549
- version: '0'
565
+ version: 1.3.1
550
566
  requirements: []
551
567
  rubyforge_project:
552
568
  rubygems_version: 2.5.1
@@ -555,6 +571,7 @@ specification_version: 4
555
571
  summary: Kontena command line tool
556
572
  test_files:
557
573
  - spec/fixtures/app.json
574
+ - spec/fixtures/docker-compose-invalid.yml
558
575
  - spec/fixtures/docker-compose.yml
559
576
  - spec/fixtures/docker-compose_v2.yml
560
577
  - spec/fixtures/health.yml
@@ -622,6 +639,7 @@ test_files:
622
639
  - spec/kontena/cli/services/services_helper_spec.rb
623
640
  - spec/kontena/cli/services/unlink_command_spec.rb
624
641
  - spec/kontena/cli/services/update_command_spec.rb
642
+ - spec/kontena/cli/stacks/build_command_spec.rb
625
643
  - spec/kontena/cli/stacks/deploy_command_spec.rb
626
644
  - spec/kontena/cli/stacks/install_command_spec.rb
627
645
  - spec/kontena/cli/stacks/list_command_spec.rb