sshkit 1.6.1 → 1.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6b3d2a602578d1cea808691cd6a94345862e87e
4
- data.tar.gz: 1f7d65fb072bb2c9e6fd830d49bfa354cf756296
3
+ metadata.gz: fbc4c4d5b2ac3c6cfda56f6d7582b6c2e4b0814d
4
+ data.tar.gz: 6a260d8a28ed5df45fd14de2140aa0de0f6ef577
5
5
  SHA512:
6
- metadata.gz: 4e0f22c3b4b0bf6e6af4bafc7d3d610c216fea810aebd29ab689819d3953da77f4aa3c5ea599453997f85b5f5bec5fae8fd629c370968a87580755bd23f6044b
7
- data.tar.gz: c789d68ad2b9025a694dd41b58b55640d55443252729bdbbd7d8460419e5fbe9670fde840b437cf2416380a1e19c28613ddd92c1b55d5a27ae0f8fa1c47a5dc8
6
+ metadata.gz: e37e0ac83457d83c0c5d41676830097c5ccd6f24ae5cc636533d2c2bb54a2f7706f387ec9af97a458a332a198b90189fd4263ec3411fb07a75db56cd0db25107
7
+ data.tar.gz: 135cc559ee24611b6f1ccab198445ea7a8efe2df7339c12409e5547a5c3ea0a1ae22d61a640b2a6703b1bb9e7c36af15d1f05fc2103d43d222bcd8fe9a978450
data/.gitignore CHANGED
@@ -1,4 +1,7 @@
1
1
  *.gem
2
+ *.swp
3
+ bin/rake
4
+ .bundle
2
5
  .yardoc
3
6
  .vagrant*
4
7
  test/tmp
@@ -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)
@@ -344,3 +344,10 @@ Replace `on` with `run_locally`
344
344
  end
345
345
  end
346
346
 
347
+ You can achieve the same thing with `on(:local)`
348
+
349
+ on(:local) do
350
+ within '/tmp' do
351
+ execute :whoami
352
+ end
353
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![SSHKit Logo](https://raw.github.com/leehambley/sshkit/master/assets/images/logo.png)
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/assets/images/example_output.png)
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
 
@@ -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
@@ -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(hostname: 'localhost') # just for logging
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, exit_status =
43
- if RUBY_ENGINE == 'jruby'
44
- _, o, e, t = Open3.popen3('/usr/bin/env', 'sh', '-c', cmd.to_command)
45
- [o.read, e.read, t.value]
46
- else
47
- Open3.capture3(cmd.to_command)
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
- cmd.stdout = stdout
51
- cmd.full_stdout += stdout
73
+ stderr_thread = Thread.new do
74
+ while line = stderr.gets do
75
+ cmd.stderr = line
76
+ cmd.full_stderr += line
52
77
 
53
- cmd.stderr = stderr
54
- cmd.full_stderr += stderr
78
+ output << cmd
79
+ end
80
+ end
55
81
 
56
- cmd.exit_status = exit_status.to_i
82
+ stdout_thread.join
83
+ stderr_thread.join
57
84
 
58
- output << cmd
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
- cmd.stdout = ''
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 ||= Netssh.config.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,
@@ -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: " + (stdout.strip.empty? ? "Nothing written" : stdout.strip) + "\n"
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
@@ -8,14 +8,6 @@ module SSHKit
8
8
  def initialize cause
9
9
  @cause = cause
10
10
  end
11
-
12
- def backtrace
13
- @cause.backtrace
14
- end
15
-
16
- def backtrace_locations
17
- @cause.backtrace_locations
18
- end
19
11
  end
20
12
  end
21
13
  end
@@ -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
 
@@ -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
- unless host_string_or_options_hash.is_a?(Hash)
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
@@ -15,7 +15,11 @@ module SSHKit
15
15
  private
16
16
 
17
17
  def backend(host, &block)
18
- SSHKit.config.backend.new(host, &block)
18
+ if host.local?
19
+ SSHKit::Backend::Local.new(&block)
20
+ else
21
+ SSHKit.config.backend.new(host, &block)
22
+ end
19
23
  end
20
24
 
21
25
  end
@@ -1,3 +1,3 @@
1
1
  module SSHKit
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -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|
@@ -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.6.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: 2014-12-16 00:00:00.000000000 Z
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
- - assets/images/example_output.png
155
- - assets/images/logo.png
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.2.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