sshkit 0.0.6 → 0.0.7
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.
- data/CHANGELOG.md +26 -0
- data/EXAMPLES.md +25 -9
- data/lib/sshkit.rb +4 -3
- data/lib/sshkit/backends/abstract.rb +7 -2
- data/lib/sshkit/backends/netssh.rb +5 -0
- data/lib/sshkit/command.rb +10 -1
- data/lib/sshkit/host.rb +1 -1
- data/lib/sshkit/runners/parallel.rb +2 -0
- data/lib/sshkit/version.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/integration/backends/test_netssh.rb +17 -19
- data/test/unit/test_command.rb +11 -3
- metadata +1 -1
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,32 @@
|
|
3
3
|
This file is written in reverse chronological order, newer releases will
|
4
4
|
appear at the top.
|
5
5
|
|
6
|
+
## 0.0.7
|
7
|
+
|
8
|
+
* DSL method `execute()` will now raise `SSHKit::Command::Failed` when the
|
9
|
+
exit status is non-zero. The message of the exception will be whatever the
|
10
|
+
process had written to stdout.
|
11
|
+
* New DSL method `test()` behaves as `execute()` used to until this version.
|
12
|
+
* `Command` now raises an error in `#exit_status=()` if the exit status given
|
13
|
+
is not zero. (see below)
|
14
|
+
* All errors raised by error conditions of SSHKit are defined as subclasses of
|
15
|
+
`SSHKit::StandardError` which is itself a subclass of `StandardError`.
|
16
|
+
|
17
|
+
The `Command` objects can be set to not raise, by passing `raise_on_non_zero_exit: false`
|
18
|
+
when instantiating them, this is exactly what `test()` does internally.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
|
22
|
+
on hosts do |host
|
23
|
+
if test "[ -d /opt/sites ]" do
|
24
|
+
within "/opt/sites" do
|
25
|
+
execute :git, :pull
|
26
|
+
end
|
27
|
+
else
|
28
|
+
execute :git, :clone, 'some-repository', '/opt/sites'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
6
32
|
## 0.0.6
|
7
33
|
|
8
34
|
* Support arbitrary properties on Host objects. (see below)
|
data/EXAMPLES.md
CHANGED
@@ -43,7 +43,7 @@ This will output:
|
|
43
43
|
**Note:** This example is a bit misleading, as the `www-data` user doesn't
|
44
44
|
have a shell defined, one cannot switch to that user.
|
45
45
|
|
46
|
-
## Stack directory nestings
|
46
|
+
## Stack directory nestings
|
47
47
|
|
48
48
|
on hosts do
|
49
49
|
in "/var" do
|
@@ -65,7 +65,7 @@ leading slashes. It may be misleading as the `File.join()` is performed on the
|
|
65
65
|
machine running the code, if that's a Windows box, the paths may be incorrectly
|
66
66
|
joined according to the expectations of the machine receiving the commands.
|
67
67
|
|
68
|
-
## Do not care about the host block
|
68
|
+
## Do not care about the host block
|
69
69
|
|
70
70
|
on hosts do
|
71
71
|
# The |host| argument is optional, it will
|
@@ -76,7 +76,7 @@ joined according to the expectations of the machine receiving the commands.
|
|
76
76
|
|
77
77
|
SSHKit.config.output = File.open('/dev/null')
|
78
78
|
|
79
|
-
## Implement a dirt-simple formatter class
|
79
|
+
## Implement a dirt-simple formatter class
|
80
80
|
|
81
81
|
class MyFormatter < SSHKit::Formatter::Abstract
|
82
82
|
def write(obj)
|
@@ -99,16 +99,32 @@ joined according to the expectations of the machine receiving the commands.
|
|
99
99
|
puts capture(:echo, "I don't care about security!")
|
100
100
|
end
|
101
101
|
|
102
|
-
## Execute and raise an error if something goes wrong
|
102
|
+
## Execute and raise an error if something goes wrong
|
103
103
|
|
104
104
|
on hosts do |host|
|
105
105
|
execute!(:echo, '"Example Message!" 1>&2; false')
|
106
106
|
end
|
107
107
|
|
108
|
-
This will raise `SSHKit::
|
109
|
-
will cause the command to abort.
|
108
|
+
This will raise `SSHKit::Command:Failed` with the `#message` "Example Message!"`
|
109
|
+
which will cause the command to abort.
|
110
110
|
|
111
|
-
##
|
111
|
+
## Make a test, or run a command which may fail without raising an error:
|
112
|
+
|
113
|
+
on hosts do |host
|
114
|
+
if test "[ -d /opt/sites ]" do
|
115
|
+
within "/opt/sites" do
|
116
|
+
execute :git, :pull
|
117
|
+
end
|
118
|
+
else
|
119
|
+
execute :git, :clone, 'some-repository', '/opt/sites'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
The `test()` command behaves exactly the same as execute however will return
|
124
|
+
false if the command exits with a non-zero exit (as `man 1 test` does). As ti
|
125
|
+
returns boolean it can be used to direct the control flow within the block.
|
126
|
+
|
127
|
+
## Do something different on one host, or another depending on a host property
|
112
128
|
|
113
129
|
host1 = SSHKit::Host.new 'user@example.com'
|
114
130
|
host2 = SSHKit::Host.new 'user@example.org'
|
@@ -123,7 +139,7 @@ will cause the command to abort.
|
|
123
139
|
execute! :git, :clone, "git@git.#{host.hostname}", target
|
124
140
|
end
|
125
141
|
|
126
|
-
## Connect to a host in the easiest possible way
|
142
|
+
## Connect to a host in the easiest possible way
|
127
143
|
|
128
144
|
on 'example.com' do |host|
|
129
145
|
execute :uptime
|
@@ -133,7 +149,7 @@ This will resolve the `example.com` hostname into a `SSHKit::Host` object, and
|
|
133
149
|
try to pull up the correct configuration for it.
|
134
150
|
|
135
151
|
|
136
|
-
## Run a command without it being command-mapped
|
152
|
+
## Run a command without it being command-mapped
|
137
153
|
|
138
154
|
If the command you attempt to call contains a space character it won't be
|
139
155
|
mapped:
|
data/lib/sshkit.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module SSHKit
|
2
2
|
module Backend
|
3
3
|
|
4
|
-
MethodUnavailableError = Class.new(
|
4
|
+
MethodUnavailableError = Class.new(SSHKit::StandardError)
|
5
5
|
|
6
6
|
class Abstract
|
7
7
|
|
@@ -25,6 +25,10 @@ module SSHKit
|
|
25
25
|
raise MethodUnavailableError
|
26
26
|
end
|
27
27
|
|
28
|
+
def test(command, args=[])
|
29
|
+
raise MethodUnavailableError
|
30
|
+
end
|
31
|
+
|
28
32
|
def execute(command, args=[])
|
29
33
|
raise MethodUnavailableError
|
30
34
|
end
|
@@ -71,7 +75,8 @@ module SSHKit
|
|
71
75
|
private
|
72
76
|
|
73
77
|
def command(*args)
|
74
|
-
|
78
|
+
options = args.extract_options!
|
79
|
+
SSHKit::Command.new(*[*args, options.merge({in: @pwd.nil? ? nil : File.join(@pwd), env: @env, host: @host, user: @user})])
|
75
80
|
end
|
76
81
|
|
77
82
|
def connection
|
@@ -11,6 +11,11 @@ module SSHKit
|
|
11
11
|
instance_exec(host, &@block)
|
12
12
|
end
|
13
13
|
|
14
|
+
def test(*args)
|
15
|
+
options = args.extract_options!.merge(raise_on_non_zero_exit: false)
|
16
|
+
_execute(*[*args, options]).success?
|
17
|
+
end
|
18
|
+
|
14
19
|
def execute(*args)
|
15
20
|
_execute(*args).success?
|
16
21
|
end
|
data/lib/sshkit/command.rb
CHANGED
@@ -31,6 +31,8 @@ module SSHKit
|
|
31
31
|
# @author Lee Hambley
|
32
32
|
class Command
|
33
33
|
|
34
|
+
Failed = Class.new(SSHKit::StandardError)
|
35
|
+
|
34
36
|
attr_reader :command, :args, :options, :started_at, :started, :exit_status
|
35
37
|
|
36
38
|
attr_accessor :stdout, :stderr
|
@@ -44,7 +46,7 @@ module SSHKit
|
|
44
46
|
#
|
45
47
|
def initialize(*args)
|
46
48
|
raise ArgumentError, "May not pass no arguments to Command.new" if args.empty?
|
47
|
-
@options = args.extract_options!
|
49
|
+
@options = default_options.merge(args.extract_options!)
|
48
50
|
@command = args.shift.to_s.strip.to_sym
|
49
51
|
@args = args
|
50
52
|
@options.symbolize_keys!
|
@@ -83,6 +85,9 @@ module SSHKit
|
|
83
85
|
def exit_status=(new_exit_status)
|
84
86
|
@finished_at = Time.now
|
85
87
|
@exit_status = new_exit_status
|
88
|
+
if options[:raise_on_non_zero_exit] && exit_status > 0
|
89
|
+
raise Failed, stderr.empty? ? "No messages written to stderr" : stderr.strip
|
90
|
+
end
|
86
91
|
end
|
87
92
|
|
88
93
|
def runtime
|
@@ -136,6 +141,10 @@ module SSHKit
|
|
136
141
|
|
137
142
|
private
|
138
143
|
|
144
|
+
def default_options
|
145
|
+
{ raise_on_non_zero_exit: true }
|
146
|
+
end
|
147
|
+
|
139
148
|
def sanitize_command!
|
140
149
|
command.to_s.strip!
|
141
150
|
if command.to_s.match("\n")
|
data/lib/sshkit/host.rb
CHANGED
data/lib/sshkit/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -17,7 +17,12 @@ module SSHKit
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
class
|
20
|
+
class TestNetssh < FunctionalTest
|
21
|
+
|
22
|
+
def setup
|
23
|
+
super
|
24
|
+
SSHKit.config.output = SSHKit::Formatter::BlackHole.new($stdout)
|
25
|
+
end
|
21
26
|
|
22
27
|
def block_to_run
|
23
28
|
lambda do |host|
|
@@ -70,26 +75,19 @@ module SSHKit
|
|
70
75
|
end
|
71
76
|
end
|
72
77
|
|
73
|
-
def
|
74
|
-
|
78
|
+
def test_execute_raises_on_non_zero_exit_status_and_captures_stderr
|
79
|
+
err = assert_raises SSHKit::Command::Failed do
|
80
|
+
Netssh.new(a_host) do |host|
|
81
|
+
execute :echo, "'Test capturing stderr' 1>&2; false"
|
82
|
+
end.run
|
83
|
+
end
|
84
|
+
assert_equal "Test capturing stderr", err.message
|
75
85
|
end
|
76
86
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
# be passed to command (raise_errors: false), which could also be
|
82
|
-
# inherited through Backend#command and specified on the (not yet
|
83
|
-
# existing) backend configurations.
|
84
|
-
assert_raises RuntimeError do
|
85
|
-
File.open('/dev/null', 'w') do |dnull|
|
86
|
-
SSHKit.capture_output(dnull) do
|
87
|
-
Netssh.new(a_host) do |host|
|
88
|
-
execute :false
|
89
|
-
end.run
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
87
|
+
def test_test_does_not_raise_on_non_zero_exit_status
|
88
|
+
Netssh.new(a_host) do |host|
|
89
|
+
test :false
|
90
|
+
end.run
|
93
91
|
end
|
94
92
|
|
95
93
|
end
|
data/test/unit/test_command.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'sshkit'
|
2
3
|
|
3
4
|
module SSHKit
|
4
5
|
class TestCommand < UnitTest
|
@@ -51,7 +52,7 @@ module SSHKit
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def test_complete?
|
54
|
-
c = Command.new(:whoami)
|
55
|
+
c = Command.new(:whoami, raise_on_non_zero_exit: false)
|
55
56
|
refute c.complete?
|
56
57
|
c.exit_status = 1
|
57
58
|
assert c.complete?
|
@@ -69,7 +70,7 @@ module SSHKit
|
|
69
70
|
end
|
70
71
|
|
71
72
|
def test_failure?
|
72
|
-
c = Command.new(:whoami)
|
73
|
+
c = Command.new(:whoami, raise_on_non_zero_exit: false)
|
73
74
|
refute c.failure?
|
74
75
|
refute c.failed?
|
75
76
|
c.exit_status = 1
|
@@ -93,7 +94,7 @@ module SSHKit
|
|
93
94
|
end
|
94
95
|
|
95
96
|
def test_setting_exit_status
|
96
|
-
c = Command.new(:whoami)
|
97
|
+
c = Command.new(:whoami, raise_on_non_zero_exit: false)
|
97
98
|
assert_equal nil, c.exit_status
|
98
99
|
assert c.exit_status = 1
|
99
100
|
assert_equal 1, c.exit_status
|
@@ -109,5 +110,12 @@ module SSHKit
|
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
113
|
+
def test_command_raises_command_failed_error_when_non_zero_exit
|
114
|
+
error = assert_raises SSHKit::Command::Failed do
|
115
|
+
Command.new(:whoami).exit_status = 1
|
116
|
+
end
|
117
|
+
assert_equal "No messages written to stderr", error.message
|
118
|
+
end
|
119
|
+
|
112
120
|
end
|
113
121
|
end
|