kontena-cli 1.2.0.dev1 → 1.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bb3a720a442f0537a388e074fc06d2deca0fe61
4
- data.tar.gz: abb0c04c02d70ea872693f70f972d26c06519fb7
3
+ metadata.gz: f03d83329e4ddcebc48f226b38df3d4eb9b6f96f
4
+ data.tar.gz: 451423d5bc02c8c01a18170cbb665a455d26a3d2
5
5
  SHA512:
6
- metadata.gz: e6c457fe87e24961e71867cfdf13b03bbd0b342f51d78ecaf84a1d67d61aaa55bdba02d3005604dbf92bb55db4e1a64583a396bb232703af8d96b2877c961e62
7
- data.tar.gz: 6d6502e6101bc887c366b4bdb49ac93480bf83ac23c8d411d9b294a95ce5835f9fa375b925a718653a4c06d76ca024e42a1bf2fea3042aa5fca3258757659670
6
+ metadata.gz: 24c1bd893acbaf99a21795710024e0673e79e0685f83f3478f6a708568c2f12f440f6caa463068406a22de4f232de2e6120017ca64334e8fc7dd7977932df3a1
7
+ data.tar.gz: c56ff810d3d4809d2c9d8c3c705389a0c801baf407290e89ec8ee718f3ef04b2d87112122eb379c498032da63994ee0b3f58cb609f24f45105ceeaca994819bf
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.0.dev1
1
+ 1.2.0.pre1
data/kontena-cli.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_runtime_dependency "launchy", "~> 2.4.3"
30
30
  spec.add_runtime_dependency "hash_validator", "~> 0.7.0"
31
31
  spec.add_runtime_dependency "retriable", "~> 2.1.0"
32
- spec.add_runtime_dependency "opto", "1.8.3"
32
+ spec.add_runtime_dependency "opto", "1.8.4"
33
33
  spec.add_runtime_dependency "semantic", "~> 1.5"
34
34
  spec.add_runtime_dependency "safe_yaml", "~> 1.0"
35
35
  spec.add_runtime_dependency "liquid", "~> 4.0.0"
@@ -41,6 +41,13 @@ module Kontena::Cli::Grids
41
41
  puts " exports:"
42
42
  puts " statsd: #{statsd['server']}:#{statsd['port']}"
43
43
  end
44
+ if logs = grid.dig('logs')
45
+ puts "logs:"
46
+ puts " forwarder: #{logs['forwarder']}"
47
+ logs['opts'].each do |k,v|
48
+ puts " #{k}: #{v}"
49
+ end
50
+ end
44
51
  end
45
52
 
46
53
  def grids
@@ -8,10 +8,13 @@ module Kontena::Cli::Grids
8
8
  parameter "NAME", "Grid name"
9
9
  option "--statsd-server", "STATSD_SERVER", "Statsd server address (host:port)"
10
10
  option "--default-affinity", "[AFFINITY]", "Default affinity rule for the grid", multivalued: true
11
+ option "--log-forwarder", "LOG_FORWARDER", "Set grid wide log forwarder"
12
+ option "--log-opt", "[LOG_OPT]", "Set log options (key=value)", multivalued: true
11
13
 
12
14
  def execute
13
15
  require_api_url
14
16
  token = require_token
17
+ validate_log_opts
15
18
  payload = {}
16
19
  if statsd_server
17
20
  server, port = statsd_server.split(':')
@@ -22,10 +25,33 @@ module Kontena::Cli::Grids
22
25
  }
23
26
  }
24
27
  end
28
+
29
+ if log_forwarder
30
+ payload[:logs] = {
31
+ forwarder: log_forwarder,
32
+ opts: parse_log_opts
33
+ }
34
+ end
35
+
25
36
  if default_affinity_list
26
37
  payload[:default_affinity] = default_affinity_list
27
38
  end
28
39
  client(token).put("grids/#{name}", payload)
29
40
  end
41
+
42
+ def validate_log_opts
43
+ if !log_opt_list.empty? && log_forwarder.nil?
44
+ raise Kontena::Errors::StandardError.new(1, "Need to specify --log-forwarder when using --log-opt")
45
+ end
46
+ end
47
+
48
+ def parse_log_opts
49
+ opts = {}
50
+ log_opt_list.each do |opt|
51
+ key, value = opt.split('=')
52
+ opts[key.to_sym] = value
53
+ end
54
+ opts
55
+ end
30
56
  end
31
57
  end
@@ -15,7 +15,7 @@ module Kontena::Cli::Services
15
15
  require_api_url
16
16
 
17
17
  query_params = {}
18
- query_params[:container] = parse_container_name(name, instance) if instance
18
+ query_params[:instance] = 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)
@@ -53,8 +53,10 @@ module Kontena::Cli::Services
53
53
  end
54
54
 
55
55
  cpu = stat['cpu'].nil? ? 'N/A' : stat['cpu']['usage']
56
- network_in = stat['network'].nil? ? 'N/A' : filesize_to_human(stat['network']['rx_bytes'])
57
- network_out = stat['network'].nil? ? 'N/A' : filesize_to_human(stat['network']['tx_bytes'])
56
+
57
+ network_in = stat['network'].nil? ? 'N/A' : filesize_to_human(network_bytes(stat['network'], 'rx_bytes'))
58
+ network_out = stat['network'].nil? ? 'N/A' : filesize_to_human(network_bytes(stat['network'], 'tx_bytes'))
59
+
58
60
  prefix = self.name.split('/')[0]
59
61
  instance_name = stat['container_id'].gsub("#{prefix}-", "")
60
62
  puts '%-30.30s %-15s %-20s %-15s %-15s' % [ instance_name, "#{cpu}%", "#{memory} / #{memory_limit}", "#{memory_pct}", "#{network_in}/#{network_out}"]
@@ -72,5 +74,13 @@ module Kontena::Cli::Services
72
74
  rescue FloatDomainError
73
75
  'N/A'
74
76
  end
77
+
78
+ ##
79
+ # @param [Hash] network
80
+ # @param [String] key
81
+ # @return [Integer]
82
+ def network_bytes(network, key)
83
+ (network.dig('internal', key) || 0) + (network.dig('external', key) || 0)
84
+ end
75
85
  end
76
86
  end
@@ -6,10 +6,16 @@ module Kontena::Cli::Stacks::YAML::Validations::CustomValidators
6
6
 
7
7
  def validate(key, value, validations, errors)
8
8
  unless value.is_a?(Hash)
9
- errors[key] = 'hooks must be array'
9
+ errors[key] = "must be a mapping, not #{value.class}"
10
10
  return
11
11
  end
12
12
 
13
+ value.keys.each do |hook|
14
+ unless %w(pre_build post_start).include?(hook)
15
+ errors[key] = "invalid hook #{hook}"
16
+ end
17
+ end
18
+
13
19
  if value['pre_build']
14
20
  validate_pre_build_hooks(key, value['pre_build'], errors)
15
21
  end
@@ -21,7 +27,7 @@ module Kontena::Cli::Stacks::YAML::Validations::CustomValidators
21
27
 
22
28
  def validate_pre_build_hooks(key, pre_build_hooks, errors)
23
29
  unless pre_build_hooks.is_a?(Array)
24
- errors[key] = 'pre_build must be array'
30
+ errors[key] = { 'pre_build' => "must be an array" }
25
31
  return
26
32
  end
27
33
  pre_build_validation = {
@@ -36,7 +42,7 @@ module Kontena::Cli::Stacks::YAML::Validations::CustomValidators
36
42
 
37
43
  def validate_post_start_hooks(key, post_start_hooks, errors)
38
44
  unless post_start_hooks.is_a?(Array)
39
- errors[key] = 'post_start must be array'
45
+ errors[key] = { 'post_start' => 'must be an array' }
40
46
  return
41
47
  end
42
48
  post_start_validation = {
@@ -0,0 +1,8 @@
1
+
2
+ class Kontena::Cli::VolumeCommand < Kontena::Command
3
+
4
+ subcommand "create", "Create a managed volume", load_subcommand('volumes/create_command')
5
+ subcommand ["remove", "rm"], "Remove a managed volume", load_subcommand('volumes/remove_command')
6
+ subcommand ["list", "ls"], "List managed volumes", load_subcommand('volumes/list_command')
7
+
8
+ end
@@ -0,0 +1,38 @@
1
+
2
+ module Kontena::Cli::Volumes
3
+ class CreateCommand < Kontena::Command
4
+ include Kontena::Cli::Common
5
+ include Kontena::Cli::GridOptions
6
+
7
+
8
+ banner "Creates a volume"
9
+ parameter 'NAME', 'Volume name'
10
+
11
+ option '--driver', 'DRIVER', 'Volume driver to be used'
12
+ option '--driver-opt', 'DRIVER_OPT', 'Volume driver options', multivalued: true
13
+ option '--scope', 'SCOPE', 'Volume scope'
14
+
15
+ requires_current_master
16
+ requires_current_master_token
17
+
18
+ def execute
19
+ volume = {
20
+ name: name,
21
+ scope: scope,
22
+ driver: driver,
23
+ driver_opts: parse_driver_opts
24
+ }
25
+ spinner "Creating volume #{pastel.cyan(name)} " do
26
+ create_volume(volume)
27
+ end
28
+ end
29
+
30
+ def parse_driver_opts
31
+ Hash[driver_opt_list.map{|opt| opt.split '='}]
32
+ end
33
+
34
+ def create_volume(volume)
35
+ client.post("volumes/#{current_grid}", volume)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Kontena::Cli::Volumes
3
+ class ListCommand < Kontena::Command
4
+ include Kontena::Cli::Common
5
+ include Kontena::Cli::GridOptions
6
+
7
+
8
+ requires_current_master
9
+ requires_current_master_token
10
+
11
+ def execute
12
+ volumes = client.get("volumes/#{current_grid}")['volumes']
13
+ columns = '%-25.25s %-25.25s %-25.25s %-25.25s'
14
+ puts columns % ['NAME', 'SCOPE', 'DRIVER', 'CREATED AT']
15
+ volumes.each do |volume|
16
+ puts columns % [volume['name'], volume['scope'], volume['driver'], volume['created_at']]
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+
2
+ module Kontena::Cli::Volumes
3
+ class RemoveCommand < Kontena::Command
4
+ include Kontena::Cli::Common
5
+ include Kontena::Cli::GridOptions
6
+
7
+
8
+ banner "Removes a volume"
9
+ parameter 'VOLUME', 'Volume'
10
+
11
+ requires_current_master
12
+ requires_current_master_token
13
+
14
+ def execute
15
+ spinner "Removing volume #{pastel.cyan(volume)} " do
16
+ remove_volume(volume)
17
+ end
18
+ end
19
+
20
+ def remove_volume(volume)
21
+ client.delete("volumes/#{current_grid}/#{volume}")
22
+ end
23
+ end
24
+ end
@@ -213,7 +213,7 @@ class Kontena::Command < Clamp::Command
213
213
  end
214
214
  rescue Kontena::Errors::StandardError => exc
215
215
  raise exc if ENV['DEBUG']
216
- puts " [#{Kontena.pastel.red('error')}] #{exc.message}"
216
+ $stderr.puts " [#{Kontena.pastel.red('error')}] #{exc.message}"
217
217
  abort
218
218
  rescue Errno::EPIPE
219
219
  # If user is piping the command outputs to some other command that might exit before CLI has outputted everything
@@ -36,6 +36,7 @@ class Kontena::MainCommand < Kontena::Command
36
36
  subcommand "whoami", "Shows current logged in user", load_subcommand('whoami_command')
37
37
  subcommand "plugin", "Plugin related commands", load_subcommand('plugin_command')
38
38
  subcommand "version", "Show CLI and current master version", load_subcommand('version_command')
39
+ subcommand "volume", "Volume specific commands", load_subcommand('volume_command')
39
40
 
40
41
  def execute
41
42
  end
@@ -4,4 +4,4 @@ export PATH=/opt/kontena/embedded/bin:$PATH
4
4
  export GEM_HOME=/opt/kontena/embedded/lib/ruby/gems/2.1.0
5
5
  export GEM_PATH=$GEM_HOME
6
6
 
7
- exec /opt/kontena/embedded/bin/kontena $@
7
+ exec /opt/kontena/embedded/bin/kontena "$@"
@@ -0,0 +1,46 @@
1
+
2
+ require_relative "../../../spec_helper"
3
+ require 'kontena/cli/grids/update_command'
4
+
5
+ describe Kontena::Cli::Grids::UpdateCommand do
6
+
7
+ include ClientHelpers
8
+
9
+ let(:client) do
10
+ Kontena::Client.new('https://foo', {access_token: 'abcd1234'})
11
+ end
12
+
13
+ let(:subject) do
14
+ described_class.new(File.basename($0))
15
+ end
16
+
17
+ let(:server) do
18
+ Kontena::Cli::Config::Server.new(url: 'https://localhost', token: 'abcd1234')
19
+ end
20
+
21
+ describe "#update" do
22
+
23
+ context 'log options' do
24
+ it 'should fail if no driver specified' do
25
+ expect {
26
+ subject.run(['--log-opt', 'foo=bar', 'test'])
27
+ }.to exit_with_error
28
+
29
+ end
30
+
31
+ it 'should send valid options to server' do
32
+ expect(client).to receive(:put).with(
33
+ 'grids/test', hash_including({
34
+ logs: {
35
+ forwarder: 'fluentd',
36
+ opts: {
37
+ foo: 'bar'
38
+ }
39
+ }
40
+ })
41
+ )
42
+ subject.run(['--log-forwarder', 'fluentd', '--log-opt', 'foo=bar', 'test'])
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "../../../spec_helper"
2
+ require "kontena/cli/services/logs_command"
3
+
4
+ describe Kontena::Cli::Services::LogsCommand do
5
+
6
+ include ClientHelpers
7
+
8
+ describe '#execute' do
9
+ before(:each) do
10
+ allow(client).to receive(:get).and_return({
11
+ 'logs' => []
12
+ })
13
+ end
14
+
15
+ it 'requires api url' do
16
+ expect(subject).to receive(:require_api_url).once
17
+ subject.run(['service-a'])
18
+ end
19
+
20
+ it 'requires token' do
21
+ expect(subject).to receive(:require_token).and_return(token)
22
+ subject.run(['service-a'])
23
+ end
24
+
25
+ it 'requests logs from master' do
26
+ expect(client).to receive(:get).with(
27
+ 'services/test-grid/null/service-a/container_logs', {limit: 100}
28
+ )
29
+ subject.run(['service-a'])
30
+ end
31
+
32
+ context 'when passing instance option ' do
33
+ it 'adds it to query params' do
34
+ expect(client).to receive(:get).with(
35
+ 'services/test-grid/null/service-a/container_logs', {instance: '1', limit: 100}
36
+ )
37
+ subject.run(['-i', '1', 'service-a'])
38
+ end
39
+ end
40
+ end
41
+ end
@@ -165,6 +165,12 @@ describe Kontena::Cli::Stacks::YAML::ValidatorV3 do
165
165
  end
166
166
 
167
167
  context 'hooks' do
168
+ context 'validates hook name' do
169
+ it 'must be valid hook' do
170
+ result = subject.validate_options('hooks' => { 'pre-build' => {} })
171
+ expect(result.errors.key?('hooks')).to be_truthy
172
+ end
173
+ end
168
174
  context 'validates pre_build' do
169
175
  it 'must be array' do
170
176
  result = subject.validate_options('hooks' => { 'pre_build' => {} })
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.2.0.dev1
4
+ version: 1.2.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-09 00:00:00.000000000 Z
11
+ date: 2017-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - '='
144
144
  - !ruby/object:Gem::Version
145
- version: 1.8.3
145
+ version: 1.8.4
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - '='
151
151
  - !ruby/object:Gem::Version
152
- version: 1.8.3
152
+ version: 1.8.4
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: semantic
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -456,6 +456,10 @@ files:
456
456
  - lib/kontena/cli/vault_command.rb
457
457
  - lib/kontena/cli/version.rb
458
458
  - lib/kontena/cli/version_command.rb
459
+ - lib/kontena/cli/volume_command.rb
460
+ - lib/kontena/cli/volumes/create_command.rb
461
+ - lib/kontena/cli/volumes/list_command.rb
462
+ - lib/kontena/cli/volumes/remove_command.rb
459
463
  - lib/kontena/cli/vpn/config_command.rb
460
464
  - lib/kontena/cli/vpn/create_command.rb
461
465
  - lib/kontena/cli/vpn/remove_command.rb
@@ -559,6 +563,7 @@ files:
559
563
  - spec/kontena/cli/grids/trusted_subnets/add_command_spec.rb
560
564
  - spec/kontena/cli/grids/trusted_subnets/list_command_spec.rb
561
565
  - spec/kontena/cli/grids/trusted_subnets/remove_command_spec.rb
566
+ - spec/kontena/cli/grids/update_command_spec.rb
562
567
  - spec/kontena/cli/grids/use_command_spec.rb
563
568
  - spec/kontena/cli/helpers/log_helper_spec.rb
564
569
  - spec/kontena/cli/main_command_spec.rb
@@ -576,6 +581,7 @@ files:
576
581
  - spec/kontena/cli/services/containers_command_spec.rb
577
582
  - spec/kontena/cli/services/exec_command_spec.rb
578
583
  - spec/kontena/cli/services/link_command_spec.rb
584
+ - spec/kontena/cli/services/logs_command_spec.rb
579
585
  - spec/kontena/cli/services/restart_command_spec.rb
580
586
  - spec/kontena/cli/services/secrets/link_command_spec.rb
581
587
  - spec/kontena/cli/services/secrets/unlink_command_spec.rb
@@ -695,6 +701,7 @@ test_files:
695
701
  - spec/kontena/cli/grids/trusted_subnets/add_command_spec.rb
696
702
  - spec/kontena/cli/grids/trusted_subnets/list_command_spec.rb
697
703
  - spec/kontena/cli/grids/trusted_subnets/remove_command_spec.rb
704
+ - spec/kontena/cli/grids/update_command_spec.rb
698
705
  - spec/kontena/cli/grids/use_command_spec.rb
699
706
  - spec/kontena/cli/helpers/log_helper_spec.rb
700
707
  - spec/kontena/cli/main_command_spec.rb
@@ -712,6 +719,7 @@ test_files:
712
719
  - spec/kontena/cli/services/containers_command_spec.rb
713
720
  - spec/kontena/cli/services/exec_command_spec.rb
714
721
  - spec/kontena/cli/services/link_command_spec.rb
722
+ - spec/kontena/cli/services/logs_command_spec.rb
715
723
  - spec/kontena/cli/services/restart_command_spec.rb
716
724
  - spec/kontena/cli/services/secrets/link_command_spec.rb
717
725
  - spec/kontena/cli/services/secrets/unlink_command_spec.rb