sshkit 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +16 -1
- data/EXAMPLES.md +7 -0
- data/README.md +2 -2
- data/Vagrantfile +1 -8
- data/{assets → examples}/images/example_output.png +0 -0
- data/{assets → examples}/images/logo.png +0 -0
- data/lib/sshkit/backends/local.rb +47 -15
- data/lib/sshkit/backends/netssh.rb +4 -4
- data/lib/sshkit/command.rb +2 -4
- data/lib/sshkit/exception.rb +0 -8
- data/lib/sshkit/formatters/pretty.rb +2 -0
- data/lib/sshkit/host.rb +10 -1
- data/lib/sshkit/runners/abstract.rb +5 -1
- data/lib/sshkit/version.rb +1 -1
- data/test/functional/backends/test_netssh.rb +11 -0
- data/test/unit/test_host.rb +9 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbc4c4d5b2ac3c6cfda56f6d7582b6c2e4b0814d
|
4
|
+
data.tar.gz: 6a260d8a28ed5df45fd14de2140aa0de0f6ef577
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e37e0ac83457d83c0c5d41676830097c5ccd6f24ae5cc636533d2c2bb54a2f7706f387ec9af97a458a332a198b90189fd4263ec3411fb07a75db56cd0db25107
|
7
|
+
data.tar.gz: 135cc559ee24611b6f1ccab198445ea7a8efe2df7339c12409e5547a5c3ea0a1ae22d61a640b2a6703b1bb9e7c36af15d1f05fc2103d43d222bcd8fe9a978450
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,11 +3,26 @@
|
|
3
3
|
This file is written in reverse chronological order, newer releases will
|
4
4
|
appear at the top.
|
5
5
|
|
6
|
-
## (Unreleased)
|
6
|
+
## `master` (Unreleased)
|
7
7
|
|
8
8
|
* Add your entries here, remember to credit yourself however you want to be
|
9
9
|
credited!
|
10
10
|
|
11
|
+
## 1.7.0
|
12
|
+
|
13
|
+
* Update Vagrantfile to use multi-provider Hashicorp precise64 box - remove URLs. @townsen
|
14
|
+
* Merge host ssh_options and Netssh defaults @townsen
|
15
|
+
Previously if host-level ssh_options were defined the Netssh defaults
|
16
|
+
were ignored.
|
17
|
+
* Merge host ssh_options and Netssh defaults
|
18
|
+
* Fixed race condition where output of failed command would be empty. @townsen
|
19
|
+
Caused random failures of `test_execute_raises_on_non_zero_exit_status_and_captures_stdout_and_stderr`
|
20
|
+
Also fixes output handling in failed commands, and generally buggy output.
|
21
|
+
* Remove override of backtrace() and backtrace_locations() from ExecuteError. @townsen
|
22
|
+
This interferes with rake default behaviour and creates duplicate stacktraces.
|
23
|
+
* Allow running local commands using `on(:local)`
|
24
|
+
* Implement the upload! and download! methods for the local backend
|
25
|
+
|
11
26
|
## 1.6.0
|
12
27
|
|
13
28
|
* Fix colorize to use the correct API (@fazibear)
|
data/EXAMPLES.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
![SSHKit Logo](https://raw.github.com/leehambley/sshkit/master/
|
1
|
+
![SSHKit Logo](https://raw.github.com/leehambley/sshkit/master/examples/images/logo.png)
|
2
2
|
|
3
3
|
**SSHKit** is a toolkit for running commands in a structured way on one or
|
4
4
|
more servers.
|
@@ -199,7 +199,7 @@ first argument before attempting to find it in the *command map*.
|
|
199
199
|
|
200
200
|
## Output Handling
|
201
201
|
|
202
|
-
![Example Output](https://raw.github.com/leehambley/sshkit/master/
|
202
|
+
![Example Output](https://raw.github.com/leehambley/sshkit/master/examples/images/example_output.png)
|
203
203
|
|
204
204
|
By default, the output format is set to `:pretty`:
|
205
205
|
|
data/Vagrantfile
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
VAGRANTFILE_API_VERSION = "2"
|
2
2
|
|
3
3
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
4
|
-
config.vm.box = 'precise64'
|
5
|
-
config.vm.provider "vmware_fusion" do |vmf|
|
6
|
-
vmf.box_url = "http://files.vagrantup.com/precise64_vmware.box"
|
7
|
-
end
|
8
|
-
config.vm.provider "virtualbox" do |vb|
|
9
|
-
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box"
|
10
|
-
end
|
4
|
+
config.vm.box = 'hashicorp/precise64'
|
11
5
|
|
12
6
|
json_config_path = File.join("test", "boxes.json")
|
13
7
|
list = File.open(json_config_path).read
|
@@ -15,7 +9,6 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
15
9
|
|
16
10
|
list.each do |vm|
|
17
11
|
config.vm.define vm["name"] do |web|
|
18
|
-
web.vm.box = "precise64"
|
19
12
|
web.vm.network "forwarded_port", guest: 22, host: vm["port"]
|
20
13
|
end
|
21
14
|
end
|
File without changes
|
File without changes
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'open3'
|
2
|
+
require 'fileutils'
|
2
3
|
module SSHKit
|
3
4
|
|
4
5
|
module Backend
|
5
6
|
|
6
7
|
class Local < Printer
|
7
8
|
|
8
|
-
def initialize(&block)
|
9
|
-
@host = Host.new(
|
9
|
+
def initialize(_ = nil, &block)
|
10
|
+
@host = Host.new(:local) # just for logging
|
10
11
|
@block = block
|
11
12
|
end
|
12
13
|
|
13
14
|
def run
|
14
|
-
instance_exec(&@block)
|
15
|
+
instance_exec(@host, &@block)
|
15
16
|
end
|
16
17
|
|
17
18
|
def test(*args)
|
@@ -31,6 +32,26 @@ module SSHKit
|
|
31
32
|
_execute(*[*args, options]).full_stdout
|
32
33
|
end
|
33
34
|
|
35
|
+
def upload!(local, remote, options = {})
|
36
|
+
if local.is_a?(String)
|
37
|
+
FileUtils.cp(local, remote)
|
38
|
+
else
|
39
|
+
File.open(remote, "wb") do |f|
|
40
|
+
IO.copy_stream(local, f)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def download!(remote, local=nil, options = {})
|
46
|
+
if local.nil?
|
47
|
+
FileUtils.cp(remote, File.basename(remote))
|
48
|
+
else
|
49
|
+
File.open(remote, "rb") do |f|
|
50
|
+
IO.copy_stream(f, local)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
34
55
|
private
|
35
56
|
|
36
57
|
def _execute(*args)
|
@@ -39,23 +60,34 @@ module SSHKit
|
|
39
60
|
|
40
61
|
cmd.started = Time.now
|
41
62
|
|
42
|
-
stdout, stderr,
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
63
|
+
Open3.popen3(cmd.to_command) do |stdin, stdout, stderr, wait_thr|
|
64
|
+
stdout_thread = Thread.new do
|
65
|
+
while line = stdout.gets do
|
66
|
+
cmd.stdout = line
|
67
|
+
cmd.full_stdout += line
|
68
|
+
|
69
|
+
output << cmd
|
70
|
+
end
|
48
71
|
end
|
49
72
|
|
50
|
-
|
51
|
-
|
73
|
+
stderr_thread = Thread.new do
|
74
|
+
while line = stderr.gets do
|
75
|
+
cmd.stderr = line
|
76
|
+
cmd.full_stderr += line
|
52
77
|
|
53
|
-
|
54
|
-
|
78
|
+
output << cmd
|
79
|
+
end
|
80
|
+
end
|
55
81
|
|
56
|
-
|
82
|
+
stdout_thread.join
|
83
|
+
stderr_thread.join
|
57
84
|
|
58
|
-
|
85
|
+
cmd.exit_status = wait_thr.value.to_i
|
86
|
+
cmd.stdout = ''
|
87
|
+
cmd.stderr = ''
|
88
|
+
|
89
|
+
output << cmd
|
90
|
+
end
|
59
91
|
end
|
60
92
|
end
|
61
93
|
|
@@ -133,6 +133,7 @@ module SSHKit
|
|
133
133
|
command(*args).tap do |cmd|
|
134
134
|
output << cmd
|
135
135
|
cmd.started = true
|
136
|
+
exit_status = nil
|
136
137
|
with_ssh do |ssh|
|
137
138
|
ssh.open_channel do |chan|
|
138
139
|
chan.request_pty if Netssh.config.pty
|
@@ -148,9 +149,7 @@ module SSHKit
|
|
148
149
|
output << cmd
|
149
150
|
end
|
150
151
|
chan.on_request("exit-status") do |ch, data|
|
151
|
-
|
152
|
-
cmd.stderr = ''
|
153
|
-
cmd.exit_status = data.read_long
|
152
|
+
exit_status = data.read_long
|
154
153
|
output << cmd
|
155
154
|
end
|
156
155
|
#chan.on_request("exit-signal") do |ch, data|
|
@@ -176,11 +175,12 @@ module SSHKit
|
|
176
175
|
end
|
177
176
|
ssh.loop
|
178
177
|
end
|
178
|
+
cmd.exit_status = exit_status if exit_status
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
182
|
def with_ssh
|
183
|
-
host.ssh_options
|
183
|
+
host.ssh_options = Netssh.config.ssh_options.merge(host.ssh_options || {})
|
184
184
|
conn = self.class.pool.checkout(
|
185
185
|
String(host.hostname),
|
186
186
|
host.username,
|
data/lib/sshkit/command.rb
CHANGED
@@ -90,10 +90,8 @@ module SSHKit
|
|
90
90
|
if options[:raise_on_non_zero_exit] && exit_status > 0
|
91
91
|
message = ""
|
92
92
|
message += "#{command} exit status: " + exit_status.to_s + "\n"
|
93
|
-
message += "#{command} stdout: " + (
|
94
|
-
|
95
|
-
stderr_message = [stderr.strip, full_stderr.strip].delete_if(&:empty?).first
|
96
|
-
message += "#{command} stderr: " + (stderr_message || 'Nothing written') + "\n"
|
93
|
+
message += "#{command} stdout: " + (full_stdout.strip.empty? ? "Nothing written" : full_stdout.strip) + "\n"
|
94
|
+
message += "#{command} stderr: " + (full_stderr.strip.empty? ? 'Nothing written' : full_stderr.strip) + "\n"
|
97
95
|
raise Failed, message
|
98
96
|
end
|
99
97
|
end
|
data/lib/sshkit/exception.rb
CHANGED
@@ -34,6 +34,7 @@ module SSHKit
|
|
34
34
|
uuid(command) + c.green("\t" + line)]
|
35
35
|
original_output << "\n" unless line[-1] == "\n"
|
36
36
|
end
|
37
|
+
command.stdout = ''
|
37
38
|
end
|
38
39
|
|
39
40
|
unless command.stderr.empty?
|
@@ -42,6 +43,7 @@ module SSHKit
|
|
42
43
|
uuid(command) + c.red("\t" + line)]
|
43
44
|
original_output << "\n" unless line[-1] == "\n"
|
44
45
|
end
|
46
|
+
command.stderr = ''
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
data/lib/sshkit/host.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ostruct'
|
2
|
+
require 'etc'
|
2
3
|
|
3
4
|
module SSHKit
|
4
5
|
|
@@ -22,7 +23,11 @@ module SSHKit
|
|
22
23
|
|
23
24
|
def initialize(host_string_or_options_hash)
|
24
25
|
|
25
|
-
|
26
|
+
if host_string_or_options_hash == :local
|
27
|
+
@local = true
|
28
|
+
@hostname = "localhost"
|
29
|
+
@user = Etc.getpwuid.name
|
30
|
+
elsif !host_string_or_options_hash.is_a?(Hash)
|
26
31
|
suitable_parsers = [
|
27
32
|
SimpleHostParser,
|
28
33
|
HostWithPortParser,
|
@@ -51,6 +56,10 @@ module SSHKit
|
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
59
|
+
def local?
|
60
|
+
@local
|
61
|
+
end
|
62
|
+
|
54
63
|
def hash
|
55
64
|
user.hash ^ hostname.hash ^ port.hash
|
56
65
|
end
|
data/lib/sshkit/version.rb
CHANGED
@@ -65,6 +65,17 @@ module SSHKit
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
def test_ssh_option_merge
|
69
|
+
a_host.ssh_options = { paranoid: true }
|
70
|
+
host_ssh_options = {}
|
71
|
+
SSHKit::Backend::Netssh.config.ssh_options = { forward_agent: false }
|
72
|
+
Netssh.new(a_host) do |host|
|
73
|
+
capture(:uname)
|
74
|
+
host_ssh_options = host.ssh_options
|
75
|
+
end.run
|
76
|
+
assert_equal({ forward_agent: false, paranoid: true }, host_ssh_options)
|
77
|
+
end
|
78
|
+
|
68
79
|
def test_execute_raises_on_non_zero_exit_status_and_captures_stdout_and_stderr
|
69
80
|
err = assert_raises SSHKit::Command::Failed do
|
70
81
|
Netssh.new(a_host) do |host|
|
data/test/unit/test_host.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'etc'
|
2
3
|
|
3
4
|
module SSHKit
|
4
5
|
|
@@ -41,6 +42,14 @@ module SSHKit
|
|
41
42
|
assert_equal 'example.com', h.hostname
|
42
43
|
end
|
43
44
|
|
45
|
+
def test_host_local
|
46
|
+
h = Host.new :local
|
47
|
+
assert h.local?
|
48
|
+
assert_nil h.port
|
49
|
+
assert_equal Etc.getpwuid.name, h.username
|
50
|
+
assert_equal 'localhost', h.hostname
|
51
|
+
end
|
52
|
+
|
44
53
|
def test_does_not_confuse_ipv6_hosts_with_port_specification
|
45
54
|
h = Host.new '[1fff:0:a88:85a3::ac1f]:8001'
|
46
55
|
assert_equal 8001, h.port
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sshkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Hambley
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-03-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -151,8 +151,8 @@ files:
|
|
151
151
|
- RELEASING.md
|
152
152
|
- Rakefile
|
153
153
|
- Vagrantfile
|
154
|
-
-
|
155
|
-
-
|
154
|
+
- examples/images/example_output.png
|
155
|
+
- examples/images/logo.png
|
156
156
|
- lib/core_ext/array.rb
|
157
157
|
- lib/core_ext/hash.rb
|
158
158
|
- lib/sshkit.rb
|
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
227
|
version: '0'
|
228
228
|
requirements: []
|
229
229
|
rubyforge_project:
|
230
|
-
rubygems_version: 2.
|
230
|
+
rubygems_version: 2.4.3
|
231
231
|
signing_key:
|
232
232
|
specification_version: 4
|
233
233
|
summary: SSHKit makes it easy to write structured, testable SSH commands in Ruby
|