sshkit 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/BREAKING_API_WISHLIST.md +14 -0
- data/CHANGELOG.md +74 -0
- data/CONTRIBUTING.md +43 -0
- data/EXAMPLES.md +265 -169
- data/Gemfile +7 -0
- data/README.md +274 -9
- data/RELEASING.md +16 -8
- data/Rakefile +8 -0
- data/lib/sshkit.rb +0 -9
- data/lib/sshkit/all.rb +6 -4
- data/lib/sshkit/backends/abstract.rb +42 -42
- data/lib/sshkit/backends/connection_pool.rb +57 -8
- data/lib/sshkit/backends/local.rb +21 -50
- data/lib/sshkit/backends/netssh.rb +45 -98
- data/lib/sshkit/backends/printer.rb +3 -23
- data/lib/sshkit/backends/skipper.rb +4 -8
- data/lib/sshkit/color.rb +51 -20
- data/lib/sshkit/command.rb +68 -47
- data/lib/sshkit/configuration.rb +38 -5
- data/lib/sshkit/deprecation_logger.rb +17 -0
- data/lib/sshkit/formatters/abstract.rb +28 -4
- data/lib/sshkit/formatters/black_hole.rb +1 -2
- data/lib/sshkit/formatters/dot.rb +3 -10
- data/lib/sshkit/formatters/pretty.rb +31 -56
- data/lib/sshkit/formatters/simple_text.rb +6 -44
- data/lib/sshkit/host.rb +5 -6
- data/lib/sshkit/logger.rb +0 -1
- data/lib/sshkit/mapping_interaction_handler.rb +47 -0
- data/lib/sshkit/runners/parallel.rb +1 -1
- data/lib/sshkit/runners/sequential.rb +1 -1
- data/lib/sshkit/version.rb +1 -1
- data/sshkit.gemspec +0 -1
- data/test/functional/backends/test_local.rb +14 -1
- data/test/functional/backends/test_netssh.rb +58 -50
- data/test/helper.rb +2 -2
- data/test/unit/backends/test_abstract.rb +145 -0
- data/test/unit/backends/test_connection_pool.rb +27 -2
- data/test/unit/backends/test_printer.rb +47 -47
- data/test/unit/formatters/test_custom.rb +65 -0
- data/test/unit/formatters/test_dot.rb +25 -32
- data/test/unit/formatters/test_pretty.rb +114 -22
- data/test/unit/formatters/test_simple_text.rb +83 -0
- data/test/unit/test_color.rb +69 -5
- data/test/unit/test_command.rb +53 -18
- data/test/unit/test_command_map.rb +0 -4
- data/test/unit/test_configuration.rb +47 -7
- data/test/unit/test_coordinator.rb +45 -52
- data/test/unit/test_deprecation_logger.rb +38 -0
- data/test/unit/test_host.rb +3 -4
- data/test/unit/test_logger.rb +0 -1
- data/test/unit/test_mapping_interaction_handler.rb +101 -0
- metadata +37 -41
- data/lib/sshkit/utils/capture_output_methods.rb +0 -13
- data/test/functional/test_coordinator.rb +0 -17
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module SSHKit
|
4
|
+
class TestSimpleText < UnitTest
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
SSHKit.config.output_verbosity = Logger::DEBUG
|
9
|
+
end
|
10
|
+
|
11
|
+
def output
|
12
|
+
@output ||= String.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def simple
|
16
|
+
@simple ||= SSHKit::Formatter::SimpleText.new(output)
|
17
|
+
end
|
18
|
+
|
19
|
+
%w(fatal error warn info debug).each do |level|
|
20
|
+
define_method("test_#{level}_output") do
|
21
|
+
simple.send(level, 'Test')
|
22
|
+
assert_log_output "Test\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_logging_message_with_leading_and_trailing_space
|
27
|
+
simple.log(" some spaces\n\n \t")
|
28
|
+
assert_log_output "some spaces\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_can_log_non_strings
|
32
|
+
simple.log(Pathname.new('/var/log/my.log'))
|
33
|
+
assert_log_output "/var/log/my.log\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_command_lifecycle_logging
|
37
|
+
command = SSHKit::Command.new(:a_cmd, 'some args', host: Host.new('user@localhost'))
|
38
|
+
command.stubs(:uuid).returns('aaaaaa')
|
39
|
+
command.stubs(:runtime).returns(1)
|
40
|
+
|
41
|
+
simple.log_command_start(command)
|
42
|
+
command.started = true
|
43
|
+
command.on_stdout(nil, 'stdout message')
|
44
|
+
simple.log_command_data(command, :stdout, 'stdout message')
|
45
|
+
command.on_stderr(nil, 'stderr message')
|
46
|
+
simple.log_command_data(command, :stderr, 'stderr message')
|
47
|
+
command.exit_status = 0
|
48
|
+
simple.log_command_exit(command)
|
49
|
+
|
50
|
+
expected_log_lines = [
|
51
|
+
'Running /usr/bin/env a_cmd some args as user@localhost',
|
52
|
+
'Command: /usr/bin/env a_cmd some args',
|
53
|
+
"\tstdout message",
|
54
|
+
"\tstderr message",
|
55
|
+
'Finished in 1.000 seconds with exit status 0 (successful).'
|
56
|
+
]
|
57
|
+
assert_equal expected_log_lines, output.split("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_unsupported_class
|
61
|
+
raised_error = assert_raises RuntimeError do
|
62
|
+
simple << Pathname.new('/tmp')
|
63
|
+
end
|
64
|
+
assert_equal('write only supports formatting SSHKit::LogMessage, called with Pathname: #<Pathname:/tmp>', raised_error.message)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_does_not_log_when_verbosity_is_too_low
|
68
|
+
SSHKit.config.output_verbosity = Logger::WARN
|
69
|
+
simple.info('Some info')
|
70
|
+
assert_log_output('')
|
71
|
+
|
72
|
+
SSHKit.config.output_verbosity = Logger::INFO
|
73
|
+
simple.info('Some other info')
|
74
|
+
assert_log_output("Some other info\n")
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def assert_log_output(expected_output)
|
80
|
+
assert_equal expected_output, output
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/test/unit/test_color.rb
CHANGED
@@ -4,13 +4,77 @@ require 'sshkit'
|
|
4
4
|
module SSHKit
|
5
5
|
class TestColor < UnitTest
|
6
6
|
|
7
|
-
def
|
8
|
-
|
7
|
+
def test_colorize_when_tty_available
|
8
|
+
color = SSHKit::Color.new(stub(tty?: true), {})
|
9
|
+
assert_equal "\e[1;32;49mhi\e[0m", color.colorize('hi', :green, :bold)
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
-
Color.
|
13
|
-
assert_equal
|
12
|
+
def test_colorize_when_SSHKIT_COLOR_present
|
13
|
+
color = SSHKit::Color.new(stub(tty?: false), {'SSHKIT_COLOR' => 'a'})
|
14
|
+
assert_equal "\e[0;31;49mhi\e[0m", color.colorize('hi', :red)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_does_not_colorize_when_no_tty_and_SSHKIT_COLOR_not_present
|
18
|
+
color = SSHKit::Color.new(stub(tty?: false), {})
|
19
|
+
assert_equal 'hi', color.colorize('hi', :red)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The output parameter may not define the tty method eg if it is a Logger.
|
23
|
+
# In this case we assume showing colors would not be supported
|
24
|
+
# https://github.com/capistrano/sshkit/pull/246#issuecomment-100358122
|
25
|
+
def test_does_not_colorize_when_tty_method_not_defined_and_SSHKIT_COLOR_not_present
|
26
|
+
color = SSHKit::Color.new(stub(), {})
|
27
|
+
assert_equal 'hi', color.colorize('hi', :red)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_colorize_colors
|
31
|
+
color = SSHKit::Color.new(stub(tty?: true), {})
|
32
|
+
assert_equal "\e[0;30;49mhi\e[0m", color.colorize('hi', :black)
|
33
|
+
assert_equal "\e[0;31;49mhi\e[0m", color.colorize('hi', :red)
|
34
|
+
assert_equal "\e[0;32;49mhi\e[0m", color.colorize('hi', :green)
|
35
|
+
assert_equal "\e[0;33;49mhi\e[0m", color.colorize('hi', :yellow)
|
36
|
+
assert_equal "\e[0;34;49mhi\e[0m", color.colorize('hi', :blue)
|
37
|
+
assert_equal "\e[0;35;49mhi\e[0m", color.colorize('hi', :magenta)
|
38
|
+
assert_equal "\e[0;36;49mhi\e[0m", color.colorize('hi', :cyan)
|
39
|
+
assert_equal "\e[0;37;49mhi\e[0m", color.colorize('hi', :white)
|
40
|
+
assert_equal "\e[0;90;49mhi\e[0m", color.colorize('hi', :light_black)
|
41
|
+
assert_equal "\e[0;91;49mhi\e[0m", color.colorize('hi', :light_red)
|
42
|
+
assert_equal "\e[0;92;49mhi\e[0m", color.colorize('hi', :light_green)
|
43
|
+
assert_equal "\e[0;93;49mhi\e[0m", color.colorize('hi', :light_yellow)
|
44
|
+
assert_equal "\e[0;94;49mhi\e[0m", color.colorize('hi', :light_blue)
|
45
|
+
assert_equal "\e[0;95;49mhi\e[0m", color.colorize('hi', :light_magenta)
|
46
|
+
assert_equal "\e[0;96;49mhi\e[0m", color.colorize('hi', :light_cyan)
|
47
|
+
assert_equal "\e[0;97;49mhi\e[0m", color.colorize('hi', :light_white)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_colorize_bold_colors
|
51
|
+
color = SSHKit::Color.new(stub(tty?: true), {})
|
52
|
+
assert_equal "\e[1;30;49mhi\e[0m", color.colorize('hi', :black, :bold)
|
53
|
+
assert_equal "\e[1;31;49mhi\e[0m", color.colorize('hi', :red, :bold)
|
54
|
+
assert_equal "\e[1;32;49mhi\e[0m", color.colorize('hi', :green, :bold)
|
55
|
+
assert_equal "\e[1;33;49mhi\e[0m", color.colorize('hi', :yellow, :bold)
|
56
|
+
assert_equal "\e[1;34;49mhi\e[0m", color.colorize('hi', :blue, :bold)
|
57
|
+
assert_equal "\e[1;35;49mhi\e[0m", color.colorize('hi', :magenta, :bold)
|
58
|
+
assert_equal "\e[1;36;49mhi\e[0m", color.colorize('hi', :cyan, :bold)
|
59
|
+
assert_equal "\e[1;37;49mhi\e[0m", color.colorize('hi', :white, :bold)
|
60
|
+
assert_equal "\e[1;90;49mhi\e[0m", color.colorize('hi', :light_black, :bold)
|
61
|
+
assert_equal "\e[1;91;49mhi\e[0m", color.colorize('hi', :light_red, :bold)
|
62
|
+
assert_equal "\e[1;92;49mhi\e[0m", color.colorize('hi', :light_green, :bold)
|
63
|
+
assert_equal "\e[1;93;49mhi\e[0m", color.colorize('hi', :light_yellow, :bold)
|
64
|
+
assert_equal "\e[1;94;49mhi\e[0m", color.colorize('hi', :light_blue, :bold)
|
65
|
+
assert_equal "\e[1;95;49mhi\e[0m", color.colorize('hi', :light_magenta, :bold)
|
66
|
+
assert_equal "\e[1;96;49mhi\e[0m", color.colorize('hi', :light_cyan, :bold)
|
67
|
+
assert_equal "\e[1;97;49mhi\e[0m", color.colorize('hi', :light_white, :bold)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_ignores_unrecognized_color
|
71
|
+
color = SSHKit::Color.new(stub(tty?: true), {})
|
72
|
+
assert_equal 'hi', color.colorize('hi', :tangerine)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_ignores_unrecognized_mode
|
76
|
+
color = SSHKit::Color.new(stub(tty?: true), {})
|
77
|
+
assert_equal "\e[0;31;49mhi\e[0m", color.colorize('hi', :red, :underline)
|
14
78
|
end
|
15
79
|
end
|
16
80
|
end
|
data/test/unit/test_command.rb
CHANGED
@@ -4,10 +4,6 @@ require 'sshkit'
|
|
4
4
|
module SSHKit
|
5
5
|
class TestCommand < UnitTest
|
6
6
|
|
7
|
-
def setup
|
8
|
-
SSHKit.reset_configuration!
|
9
|
-
end
|
10
|
-
|
11
7
|
def test_maps_a_command
|
12
8
|
c = Command.new('example')
|
13
9
|
assert_equal '/usr/bin/env example', c.to_command
|
@@ -32,38 +28,44 @@ module SSHKit
|
|
32
28
|
def test_including_the_env
|
33
29
|
SSHKit.config = nil
|
34
30
|
c = Command.new(:rails, 'server', env: {rails_env: :production})
|
35
|
-
assert_equal
|
31
|
+
assert_equal %{( export RAILS_ENV="production" ; /usr/bin/env rails server )}, c.to_command
|
36
32
|
end
|
37
33
|
|
38
34
|
def test_including_the_env_with_multiple_keys
|
39
35
|
SSHKit.config = nil
|
40
36
|
c = Command.new(:rails, 'server', env: {rails_env: :production, foo: 'bar'})
|
41
|
-
assert_equal
|
37
|
+
assert_equal %{( export RAILS_ENV="production" FOO="bar" ; /usr/bin/env rails server )}, c.to_command
|
42
38
|
end
|
43
39
|
|
44
40
|
def test_including_the_env_with_string_keys
|
45
41
|
SSHKit.config = nil
|
46
42
|
c = Command.new(:rails, 'server', env: {'FACTER_env' => :production, foo: 'bar'})
|
47
|
-
assert_equal
|
43
|
+
assert_equal %{( export FACTER_env="production" FOO="bar" ; /usr/bin/env rails server )}, c.to_command
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_double_quotes_are_escaped_in_env
|
47
|
+
SSHKit.config = nil
|
48
|
+
c = Command.new(:rails, 'server', env: {foo: 'asdf"hjkl'})
|
49
|
+
assert_equal %{( export FOO="asdf\\\"hjkl" ; /usr/bin/env rails server )}, c.to_command
|
48
50
|
end
|
49
51
|
|
50
52
|
def test_including_the_env_doesnt_addressively_escape
|
51
53
|
SSHKit.config = nil
|
52
54
|
c = Command.new(:rails, 'server', env: {path: '/example:$PATH'})
|
53
|
-
assert_equal
|
55
|
+
assert_equal %{( export PATH="/example:$PATH" ; /usr/bin/env rails server )}, c.to_command
|
54
56
|
end
|
55
57
|
|
56
58
|
def test_global_env
|
57
59
|
SSHKit.config = nil
|
58
60
|
SSHKit.config.default_env = { default: 'env' }
|
59
61
|
c = Command.new(:rails, 'server', env: {})
|
60
|
-
assert_equal
|
62
|
+
assert_equal %{( export DEFAULT="env" ; /usr/bin/env rails server )}, c.to_command
|
61
63
|
end
|
62
64
|
|
63
65
|
def test_default_env_is_overwritten_with_locally_defined
|
64
66
|
SSHKit.config.default_env = { foo: 'bar', over: 'under' }
|
65
67
|
c = Command.new(:rails, 'server', env: { over: 'write'})
|
66
|
-
assert_equal
|
68
|
+
assert_equal %{( export FOO="bar" OVER="write" ; /usr/bin/env rails server )}, c.to_command
|
67
69
|
end
|
68
70
|
|
69
71
|
def test_working_in_a_given_directory
|
@@ -73,7 +75,7 @@ module SSHKit
|
|
73
75
|
|
74
76
|
def test_working_in_a_given_directory_with_env
|
75
77
|
c = Command.new(:ls, '-l', in: "/opt/sites", env: {a: :b})
|
76
|
-
assert_equal
|
78
|
+
assert_equal %{cd /opt/sites && ( export A="b" ; /usr/bin/env ls -l )}, c.to_command
|
77
79
|
end
|
78
80
|
|
79
81
|
def test_having_a_host_passed
|
@@ -118,7 +120,7 @@ module SSHKit
|
|
118
120
|
def test_umask_with_env_and_working_directory_and_user
|
119
121
|
SSHKit.config.umask = '007'
|
120
122
|
c = Command.new(:touch, 'somefile', user: 'bob', env: {a: 'b'}, in: '/var')
|
121
|
-
assert_equal
|
123
|
+
assert_equal %{cd /var && umask 007 && ( export A="b" ; sudo -u bob A="b" -- sh -c '/usr/bin/env touch somefile' )}, c.to_command
|
122
124
|
end
|
123
125
|
|
124
126
|
def test_verbosity_defaults_to_logger_info
|
@@ -163,16 +165,49 @@ module SSHKit
|
|
163
165
|
assert c.failed?
|
164
166
|
end
|
165
167
|
|
166
|
-
def
|
168
|
+
def test_on_stdout
|
167
169
|
c = Command.new(:whoami)
|
168
|
-
|
169
|
-
|
170
|
+
c.on_stdout(nil, "test\n")
|
171
|
+
c.on_stdout(nil, 'test2')
|
172
|
+
c.on_stdout(nil, 'test3')
|
173
|
+
assert_equal "test\ntest2test3", c.full_stdout
|
170
174
|
end
|
171
175
|
|
172
|
-
def
|
176
|
+
def test_on_stderr
|
177
|
+
c = Command.new(:whoami)
|
178
|
+
c.on_stderr(nil, 'test')
|
179
|
+
assert_equal 'test', c.full_stderr
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_deprecated_stdtream_accessors
|
183
|
+
deprecation_out = ''
|
184
|
+
SSHKit.config.deprecation_output = deprecation_out
|
185
|
+
|
173
186
|
c = Command.new(:whoami)
|
174
|
-
|
175
|
-
assert_equal
|
187
|
+
c.stdout='a test'
|
188
|
+
assert_equal('a test', c.stdout)
|
189
|
+
c.stderr='another test'
|
190
|
+
assert_equal('another test', c.stderr)
|
191
|
+
deprecation_lines = deprecation_out.lines.to_a
|
192
|
+
|
193
|
+
assert_equal 8, deprecation_lines.size
|
194
|
+
assert_equal(
|
195
|
+
'[Deprecated] The stdout= method on Command is deprecated. ' +
|
196
|
+
"The @stdout attribute will be removed in a future release.\n",
|
197
|
+
deprecation_lines[0])
|
198
|
+
assert_equal(
|
199
|
+
'[Deprecated] The stdout method on Command is deprecated. ' +
|
200
|
+
"The @stdout attribute will be removed in a future release. Use full_stdout() instead.\n",
|
201
|
+
deprecation_lines[2])
|
202
|
+
|
203
|
+
assert_equal(
|
204
|
+
'[Deprecated] The stderr= method on Command is deprecated. ' +
|
205
|
+
"The @stderr attribute will be removed in a future release.\n",
|
206
|
+
deprecation_lines[4])
|
207
|
+
assert_equal(
|
208
|
+
'[Deprecated] The stderr method on Command is deprecated. ' +
|
209
|
+
"The @stderr attribute will be removed in a future release. Use full_stderr() instead.\n",
|
210
|
+
deprecation_lines[6])
|
176
211
|
end
|
177
212
|
|
178
213
|
def test_setting_exit_status
|
@@ -5,11 +5,27 @@ module SSHKit
|
|
5
5
|
class TestConfiguration < UnitTest
|
6
6
|
|
7
7
|
def setup
|
8
|
-
|
8
|
+
super
|
9
9
|
SSHKit.config.command_map.clear
|
10
10
|
SSHKit.config.output = SSHKit::Formatter::Pretty.new($stdout)
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_deprecation_output
|
14
|
+
output = ''
|
15
|
+
SSHKit.config.deprecation_output = output
|
16
|
+
SSHKit.config.deprecation_logger.log('Test')
|
17
|
+
assert_equal "[Deprecated] Test\n", output.lines.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_default_deprecation_output
|
21
|
+
SSHKit.config.deprecation_logger.log('Test')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_nil_deprecation_output
|
25
|
+
SSHKit.config.deprecation_output = nil
|
26
|
+
SSHKit.config.deprecation_logger.log('Test')
|
27
|
+
end
|
28
|
+
|
13
29
|
def test_output
|
14
30
|
assert SSHKit.config.output.is_a? SSHKit::Formatter::Pretty
|
15
31
|
assert SSHKit.config.output = $stderr
|
@@ -51,14 +67,38 @@ module SSHKit
|
|
51
67
|
assert_equal "/opt/sites/example/current/bin ruby", SSHKit.config.command_map[:ruby]
|
52
68
|
end
|
53
69
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
70
|
+
def test_setting_formatter_types
|
71
|
+
{
|
72
|
+
dot: SSHKit::Formatter::Dot,
|
73
|
+
blackhole: SSHKit::Formatter::BlackHole,
|
74
|
+
simpletext: SSHKit::Formatter::SimpleText,
|
75
|
+
}.each do |format, expected_class|
|
76
|
+
SSHKit.config.format = format
|
77
|
+
assert SSHKit.config.output.is_a? expected_class
|
78
|
+
end
|
57
79
|
end
|
58
80
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
81
|
+
def test_prohibits_unknown_formatter_type_with_exception
|
82
|
+
assert_raises(NameError) do
|
83
|
+
SSHKit.config.format = :doesnotexist
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_options_can_be_provided_to_formatter
|
88
|
+
SSHKit.config.use_format(TestFormatter, :color => false)
|
89
|
+
formatter = SSHKit.config.output
|
90
|
+
assert_instance_of(TestFormatter, formatter)
|
91
|
+
assert_equal($stdout, formatter.output)
|
92
|
+
assert_equal({ :color => false }, formatter.options)
|
93
|
+
end
|
94
|
+
|
95
|
+
class TestFormatter
|
96
|
+
attr_accessor :output, :options
|
97
|
+
|
98
|
+
def initialize(output, options={})
|
99
|
+
@output = output
|
100
|
+
@options = options
|
101
|
+
end
|
62
102
|
end
|
63
103
|
end
|
64
104
|
|
@@ -5,20 +5,16 @@ module SSHKit
|
|
5
5
|
|
6
6
|
class TestCoordinator < UnitTest
|
7
7
|
|
8
|
-
CloseEnough = 0.01; # 10 msec
|
9
|
-
|
10
8
|
def setup
|
11
9
|
super
|
12
|
-
@
|
10
|
+
@output = String.new
|
11
|
+
SSHKit.config.output_verbosity = :debug
|
12
|
+
SSHKit.config.output = SSHKit::Formatter::SimpleText.new(@output)
|
13
13
|
SSHKit.config.backend = SSHKit::Backend::Printer
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
def block_to_run
|
21
|
-
lambda do |host|
|
16
|
+
def echo_time
|
17
|
+
lambda do |_host|
|
22
18
|
execute "echo #{Time.now.to_f}"
|
23
19
|
end
|
24
20
|
end
|
@@ -42,69 +38,66 @@ module SSHKit
|
|
42
38
|
end
|
43
39
|
|
44
40
|
def test_the_connection_manager_yields_the_host_to_each_connection_instance
|
45
|
-
|
41
|
+
Coordinator.new(%w{1.example.com}).each do |host|
|
46
42
|
execute "echo #{host.hostname}"
|
47
43
|
end
|
48
|
-
|
49
|
-
SSHKit.capture_output str do
|
50
|
-
Coordinator.new(%w{1.example.com}).each &spy
|
51
|
-
end
|
52
|
-
assert_equal "/usr/bin/env echo 1.example.com", str.strip
|
53
|
-
end
|
44
|
+
assert_equal "Command: echo 1.example.com\n", actual_output_commands.last
|
54
45
|
end
|
55
46
|
|
56
47
|
def test_the_connection_manaager_runs_things_in_parallel_by_default
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
assert_equal 2, results.length
|
61
|
-
assert_in_delta *results, CloseEnough
|
48
|
+
Coordinator.new(%w{1.example.com 2.example.com}).each(&echo_time)
|
49
|
+
assert_equal 2, actual_execution_times.length
|
50
|
+
assert_within_10_ms(actual_execution_times)
|
62
51
|
end
|
63
52
|
|
64
53
|
def test_the_connection_manager_can_run_things_in_sequence
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
assert_equal 2, results.length
|
69
|
-
assert_operator (results.last - results.first), :>, 1.0
|
54
|
+
Coordinator.new(%w{1.example.com 2.example.com}).each in: :sequence, &echo_time
|
55
|
+
assert_equal 2, actual_execution_times.length
|
56
|
+
assert_at_least_1_sec_apart(actual_execution_times.first, actual_execution_times.last)
|
70
57
|
end
|
71
58
|
|
72
59
|
def test_the_connection_manager_can_run_things_in_sequence_with_wait
|
73
60
|
start = Time.now
|
74
|
-
|
75
|
-
Coordinator.new(%w{1.example.com 2.example.com}).each in: :sequence, wait: 10, &block_to_run
|
76
|
-
end
|
61
|
+
Coordinator.new(%w{1.example.com 2.example.com}).each in: :sequence, wait: 10, &echo_time
|
77
62
|
stop = Time.now
|
78
|
-
assert_operator
|
63
|
+
assert_operator(stop - start, :>=, 10.0)
|
79
64
|
end
|
80
65
|
|
81
66
|
def test_the_connection_manager_can_run_things_in_groups
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
assert_operator (results[2] - results[1]), :>, 1.0
|
99
|
-
assert_operator (results[4] - results[3]), :>, 1.0
|
67
|
+
Coordinator.new(
|
68
|
+
%w{
|
69
|
+
1.example.com
|
70
|
+
2.example.com
|
71
|
+
3.example.com
|
72
|
+
4.example.com
|
73
|
+
5.example.com
|
74
|
+
6.example.com
|
75
|
+
}
|
76
|
+
).each in: :groups, &echo_time
|
77
|
+
assert_equal 6, actual_execution_times.length
|
78
|
+
assert_within_10_ms(actual_execution_times[0..1])
|
79
|
+
assert_within_10_ms(actual_execution_times[2..3])
|
80
|
+
assert_within_10_ms(actual_execution_times[4..5])
|
81
|
+
assert_at_least_1_sec_apart(actual_execution_times[1], actual_execution_times[2])
|
82
|
+
assert_at_least_1_sec_apart(actual_execution_times[3], actual_execution_times[4])
|
100
83
|
end
|
101
84
|
|
102
85
|
private
|
103
86
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
87
|
+
def assert_at_least_1_sec_apart(first_time, last_time)
|
88
|
+
assert_operator(last_time - first_time, :>, 1.0)
|
89
|
+
end
|
90
|
+
|
91
|
+
def assert_within_10_ms(array)
|
92
|
+
assert_in_delta(*array, 0.01) # 10 msec
|
93
|
+
end
|
94
|
+
|
95
|
+
def actual_execution_times
|
96
|
+
actual_output_commands.map { |line| line.split(' ').last.to_f }
|
97
|
+
end
|
98
|
+
|
99
|
+
def actual_output_commands
|
100
|
+
@output.lines.select { |line| line.start_with?('Command:') }
|
108
101
|
end
|
109
102
|
|
110
103
|
end
|