sshkit 0.0.2 → 0.0.3

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/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  *.gem
2
+ .yardoc
2
3
  .vagrant
3
4
  test/tmp
data/.yardopts CHANGED
@@ -1 +1 @@
1
- --no-private - README.md CHANGELOG.md FAQ.md LICENSE.md EXAMPLES.md
1
+ --no-private - README.md CHANGELOG.md FAQ.md LICENSE.md EXAMPLES.md CONTRIBUTING.md RELEASING.md
data/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  This file is written in reverse chronological order, newer releases will
4
4
  appear at the top.
5
5
 
6
+ ## 0.0.3
7
+
8
+ * Refactor the runner classes into an abstract heirarchy.
9
+
6
10
  ## 0.0.2
7
11
 
8
12
  * Include a *Pretty* formatter
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,4 @@
1
+ # Contributing to SSHKit
2
+
3
+ * [**Don't** push your pull request](http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/)
4
+ * [**Do** write a good commit message](http://365git.tumblr.com/post/3308646748/writing-git-commit-messages)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sshkit (0.0.1)
4
+ sshkit (0.0.2)
5
5
  net-ssh
6
6
  term-ansicolor
7
7
 
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- ![SSHKit Logo](/Users/leehambley/Projects/deployrb-deploy/assets/images/logo.png)
2
-
1
+ ![SSHKit Logo](https://raw.github.com/wacku/sshkit/master/assets/images/logo.png)
3
2
 
4
3
  **SSHKit** is a toolkit for running commands in a structured way on one or
5
4
  more servers.
@@ -48,7 +47,7 @@ the raised error.
48
47
  Helpers such as `runner()` and `rake()` which expand to `execute(:rails, "runner", ...)` and
49
48
  `execute(:rake, ...)` are convenience helpers for Ruby, and Rails based apps.
50
49
 
51
- ## Parallel
50
+ ## Parallel
52
51
 
53
52
  Notice on the `on()` call the `in: :sequence` option, the following will do
54
53
  what you might expect:
@@ -156,6 +155,8 @@ first argument before attempting to find it in the *command map*.
156
155
 
157
156
  ## Output Handling
158
157
 
158
+ ![Example Output](https://raw.github.com/wacku/sshkit/master/assets/images/example_output.png)
159
+
159
160
  The output handling comprises two objects, first is the output itself, by
160
161
  default this is *$stdout*, but can be any object responding to a
161
162
  *StringIO*-like interface. The second part is the *formatter*.
@@ -173,9 +174,30 @@ should be printed.
173
174
  ## Known Issues
174
175
 
175
176
  * No handling of slow / timed out connections
176
- * No handling ot slow / hung remote commands
177
+ * No handling of slow / hung remote commands
177
178
  * No built-in way to background() something (execute and background the
178
- process)
179
- * No environment handling
180
- * No arbitrary `Host` properties
181
-
179
+ process).
180
+ * No environment handling (sshkit might not need to care)
181
+ * No arbitrary `Host` properties (example storing `roles` on servers, or other
182
+ metadata that might be useful in the `on()` block)
183
+ * No log/warning facility (passing Log messages to the output would work)
184
+ A log object could be made available globally which would emit a LogMessage
185
+ type object which would be recognised by the formatters that need to care
186
+ about them.
187
+ * No verbosity control, commands should have a `Logger::LEVEL` on them,
188
+ user-generated should be at a high level, the commands auto-generated from
189
+ the guards and checks from as() and within() should have a lower level.
190
+ * Decide if `execute()` (and friends) should raise on non-zero exit statuses or
191
+ not, perhaps a family of similarly named bang methods should be the ones to
192
+ raise. (Perhaps `test()` should be a way to `execute()` without raising, and
193
+ `execute()` and friends should always raise)
194
+ * It would be nice to be able to say `SSHKit.config.formatter = :pretty` and
195
+ have that method setter do the legwork of updating `SSHKit.config.output` to
196
+ be an instance of the correct formatter class wrapping the existing output
197
+ stream.
198
+ * No closing of connections, the abstract backend class should include a
199
+ cleanup method which is empty but can be overriden by
200
+ * No conncetion pooling, the `connection` method of the NetSSH backend could
201
+ easily be modified to look into some connection factory for it's objects,
202
+ saving half a second when running lots of `on()` blocks.
203
+ * Documentation! (YARD style)
data/RELEASING.md ADDED
@@ -0,0 +1,10 @@
1
+ # Releasing
2
+
3
+ * **Ensure the tests are passing.**
4
+ * Determine which would be the correct next version number according to [semver](http://semver.org/).
5
+ * Update the version in `./lib/sshkit/version.rb`.
6
+ * Update the `CHANGELOG`.
7
+ * Commit the changelog and version in a single commit, the message should be "Preparing vX.Y.Z"
8
+ * Tag the commit `git tag vX.Y.Z` (if tagging a historical commit, `git tag` can take a *SHA1* after the tag name)
9
+ * Push new commits, and tags to Github.
10
+ * Push the gem to [rubygems](http://rubygems.org).
Binary file
data/lib/sshkit/all.rb CHANGED
@@ -11,6 +11,7 @@ require_relative 'connection_manager'
11
11
  require_relative 'formatters/abstract'
12
12
  require_relative 'formatters/black_hole'
13
13
  require_relative 'formatters/pretty'
14
+ require_relative 'formatters/dot'
14
15
 
15
16
  require_relative 'backends/abstract'
16
17
  require_relative 'backends/printer'
@@ -10,7 +10,7 @@ module SSHKit
10
10
  end
11
11
 
12
12
  def execute(*args)
13
- output << command(*args)
13
+ output << String(command(*args)) + "\n"
14
14
  end
15
15
 
16
16
  def capture(command, args=[])
@@ -1,54 +1,68 @@
1
1
  require 'timeout'
2
2
 
3
- class Runner
3
+ module SSHKit
4
4
 
5
- attr_reader :hosts, :block
5
+ module Runner
6
6
 
7
- def initialize(hosts, &block)
8
- @hosts = Array(hosts)
9
- @block = block
10
- end
7
+ class Abstract
11
8
 
12
- end
9
+ attr_reader :hosts, :block
10
+
11
+ def initialize(hosts, &block)
12
+ @hosts = Array(hosts)
13
+ @block = block
14
+ end
15
+
16
+ private
13
17
 
14
- class ParallelRunner < Runner
15
- def execute
16
- threads = []
17
- hosts.each do |host|
18
- threads << Thread.new(host) do |h|
19
- SSHKit.config.backend.new(host, &block).run
18
+ def backend(host, &block)
19
+ SSHKit.config.backend.new(host, &block)
20
20
  end
21
+
21
22
  end
22
- threads.map(&:join)
23
- end
24
- end
25
23
 
26
- class SequentialRunner < Runner
27
- attr_writer :wait_interval
28
- def execute
29
- hosts.each do |host|
30
- SSHKit.config.backend.new(host, &block).run
31
- sleep wait_interval
24
+ class Parallel < Abstract
25
+ def execute
26
+ threads = []
27
+ hosts.each do |host|
28
+ threads << Thread.new(host) do |h|
29
+ backend(host, &block).run
30
+ end
31
+ end
32
+ threads.map(&:join)
33
+ end
34
+ end
35
+
36
+ class Sequential < Abstract
37
+ attr_writer :wait_interval
38
+ def execute
39
+ hosts.each do |host|
40
+ backend(host, &block).run
41
+ sleep wait_interval
42
+ end
43
+ end
44
+ private
45
+ def wait_interval
46
+ @wait_interval ||= 2
47
+ end
48
+ end
49
+
50
+ class Group < Sequential
51
+ attr_writer :group_size
52
+ def execute
53
+ hosts.each_slice(group_size).collect do |group_hosts|
54
+ Parallel.new(group_hosts, &block).execute
55
+ sleep wait_interval
56
+ end.flatten
57
+ end
58
+ private
59
+ def group_size
60
+ @group_size ||= 2
61
+ end
32
62
  end
33
- end
34
- private
35
- def wait_interval
36
- @wait_interval ||= 2
37
- end
38
- end
39
63
 
40
- class GroupRunner < SequentialRunner
41
- attr_writer :group_size
42
- def execute
43
- hosts.each_slice(group_size).collect do |group_hosts|
44
- ParallelRunner.new(group_hosts, &block).execute
45
- sleep wait_interval
46
- end.flatten
47
- end
48
- private
49
- def group_size
50
- @group_size ||= 2
51
64
  end
65
+
52
66
  end
53
67
 
54
68
  module SSHKit
@@ -68,9 +82,9 @@ module SSHKit
68
82
  def each(options={}, &block)
69
83
  options = default_options.merge(options)
70
84
  case options[:in]
71
- when :parallel then ParallelRunner
72
- when :sequence then SequentialRunner
73
- when :groups then GroupRunner
85
+ when :parallel then Runner::Parallel
86
+ when :sequence then Runner::Sequential
87
+ when :groups then Runner::Group
74
88
  else
75
89
  raise RuntimeError, "Don't know how to handle run style #{options[:in].inspect}"
76
90
  end.new(hosts, &block).execute
@@ -0,0 +1,28 @@
1
+ require 'term/ansicolor'
2
+
3
+ module SSHKit
4
+
5
+ module Formatter
6
+
7
+ class Dot < Abstract
8
+
9
+ def write(obj)
10
+ if obj.is_a? SSHKit::Command
11
+ if obj.finished?
12
+ original_output << (obj.failure? ? c.red('.') : c.green('.'))
13
+ end
14
+ end
15
+ end
16
+ alias :<< :write
17
+
18
+ private
19
+
20
+ def c
21
+ @c ||= Term::ANSIColor
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -1,3 +1,3 @@
1
1
  module SSHKit
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -4,18 +4,6 @@ module SSHKit
4
4
 
5
5
  module Backend
6
6
 
7
- class ToSIoFormatter < StringIO
8
- extend Forwardable
9
- attr_reader :original_output
10
- def_delegators :@original_output, :read, :rewind
11
- def initialize(oio)
12
- @original_output = oio
13
- end
14
- def write(obj)
15
- original_output.write "> Executing #{obj}\n"
16
- end
17
- end
18
-
19
7
  class TestPrinter < UnitTest
20
8
 
21
9
  def block_to_run
@@ -39,19 +27,19 @@ module SSHKit
39
27
  end
40
28
 
41
29
  def test_simple_printing
42
- sio = ToSIoFormatter.new(StringIO.new)
30
+ sio = StringIO.new
43
31
  SSHKit.capture_output(sio) do
44
32
  printer.run
45
33
  end
46
34
  sio.rewind
47
35
  result = sio.read
48
36
  assert_equal <<-EOEXPECTED.unindent, result
49
- > Executing if test ! -d /opt/sites/example.com; then echo "Directory does not exist '/opt/sites/example.com'" 1>&2; false; fi
50
- > Executing cd /opt/sites/example.com && /usr/bin/env date
51
- > Executing cd /opt/sites/example.com && /usr/bin/env ls -l /some/directory
52
- > Executing if test ! -d /opt/sites/example.com/tmp; then echo "Directory does not exist '/opt/sites/example.com/tmp'" 1>&2; false; fi
53
- > Executing if ! sudo su root -c whoami > /dev/null; then echo "You cannot switch to user 'root' using sudo, please check the sudoers file" 1>&2; false; fi
54
- > Executing cd /opt/sites/example.com/tmp && ( RAILS_ENV=production sudo su root -c /usr/bin/env touch restart.txt )
37
+ if test ! -d /opt/sites/example.com; then echo "Directory does not exist '/opt/sites/example.com'" 1>&2; false; fi
38
+ cd /opt/sites/example.com && /usr/bin/env date
39
+ cd /opt/sites/example.com && /usr/bin/env ls -l /some/directory
40
+ if test ! -d /opt/sites/example.com/tmp; then echo "Directory does not exist '/opt/sites/example.com/tmp'" 1>&2; false; fi
41
+ if ! sudo su root -c whoami > /dev/null; then echo "You cannot switch to user 'root' using sudo, please check the sudoers file" 1>&2; false; fi
42
+ cd /opt/sites/example.com/tmp && ( RAILS_ENV=production sudo su root -c /usr/bin/env touch restart.txt )
55
43
  EOEXPECTED
56
44
  end
57
45
 
@@ -1,3 +1,4 @@
1
+ require 'time'
1
2
  require 'helper'
2
3
 
3
4
  module SSHKit
@@ -5,7 +6,18 @@ module SSHKit
5
6
  class TestConnectionManager < UnitTest
6
7
 
7
8
  def setup
8
- SSHKit.config.backend = SSHKit::Backend::Abstract
9
+ @s = String.new
10
+ SSHKit.config.backend = SSHKit::Backend::Printer
11
+ end
12
+
13
+ def tearddown
14
+ @s = nil
15
+ end
16
+
17
+ def block_to_run
18
+ lambda do |host|
19
+ execute "echo #{Time.now}"
20
+ end
9
21
  end
10
22
 
11
23
  def test_connection_manager_handles_a_single_argument
@@ -26,40 +38,38 @@ module SSHKit
26
38
  end
27
39
 
28
40
  def test_the_connection_manager_yields_the_host_to_each_connection_instance
29
- spy = lambda do |host, connection|
30
- assert_equal host, Host.new("1.example.com")
41
+ spy = lambda do |host|
42
+ execute "echo #{host.hostname}"
43
+ end
44
+ String.new.tap do |str|
45
+ SSHKit.capture_output str do
46
+ ConnectionManager.new(%w{1.example.com}).each &spy
47
+ end
48
+ assert_equal "echo 1.example.com", str.strip
31
49
  end
32
- ConnectionManager.new(%w{1.example.com}).each &spy
33
50
  end
34
51
 
35
52
  def test_the_connection_manaager_runs_things_in_parallel_by_default
36
- results = []
37
- command = lambda do |host,connection|
38
- results << Time.now
53
+ SSHKit.capture_output @s do
54
+ ConnectionManager.new(%w{1.example.com 2.example.com}).each &block_to_run
39
55
  end
40
- ConnectionManager.new(%w{1.example.com 2.example.com}).each &command
41
56
  assert_equal 2, results.length
42
57
  assert_equal *results.map(&:to_i)
43
58
  end
44
59
 
45
60
  def test_the_connection_manager_can_run_things_in_sequence
46
- results = []
47
- command = lambda do |host,connection|
48
- results << Time.now
61
+ SSHKit.capture_output @s do
62
+ ConnectionManager.new(%w{1.example.com 2.example.com}).each in: :sequence, &block_to_run
49
63
  end
50
- ConnectionManager.new(%w{1.example.com 2.example.com}).each(in: :sequence, &command)
51
64
  assert_equal 2, results.length
52
65
  assert_operator results.first.to_i, :<, results.last.to_i
53
66
  end
54
67
 
55
68
  def test_the_connection_manager_can_run_things_in_groups
56
- results = []
57
- command = lambda do |host,connection|
58
- debugger
59
- results << Time.now
69
+ SSHKit.capture_output @s do
70
+ ConnectionManager.new(%w{1.example.com 2.example.com 3.example.com
71
+ 4.example.com 5.example.com 6.example.com}).each in: :groups, &block_to_run
60
72
  end
61
- ConnectionManager.new(%w{1.example.com 2.example.com 3.example.com
62
- 4.example.com 5.example.com 6.example.com}).each(in: :groups, &command)
63
73
  assert_equal 6, results.length
64
74
  assert_equal *results[0..1].map(&:to_i)
65
75
  assert_equal *results[2..3].map(&:to_i)
@@ -68,9 +78,12 @@ module SSHKit
68
78
  assert_operator results[3].to_i, :<, results[4].to_i
69
79
  end
70
80
 
71
- def test_slow_host_timeout
72
- # Ensure that we throw an error and rollback if one host takes an
73
- # exceptional length of time longer than the others
81
+ private
82
+
83
+ def results
84
+ @s.lines.collect do |line|
85
+ Time.parse(line.split[1..-1].join(' '))
86
+ end
74
87
  end
75
88
 
76
89
  end
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: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-01-16 00:00:00.000000000 Z
13
+ date: 2013-01-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: net-ssh
@@ -221,20 +221,19 @@ extra_rdoc_files: []
221
221
  files:
222
222
  - .gitignore
223
223
  - .travis.yml
224
- - .yardoc/checksums
225
- - .yardoc/object_types
226
- - .yardoc/objects/root.dat
227
- - .yardoc/proxy_types
228
224
  - .yardopts
229
225
  - CHANGELOG.md
226
+ - CONTRIBUTING.md
230
227
  - EXAMPLES.md
231
228
  - FAQ.md
232
229
  - Gemfile
233
230
  - Gemfile.lock
234
231
  - LICENSE.md
235
232
  - README.md
233
+ - RELEASING.md
236
234
  - Rakefile
237
235
  - Vagrantfile
236
+ - assets/images/example_output.png
238
237
  - assets/images/logo.png
239
238
  - example.rb
240
239
  - lib/core_ext/array.rb
@@ -250,6 +249,7 @@ files:
250
249
  - lib/sshkit/dsl.rb
251
250
  - lib/sshkit/formatters/abstract.rb
252
251
  - lib/sshkit/formatters/black_hole.rb
252
+ - lib/sshkit/formatters/dot.rb
253
253
  - lib/sshkit/formatters/pretty.rb
254
254
  - lib/sshkit/host.rb
255
255
  - lib/sshkit/version.rb
data/.yardoc/checksums DELETED
@@ -1,13 +0,0 @@
1
- lib/deploy.rb 8f584561b611345114f38176ec53bf00f9d5550f
2
- lib/deploy/all.rb 9fc0b15f0968612fbd2ffaf0bba9dff6f788e3d1
3
- lib/deploy/host.rb 777a8deedcdd5b41dceab8773c992bafa5ee9f92
4
- lib/core_ext/hash.rb b7a0f0d1ab3b83f6b251e2f865ad6fa3766124a0
5
- lib/deploy/command.rb 1a04acc7d5abd1b288bbea3676c287434849ef05
6
- lib/core_ext/array.rb 3d495a96a0d1566877bf2ebb70ab9ea10a7d32e1
7
- lib/deploy/version.rb 30e41688e07f7ee74377aaef147250340df4a3f0
8
- lib/deploy/configuration.rb 3e9f042e0e9e9860d3950a1406a988586434de16
9
- lib/deploy/backends/netssh.rb c931441edd28ba7e134b0d3ae2fbf40efb347b81
10
- lib/deploy/backends/printer.rb db41b51e9624105efd7cb7f1fef426b506ebadaa
11
- lib/deploy/backends/abstract.rb 74260020d3a6c4913f7a3d9294968e1b2a1304a9
12
- lib/deploy/connection_manager.rb 28c8ef12a8a5923aeaa497ed02fd22869f57186b
13
- lib/deploy/dsl.rb a487b4e65ab52955b12a5fe55bda99dec61e16b9
data/.yardoc/object_types DELETED
Binary file
Binary file
data/.yardoc/proxy_types DELETED
Binary file