kontena-cli 1.2.0.dev1 → 1.2.0.pre1
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/kontena-cli.gemspec +1 -1
- data/lib/kontena/cli/grids/common.rb +7 -0
- data/lib/kontena/cli/grids/update_command.rb +26 -0
- data/lib/kontena/cli/services/logs_command.rb +1 -1
- data/lib/kontena/cli/services/stats_command.rb +12 -2
- data/lib/kontena/cli/stacks/yaml/custom_validators/hooks_validator.rb +9 -3
- data/lib/kontena/cli/volume_command.rb +8 -0
- data/lib/kontena/cli/volumes/create_command.rb +38 -0
- data/lib/kontena/cli/volumes/list_command.rb +21 -0
- data/lib/kontena/cli/volumes/remove_command.rb +24 -0
- data/lib/kontena/command.rb +1 -1
- data/lib/kontena/main_command.rb +1 -0
- data/omnibus/wrappers/sh/kontena +1 -1
- data/spec/kontena/cli/grids/update_command_spec.rb +46 -0
- data/spec/kontena/cli/services/logs_command_spec.rb +41 -0
- data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +6 -0
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f03d83329e4ddcebc48f226b38df3d4eb9b6f96f
|
4
|
+
data.tar.gz: 451423d5bc02c8c01a18170cbb665a455d26a3d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24c1bd893acbaf99a21795710024e0673e79e0685f83f3478f6a708568c2f12f440f6caa463068406a22de4f232de2e6120017ca64334e8fc7dd7977932df3a1
|
7
|
+
data.tar.gz: c56ff810d3d4809d2c9d8c3c705389a0c801baf407290e89ec8ee718f3ef04b2d87112122eb379c498032da63994ee0b3f58cb609f24f45105ceeaca994819bf
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.0.
|
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.
|
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[:
|
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
|
-
|
57
|
-
|
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] =
|
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
|
data/lib/kontena/command.rb
CHANGED
@@ -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
|
data/lib/kontena/main_command.rb
CHANGED
@@ -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
|
data/omnibus/wrappers/sh/kontena
CHANGED
@@ -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.
|
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-
|
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.
|
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.
|
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
|