kontena-cli 1.3.5 → 1.4.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/VERSION +1 -1
- data/lib/kontena/cli/etcd/health_command.rb +1 -1
- data/lib/kontena/cli/grids/common.rb +51 -0
- data/lib/kontena/cli/grids/create_command.rb +13 -9
- data/lib/kontena/cli/grids/update_command.rb +11 -44
- data/lib/kontena/cli/node_command.rb +3 -0
- data/lib/kontena/cli/nodes/create_command.rb +25 -0
- data/lib/kontena/cli/nodes/env_command.rb +32 -0
- data/lib/kontena/cli/nodes/health_command.rb +2 -2
- data/lib/kontena/cli/nodes/labels/add_command.rb +3 -3
- data/lib/kontena/cli/nodes/labels/list_command.rb +2 -2
- data/lib/kontena/cli/nodes/labels/remove_command.rb +3 -3
- data/lib/kontena/cli/nodes/remove_command.rb +9 -7
- data/lib/kontena/cli/nodes/reset_token_command.rb +31 -0
- data/lib/kontena/cli/nodes/show_command.rb +4 -4
- data/lib/kontena/cli/nodes/ssh_command.rb +4 -4
- data/lib/kontena/cli/nodes/update_command.rb +13 -8
- data/lib/kontena/cli/services/create_command.rb +4 -0
- data/lib/kontena/cli/services/services_helper.rb +2 -0
- data/lib/kontena/cli/services/update_command.rb +2 -0
- data/lib/kontena/cli/stacks/service_generator.rb +2 -0
- data/lib/kontena/cli/stacks/show_command.rb +1 -0
- data/lib/kontena/cli/stacks/stacks_helper.rb +2 -3
- data/lib/kontena/cli/stacks/yaml/validations.rb +3 -1
- data/lib/kontena/machine/cloud_config/cloudinit.yml +17 -4
- data/omnibus/package-scripts/kontena/postinst +0 -4
- data/omnibus/package-scripts/kontena/postrm +1 -1
- data/omnibus/package-scripts/kontena/preinst +0 -2
- data/spec/fixtures/api/node.json +93 -0
- data/spec/kontena/cli/containers/logs_command_spec.rb +0 -4
- data/spec/kontena/cli/etcd/health_command_spec.rb +128 -63
- data/spec/kontena/cli/nodes/create_command_spec.rb +24 -0
- data/spec/kontena/cli/nodes/env_command_spec.rb +49 -0
- data/spec/kontena/cli/nodes/health_command_spec.rb +15 -173
- data/spec/kontena/cli/nodes/labels/add_command_spec.rb +56 -0
- data/spec/kontena/cli/nodes/labels/list_command_spec.rb +43 -0
- data/spec/kontena/cli/nodes/labels/remove_command_spec.rb +57 -0
- data/spec/kontena/cli/nodes/list_command_spec.rb +0 -2
- data/spec/kontena/cli/nodes/remove_command_spec.rb +76 -0
- data/spec/kontena/cli/nodes/reset_token_command_spec.rb +38 -0
- data/spec/kontena/cli/nodes/show_command_spec.rb +46 -0
- data/spec/kontena/cli/nodes/ssh_command_spec.rb +5 -0
- data/spec/kontena/cli/nodes/update_command_spec.rb +24 -0
- data/spec/kontena/cli/stacks/deploy_command_spec.rb +21 -0
- data/spec/kontena/cli/stacks/logs_command_spec.rb +0 -4
- data/spec/kontena/cli/table_generator_spec.rb +0 -4
- data/spec/spec_helper.rb +5 -0
- data/spec/support/output_helpers.rb +3 -14
- data/tasks/release.rake +2 -2
- metadata +28 -5
@@ -3,7 +3,7 @@ module Kontena::Cli::Nodes
|
|
3
3
|
include Kontena::Cli::Common
|
4
4
|
include Kontena::Cli::GridOptions
|
5
5
|
|
6
|
-
parameter "[
|
6
|
+
parameter "[NODE]", "SSH to Grid node. Use --any to connect to the first available node"
|
7
7
|
parameter "[COMMANDS] ...", "Run command on host"
|
8
8
|
option ["-a", "--any"], :flag, "Connect to first available node"
|
9
9
|
option ["-i", "--identity-file"], "IDENTITY_FILE", "Path to ssh private key"
|
@@ -15,10 +15,10 @@ module Kontena::Cli::Nodes
|
|
15
15
|
requires_current_grid
|
16
16
|
|
17
17
|
def execute
|
18
|
-
exit_with_error "Cannot combine --any with a node name" if
|
18
|
+
exit_with_error "Cannot combine --any with a node name" if self.node && any?
|
19
19
|
|
20
|
-
if
|
21
|
-
node = client.get("nodes/#{current_grid}/#{
|
20
|
+
if self.node
|
21
|
+
node = client.get("nodes/#{current_grid}/#{self.node}")
|
22
22
|
elsif any?
|
23
23
|
nodes = client.get("grids/#{current_grid}/nodes")['nodes']
|
24
24
|
node = nodes.select{ |node| node['connected'] }.first
|
@@ -3,18 +3,23 @@ module Kontena::Cli::Nodes
|
|
3
3
|
include Kontena::Cli::Common
|
4
4
|
include Kontena::Cli::GridOptions
|
5
5
|
|
6
|
-
|
6
|
+
requires_current_master
|
7
|
+
requires_current_master_token
|
8
|
+
requires_current_grid
|
9
|
+
|
10
|
+
parameter "NODE", "Node name"
|
11
|
+
|
7
12
|
option ["-l", "--label"], "LABEL", "Node label", multivalued: true
|
13
|
+
option "--clear-labels", :flag, "Clear node labels"
|
8
14
|
|
9
15
|
def execute
|
10
|
-
require_api_url
|
11
|
-
require_current_grid
|
12
|
-
token = require_token
|
13
|
-
|
14
16
|
data = {}
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
|
18
|
+
data[:labels] = self.label_list unless self.label_list.empty?
|
19
|
+
data[:labels] = [] if self.clear_labels?
|
20
|
+
|
21
|
+
spinner "Updating #{self.node.colorize(:cyan)} node " do
|
22
|
+
client.put("nodes/#{current_grid}/#{self.node}", data)
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -41,6 +41,8 @@ module Kontena::Cli::Services
|
|
41
41
|
option "--health-check-initial-delay", "DELAY", "Initial delay for health check"
|
42
42
|
option "--health-check-port", "PORT", "Port for health check"
|
43
43
|
option "--health-check-protocol", "PROTOCOL", "Protocol of health check"
|
44
|
+
option "--stop-timeout", "STOP_TIMEOUT", "Timeout (duration) to stop a container"
|
45
|
+
option "--read-only", :flag, "Read-only root fs for the container", default: false
|
44
46
|
|
45
47
|
def execute
|
46
48
|
require_api_url
|
@@ -87,6 +89,8 @@ module Kontena::Cli::Services
|
|
87
89
|
health_check = parse_health_check
|
88
90
|
data[:health_check] = health_check unless health_check.empty?
|
89
91
|
data[:pid] = pid if pid
|
92
|
+
data[:stop_grace_period] = stop_timeout if stop_timeout
|
93
|
+
data[:read_only] = read_only?
|
90
94
|
data
|
91
95
|
end
|
92
96
|
end
|
@@ -52,6 +52,8 @@ module Kontena
|
|
52
52
|
puts " stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
|
53
53
|
puts " scaling: #{service['instances'] }"
|
54
54
|
puts " strategy: #{service['strategy']}"
|
55
|
+
puts " read_only: #{service['read_only'] == true ? 'yes' : 'no'}"
|
56
|
+
puts " stop_grace_period: #{service['stop_grace_period']}s"
|
55
57
|
puts " deploy_opts:"
|
56
58
|
if service['deploy_opts']['min_health']
|
57
59
|
puts " min_health: #{service['deploy_opts']['min_health']}"
|
@@ -38,6 +38,7 @@ module Kontena::Cli::Services
|
|
38
38
|
option "--health-check-initial-delay", "DELAY", "Initial for HTTP health check"
|
39
39
|
option "--health-check-port", "PORT", "Port for HTTP health check"
|
40
40
|
option "--health-check-protocol", "PROTOCOL", "Protocol of health check"
|
41
|
+
option "--stop-timeout", "STOP_TIMEOUT", "Timeout (duration) to stop a container"
|
41
42
|
|
42
43
|
def execute
|
43
44
|
require_api_url
|
@@ -78,6 +79,7 @@ module Kontena::Cli::Services
|
|
78
79
|
health_check = parse_health_check
|
79
80
|
data[:health_check] = health_check unless health_check.empty?
|
80
81
|
data[:pid] = pid if pid
|
82
|
+
data[:stop_grace_period] = stop_timeout if stop_timeout
|
81
83
|
data
|
82
84
|
end
|
83
85
|
end
|
@@ -63,6 +63,8 @@ module Kontena::Cli::Stacks
|
|
63
63
|
data['secrets'] = options['secrets'] if options['secrets']
|
64
64
|
data['build'] = parse_build_options(options) if options['build']
|
65
65
|
data['health_check'] = parse_health_check(options)
|
66
|
+
data['stop_grace_period'] = options['stop_grace_period'] if options['stop_grace_period']
|
67
|
+
data['read_only'] = options['read_only'] || false
|
66
68
|
data
|
67
69
|
end
|
68
70
|
|
@@ -57,6 +57,7 @@ module Kontena::Cli::Stacks
|
|
57
57
|
puts "#{pad} stateful: #{service['stateful'] == true ? 'yes' : 'no' }"
|
58
58
|
puts "#{pad} scaling: #{service['instances'] }"
|
59
59
|
puts "#{pad} strategy: #{service['strategy']}"
|
60
|
+
puts "#{pad} read_only: #{service['read_only'] == true ? 'yes' : 'no'}"
|
60
61
|
puts "#{pad} deploy_opts:"
|
61
62
|
puts "#{pad} min_health: #{service['deploy_opts']['min_health']}"
|
62
63
|
if service['deploy_opts']['wait_for_port']
|
@@ -4,10 +4,9 @@ module Kontena::Cli::Stacks
|
|
4
4
|
def wait_for_deployment_to_start(deployment, timeout = 600)
|
5
5
|
started = false
|
6
6
|
Timeout::timeout(timeout) do
|
7
|
-
|
8
|
-
deployment = client.get("stacks/#{deployment['stack_id']}/deploys/#{deployment['id']}")
|
9
|
-
started = true if deployment['service_deploys'].size > 0
|
7
|
+
while deployment['state'] == 'created'
|
10
8
|
sleep 1
|
9
|
+
deployment = client.get("stacks/#{deployment['stack_id']}/deploys/#{deployment['id']}")
|
11
10
|
end
|
12
11
|
if deployment['state'] == 'error'
|
13
12
|
deployment['service_deploys'].each do |service_deploy|
|
@@ -74,7 +74,9 @@ module Kontena::Cli::Stacks::YAML
|
|
74
74
|
'timeout' => optional('integer'),
|
75
75
|
'interval' => optional('integer'),
|
76
76
|
'initial_delay' => optional('integer')
|
77
|
-
})
|
77
|
+
}),
|
78
|
+
'stop_grace_period' => optional(/(\d+(?:\.\d+)?)([hms])/),
|
79
|
+
'read_only' => optional('boolean')
|
78
80
|
}
|
79
81
|
end
|
80
82
|
|
@@ -19,10 +19,23 @@ write_files:
|
|
19
19
|
fs.inotify.max_user_instances = 8192
|
20
20
|
coreos:
|
21
21
|
units:
|
22
|
-
- name: 50-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
- name: 50-weave.network
|
23
|
+
content: |
|
24
|
+
[Match]
|
25
|
+
Name=weave datapath vxlan-6784
|
26
|
+
|
27
|
+
[Network]
|
28
|
+
Description=Network interfaces managed by weave
|
29
|
+
|
30
|
+
[Link]
|
31
|
+
Unmanaged=true
|
32
|
+
- name: 90-dummy.network
|
33
|
+
content: |
|
34
|
+
[Match]
|
35
|
+
Name=dummy0
|
36
|
+
|
37
|
+
[Link]
|
38
|
+
Unmanaged=true
|
26
39
|
- name: zz-default.network
|
27
40
|
content: |
|
28
41
|
# default should not match virtual Docker/weave bridge/veth network interfaces
|
@@ -12,11 +12,7 @@ error_exit()
|
|
12
12
|
exit 1
|
13
13
|
}
|
14
14
|
|
15
|
-
chown $USER /opt/kontena/embedded/bin
|
16
|
-
chown $USER -R /opt/kontena/embedded/lib/ruby/gems/2.1.0
|
17
15
|
mkdir -p /usr/local/bin
|
18
16
|
ln -s /opt/kontena/bin/kontena /usr/local/bin/kontena
|
19
17
|
|
20
|
-
echo "Thank you for installing Kontena!"
|
21
|
-
|
22
18
|
exit 0
|
@@ -0,0 +1,93 @@
|
|
1
|
+
{
|
2
|
+
"initial_member" : true,
|
3
|
+
"peer_ips" : [
|
4
|
+
"192.168.66.102"
|
5
|
+
],
|
6
|
+
"last_seen_at" : "2017-07-04T08:36:02.280Z",
|
7
|
+
"updated_at" : "2017-07-04T08:35:09.455Z",
|
8
|
+
"node_number" : 1,
|
9
|
+
"volume_drivers" : [
|
10
|
+
{
|
11
|
+
"version" : null,
|
12
|
+
"name" : "local"
|
13
|
+
}
|
14
|
+
],
|
15
|
+
"resource_usage" : {
|
16
|
+
"memory" : {
|
17
|
+
"free" : 194068480,
|
18
|
+
"inactive" : 225415168,
|
19
|
+
"buffers" : 37978112,
|
20
|
+
"cached" : 390828032,
|
21
|
+
"total" : 1045561344,
|
22
|
+
"used" : 851492864,
|
23
|
+
"active" : 521949184
|
24
|
+
},
|
25
|
+
"cpu" : null,
|
26
|
+
"usage" : null,
|
27
|
+
"load" : {
|
28
|
+
"5m" : 0.33642578125,
|
29
|
+
"1m" : 1.48779296875,
|
30
|
+
"15m" : 0.10888671875
|
31
|
+
},
|
32
|
+
"filesystem" : [
|
33
|
+
{
|
34
|
+
"total" : 16718393344,
|
35
|
+
"used" : 3104915456,
|
36
|
+
"name" : "/var/lib/docker",
|
37
|
+
"free" : 13613477888,
|
38
|
+
"available" : 12730281984
|
39
|
+
}
|
40
|
+
]
|
41
|
+
},
|
42
|
+
"overlay_ip" : "10.81.0.1",
|
43
|
+
"labels" : [
|
44
|
+
"test"
|
45
|
+
],
|
46
|
+
"engine_root_dir" : "/var/lib/docker",
|
47
|
+
"cpus" : 1,
|
48
|
+
"os" : "Container Linux by CoreOS 1409.5.0 (Ladybug)",
|
49
|
+
"public_ip" : "91.150.10.190",
|
50
|
+
"kernel_version" : "4.11.6-coreos-r1",
|
51
|
+
"node_id" : "XI4K:NPOL:EQJ4:S4V7:EN3B:DHC5:KZJD:F3U2:PCAN:46EV:IO4A:63S5",
|
52
|
+
"created_at" : "2016-10-27T08:15:31.084Z",
|
53
|
+
"id" : "development/core-01",
|
54
|
+
"name" : "core-01",
|
55
|
+
"network_drivers" : [
|
56
|
+
{
|
57
|
+
"version" : null,
|
58
|
+
"name" : "bridge"
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"version" : null,
|
62
|
+
"name" : "host"
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"version" : null,
|
66
|
+
"name" : "overlay"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"name" : "null",
|
70
|
+
"version" : null
|
71
|
+
}
|
72
|
+
],
|
73
|
+
"driver" : "overlay",
|
74
|
+
"mem_limit" : 0,
|
75
|
+
"docker_version" : "1.12.6",
|
76
|
+
"agent_version" : "1.4.0.dev",
|
77
|
+
"private_ip" : "192.168.66.101",
|
78
|
+
"connected_at" : "2017-07-04T08:36:02.235Z",
|
79
|
+
"grid" : {
|
80
|
+
"supernet" : "10.80.0.0/12",
|
81
|
+
"trusted_subnets" : [],
|
82
|
+
"stats" : {
|
83
|
+
"statsd" : null
|
84
|
+
},
|
85
|
+
"token" : "tBsoco4sBClMtIOD/bHeIqS1KYM0kZMG7B960jNWWQXMOxqhOf8W1QgiNJlW9u6B/qS+rfS2ZLpC/ZJsyPNj0A==",
|
86
|
+
"id" : "development",
|
87
|
+
"name" : "development",
|
88
|
+
"subnet" : "10.81.0.0/16",
|
89
|
+
"initial_size" : 1
|
90
|
+
},
|
91
|
+
"mem_total" : 1045032960,
|
92
|
+
"connected" : true
|
93
|
+
}
|
@@ -27,10 +27,6 @@ describe Kontena::Cli::Containers::LogsCommand do
|
|
27
27
|
]
|
28
28
|
end
|
29
29
|
|
30
|
-
before(:each) do
|
31
|
-
Kontena.pastel.resolver.color.disable!
|
32
|
-
end
|
33
|
-
|
34
30
|
it "shows all logs" do
|
35
31
|
allow(client).to receive(:get).with('containers/test-grid/node-1/test-mysql-1/logs', {
|
36
32
|
limit: 100,
|
@@ -8,82 +8,147 @@ describe Kontena::Cli::Etcd::HealthCommand do
|
|
8
8
|
allow(subject).to receive(:health_icon) {|health| health.inspect }
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
let :node1_health do
|
12
|
+
{
|
13
|
+
"id" => 'test-grid/node-1',
|
14
|
+
"connected" => false,
|
15
|
+
"name" => "node-1",
|
16
|
+
'etcd_health' => {
|
17
|
+
'health' => nil,
|
18
|
+
'error' => nil,
|
19
|
+
},
|
20
|
+
}
|
21
|
+
end
|
22
|
+
let :node2_health do
|
23
|
+
{
|
24
|
+
"id" => 'test-grid/node-2',
|
25
|
+
"name" => "node-2",
|
26
|
+
"connected" => true,
|
27
|
+
'etcd_health' => {
|
28
|
+
'health' => nil,
|
29
|
+
'error' => "timeout",
|
30
|
+
},
|
31
|
+
}
|
32
|
+
end
|
33
|
+
let :node3_health do
|
34
|
+
{
|
35
|
+
"id" => 'test-grid/node-3',
|
36
|
+
"name" => "node-3",
|
37
|
+
"connected" => true,
|
38
|
+
'etcd_health' => {
|
39
|
+
'health' => false,
|
40
|
+
'error' => nil,
|
41
|
+
},
|
42
|
+
}
|
43
|
+
end
|
44
|
+
let :node4_health do
|
45
|
+
{
|
46
|
+
"id" => 'test-grid/node-4',
|
47
|
+
"name" => "node-4",
|
48
|
+
"connected" => true,
|
49
|
+
'etcd_health' => {
|
50
|
+
'health' => true,
|
51
|
+
'error' => nil,
|
52
|
+
},
|
53
|
+
}
|
54
|
+
end
|
23
55
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
56
|
+
before do
|
57
|
+
allow(client).to receive(:get).with('nodes/test-grid/node-1/health').and_return(node1_health)
|
58
|
+
allow(client).to receive(:get).with('nodes/test-grid/node-2/health').and_return(node2_health)
|
59
|
+
allow(client).to receive(:get).with('nodes/test-grid/node-3/health').and_return(node3_health)
|
60
|
+
allow(client).to receive(:get).with('nodes/test-grid/node-4/health').and_return(node4_health)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "For an offline node-1" do
|
64
|
+
it "shows offline and returns false" do
|
65
|
+
expect{subject.run(['node-1'])}.to exit_with_error.and output_lines [
|
66
|
+
":offline Node node-1 is offline",
|
67
|
+
]
|
29
68
|
end
|
69
|
+
end
|
30
70
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
71
|
+
context "For a node-2 with health errors" do
|
72
|
+
it "shows errored and returns false" do
|
73
|
+
expect{subject.run(['node-2'])}.to exit_with_error.and output_lines [
|
74
|
+
":error Node node-2 is unhealthy: timeout",
|
75
|
+
]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "For a node-3 that returns health=false" do
|
80
|
+
it "shows unhealthy and returns false" do
|
81
|
+
expect{subject.run(['node-3'])}.to exit_with_error.and output_lines [
|
82
|
+
":error Node node-3 is unhealthy",
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
42
86
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
87
|
+
context "For a healthy node-4" do
|
88
|
+
it "shows healthy and returns true" do
|
89
|
+
expect{subject.run(['node-4'])}.to output_lines [
|
90
|
+
":ok Node node-4 is healthy",
|
91
|
+
]
|
48
92
|
end
|
93
|
+
end
|
49
94
|
|
50
|
-
|
51
|
-
|
95
|
+
context "For a grid of mixed nodes" do
|
96
|
+
let :grid_nodes do
|
97
|
+
[
|
98
|
+
{
|
99
|
+
'id' => 'test-grid/node-1',
|
100
|
+
},
|
52
101
|
{
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
102
|
+
'id' => 'test-grid/node-2',
|
103
|
+
},
|
104
|
+
{
|
105
|
+
'id' => 'test-grid/node-3',
|
106
|
+
},
|
107
|
+
{
|
108
|
+
'id' => 'test-grid/node-4',
|
109
|
+
},
|
110
|
+
]
|
111
|
+
end
|
61
112
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
113
|
+
before do
|
114
|
+
allow(client).to receive(:get).with('grids/test-grid/nodes').and_return(
|
115
|
+
'nodes' => grid_nodes,
|
116
|
+
)
|
67
117
|
end
|
68
118
|
|
69
|
-
|
70
|
-
|
119
|
+
it 'shows all nodes and exits with an error' do
|
120
|
+
expect{subject.run([])}.to exit_with_error.and output_lines [
|
121
|
+
":offline Node node-1 is offline",
|
122
|
+
":error Node node-2 is unhealthy: timeout",
|
123
|
+
":error Node node-3 is unhealthy",
|
124
|
+
":ok Node node-4 is healthy",
|
125
|
+
]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'for a grid with healthy nodes' do
|
130
|
+
let :grid_nodes do
|
131
|
+
[
|
71
132
|
{
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
133
|
+
'id' => 'test-grid/node-4',
|
134
|
+
},
|
135
|
+
{
|
136
|
+
'id' => 'test-grid/node-4',
|
137
|
+
},
|
138
|
+
]
|
139
|
+
end
|
80
140
|
|
141
|
+
before do
|
142
|
+
allow(client).to receive(:get).with('grids/test-grid/nodes').and_return(
|
143
|
+
'nodes' => grid_nodes,
|
144
|
+
)
|
145
|
+
end
|
81
146
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
147
|
+
it 'shows nodes as healthy anddoes not and exit with an error' do
|
148
|
+
expect{subject.run([])}.to output_lines [
|
149
|
+
":ok Node node-4 is healthy",
|
150
|
+
":ok Node node-4 is healthy",
|
151
|
+
]
|
87
152
|
end
|
88
153
|
end
|
89
154
|
end
|