sshkit 0.0.1

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.
Files changed (44) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +5 -0
  3. data/.yardoc/checksums +13 -0
  4. data/.yardoc/object_types +0 -0
  5. data/.yardoc/objects/root.dat +0 -0
  6. data/.yardoc/proxy_types +0 -0
  7. data/.yardopts +1 -0
  8. data/CHANGELOG.md +0 -0
  9. data/EXAMPLES.md +167 -0
  10. data/FAQ.md +17 -0
  11. data/Gemfile +2 -0
  12. data/Gemfile.lock +69 -0
  13. data/LICENSE.md +674 -0
  14. data/README.md +181 -0
  15. data/Rakefile +37 -0
  16. data/Vagrantfile +18 -0
  17. data/assets/images/logo.png +0 -0
  18. data/example.rb +70 -0
  19. data/lib/core_ext/array.rb +5 -0
  20. data/lib/core_ext/hash.rb +11 -0
  21. data/lib/sshkit/all.rb +13 -0
  22. data/lib/sshkit/backends/abstract.rb +83 -0
  23. data/lib/sshkit/backends/netssh.rb +82 -0
  24. data/lib/sshkit/backends/printer.rb +28 -0
  25. data/lib/sshkit/command.rb +153 -0
  26. data/lib/sshkit/configuration.rb +29 -0
  27. data/lib/sshkit/connection_manager.rb +93 -0
  28. data/lib/sshkit/dsl.rb +15 -0
  29. data/lib/sshkit/host.rb +151 -0
  30. data/lib/sshkit/version.rb +3 -0
  31. data/lib/sshkit.rb +27 -0
  32. data/sshkit.gemspec +34 -0
  33. data/test/functional/test_connection_manager.rb +17 -0
  34. data/test/functional/test_ssh_server_comes_up_for_functional_tests.rb +23 -0
  35. data/test/helper.rb +125 -0
  36. data/test/integration/backends/test_netssh.rb +99 -0
  37. data/test/unit/backends/test_netssh.rb +14 -0
  38. data/test/unit/backends/test_printer.rb +62 -0
  39. data/test/unit/core_ext/test_string.rb +12 -0
  40. data/test/unit/test_command.rb +113 -0
  41. data/test/unit/test_configuration.rb +47 -0
  42. data/test/unit/test_connection_manager.rb +78 -0
  43. data/test/unit/test_host.rb +65 -0
  44. metadata +301 -0
@@ -0,0 +1,12 @@
1
+ class String
2
+
3
+ def unindent
4
+ indent = self.split("\n").select do |line|
5
+ !line.strip.empty?
6
+ end.map do |line|
7
+ line.index(/[^\s]/)
8
+ end.compact.min || 0
9
+ self.gsub(/^[[:blank:]]{#{indent}}/, '')
10
+ end
11
+
12
+ end
@@ -0,0 +1,113 @@
1
+ require 'helper'
2
+
3
+ module SSHKit
4
+ class TestCommand < UnitTest
5
+
6
+ def test_maps_a_command
7
+ c = Command.new('example')
8
+ assert_equal '/usr/bin/env example', String(c)
9
+ end
10
+
11
+ def test_not_mapping_a_builtin
12
+ %w{if test time}.each do |builtin|
13
+ c = Command.new(builtin)
14
+ assert_equal builtin, String(c)
15
+ end
16
+ end
17
+
18
+ def test_using_a_heredoc
19
+ c = Command.new <<-EOHEREDOC
20
+ if test ! -d /var/log; then
21
+ echo "Example"
22
+ fi
23
+ EOHEREDOC
24
+ assert_equal "if test ! -d /var/log; then; echo \"Example\"; fi", String(c)
25
+ end
26
+
27
+ def test_including_the_env
28
+ c = Command.new(:rails, 'server', env: {rails_env: :production})
29
+ assert_equal "( RAILS_ENV=production /usr/bin/env rails server )", String(c)
30
+ end
31
+
32
+ def test_working_in_a_given_directory
33
+ c = Command.new(:ls, '-l', in: "/opt/sites")
34
+ assert_equal "cd /opt/sites && /usr/bin/env ls -l", String(c)
35
+ end
36
+
37
+ def test_working_in_a_given_directory_with_env
38
+ c = Command.new(:ls, '-l', in: "/opt/sites", env: {a: :b})
39
+ assert_equal "cd /opt/sites && ( A=b /usr/bin/env ls -l )", String(c)
40
+ end
41
+
42
+ def test_having_a_host_passed
43
+ refute Command.new(:date).host
44
+ assert Command.new(:date, host: :foo)
45
+ assert_equal :foo, Command.new(host: :foo).host
46
+ end
47
+
48
+ def test_working_as_a_given_user
49
+ c = Command.new(:whoami, user: :anotheruser)
50
+ assert_equal "sudo su anotheruser -c /usr/bin/env whoami", String(c)
51
+ end
52
+
53
+ def test_complete?
54
+ c = Command.new(:whoami)
55
+ refute c.complete?
56
+ c.exit_status = 1
57
+ assert c.complete?
58
+ c.exit_status = 0
59
+ assert c.complete?
60
+ end
61
+
62
+ def test_successful?
63
+ c = Command.new(:whoami)
64
+ refute c.successful?
65
+ refute c.success?
66
+ c.exit_status = 0
67
+ assert c.successful?
68
+ assert c.success?
69
+ end
70
+
71
+ def test_failure?
72
+ c = Command.new(:whoami)
73
+ refute c.failure?
74
+ refute c.failed?
75
+ c.exit_status = 1
76
+ assert c.failure?
77
+ assert c.failed?
78
+ c.exit_status = 127
79
+ assert c.failure?
80
+ assert c.failed?
81
+ end
82
+
83
+ def test_appending_stdout
84
+ c = Command.new(:whoami)
85
+ assert c.stdout += "test\n"
86
+ assert_equal "test\n", c.stdout
87
+ end
88
+
89
+ def test_appending_stderr
90
+ c = Command.new(:whoami)
91
+ assert c.stderr += "test\n"
92
+ assert_equal "test\n", c.stderr
93
+ end
94
+
95
+ def test_setting_exit_status
96
+ c = Command.new(:whoami)
97
+ assert_equal nil, c.exit_status
98
+ assert c.exit_status = 1
99
+ assert_equal 1, c.exit_status
100
+ end
101
+
102
+ def test_command_has_a_guid
103
+ assert Command.new(:whosmi).uuid
104
+ end
105
+
106
+ def test_wont_take_no_args
107
+ assert_raises ArgumentError do
108
+ Command.new
109
+ end
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+
3
+ module SSHKit
4
+
5
+ class TestConfiguration < UnitTest
6
+
7
+ def setup
8
+ SSHKit.config = nil
9
+ SSHKit.config.command_map.clear
10
+ end
11
+
12
+ def test_output
13
+ assert_equal $stdout, SSHKit.config.output
14
+ assert SSHKit.config.output = $stderr
15
+ assert_equal $stderr, SSHKit.config.output
16
+ end
17
+
18
+ def test_runner
19
+ assert_equal :parallel, SSHKit.config.runner
20
+ assert SSHKit.config.runner = :sequence
21
+ assert_equal :sequence, SSHKit.config.runner
22
+ end
23
+
24
+ def test_format
25
+ assert_equal :dot, SSHKit.config.format
26
+ assert SSHKit.config.format = :pretty
27
+ assert_equal :pretty, SSHKit.config.format
28
+ end
29
+
30
+ def test_backend
31
+ assert_equal SSHKit::Backend::Netssh, SSHKit.config.backend
32
+ assert SSHKit.config.backend = SSHKit::Backend::Printer
33
+ assert_equal SSHKit::Backend::Printer, SSHKit.config.backend
34
+ end
35
+
36
+ def test_command_map
37
+ cm = Hash.new { |h,k| h[k] = "/opt/sites/example/current/bin #{k}"}
38
+ assert_equal Hash.new, SSHKit.config.command_map
39
+ assert_equal "/usr/bin/env ruby", SSHKit.config.command_map[:ruby]
40
+ assert SSHKit.config.command_map = cm
41
+ assert_equal cm, SSHKit.config.command_map
42
+ assert_equal "/opt/sites/example/current/bin ruby", SSHKit.config.command_map[:ruby]
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,78 @@
1
+ require 'helper'
2
+
3
+ module SSHKit
4
+
5
+ class TestConnectionManager < UnitTest
6
+
7
+ def setup
8
+ SSHKit.config.backend = SSHKit::Backend::Abstract
9
+ end
10
+
11
+ def test_connection_manager_handles_a_single_argument
12
+ h = Host.new('1.example.com')
13
+ Host.expects(:new).with('1.example.com').once().returns(h)
14
+ ConnectionManager.new '1.example.com'
15
+ end
16
+
17
+ def test_connection_manager_resolves_hosts
18
+ h = Host.new('n.example.com')
19
+ Host.expects(:new).times(3).returns(h)
20
+ ConnectionManager.new %w{1.example.com 2.example.com 3.example.com}
21
+ end
22
+
23
+ def test_connection_manager_removes_duplicates_after_resolving_hosts
24
+ cm = ConnectionManager.new %w{user@1.example.com:22 user@1.example.com}
25
+ assert_equal ['user@1.example.com:22'], cm.hosts.map(&:to_s)
26
+ end
27
+
28
+ 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")
31
+ end
32
+ ConnectionManager.new(%w{1.example.com}).each &spy
33
+ end
34
+
35
+ def test_the_connection_manaager_runs_things_in_parallel_by_default
36
+ results = []
37
+ command = lambda do |host,connection|
38
+ results << Time.now
39
+ end
40
+ ConnectionManager.new(%w{1.example.com 2.example.com}).each &command
41
+ assert_equal 2, results.length
42
+ assert_equal *results.map(&:to_i)
43
+ end
44
+
45
+ def test_the_connection_manager_can_run_things_in_sequence
46
+ results = []
47
+ command = lambda do |host,connection|
48
+ results << Time.now
49
+ end
50
+ ConnectionManager.new(%w{1.example.com 2.example.com}).each(in: :sequence, &command)
51
+ assert_equal 2, results.length
52
+ assert_operator results.first.to_i, :<, results.last.to_i
53
+ end
54
+
55
+ def test_the_connection_manager_can_run_things_in_groups
56
+ results = []
57
+ command = lambda do |host,connection|
58
+ debugger
59
+ results << Time.now
60
+ 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
+ assert_equal 6, results.length
64
+ assert_equal *results[0..1].map(&:to_i)
65
+ assert_equal *results[2..3].map(&:to_i)
66
+ assert_equal *results[4..5].map(&:to_i)
67
+ assert_operator results[0].to_i, :<, results[2].to_i
68
+ assert_operator results[3].to_i, :<, results[4].to_i
69
+ end
70
+
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
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,65 @@
1
+ require 'helper'
2
+
3
+ module SSHKit
4
+
5
+ class TestHost < UnitTest
6
+
7
+ def test_raises_on_unparsable_string
8
+ assert_raises UnparsableHostStringError do
9
+ Host.new(":@hello@:")
10
+ end
11
+ end
12
+
13
+ def test_regular_hosts
14
+ h = Host.new 'example.com'
15
+ assert_equal 22, h.port
16
+ assert_equal `whoami`.chomp, h.username
17
+ assert_equal 'example.com', h.hostname
18
+ end
19
+
20
+ def test_host_with_port
21
+ h = Host.new 'example.com:2222'
22
+ assert_equal 2222, h.port
23
+ assert_equal 'example.com', h.hostname
24
+ end
25
+
26
+ def test_host_with_username
27
+ h = Host.new 'root@example.com'
28
+ assert_equal 'root', h.username
29
+ assert_equal 'example.com', h.hostname
30
+ end
31
+
32
+ def test_host_with_username_and_port
33
+ h = Host.new 'user@example.com:123'
34
+ assert_equal 123, h.port
35
+ assert_equal 'user', h.username
36
+ assert_equal 'example.com', h.hostname
37
+ end
38
+
39
+ def test_does_not_confuse_ipv6_hosts_with_port_specification
40
+ h = Host.new '[1fff:0:a88:85a3::ac1f]:8001'
41
+ assert_equal 8001, h.port
42
+ assert_equal '1fff:0:a88:85a3::ac1f', h.hostname
43
+ end
44
+
45
+ def testing_host_casting_to_a_key
46
+ assert_equal :"user@example.com:1234", Host.new('user@example.com:1234').to_key
47
+ end
48
+
49
+ def testing_host_casting_to_a_string
50
+ assert_equal "user@example.com:1234", Host.new('user@example.com:1234').to_s
51
+ end
52
+
53
+ def test_assert_hosts_hash_equally
54
+ assert_equal Host.new('example.com').hash, Host.new('example.com').hash
55
+ end
56
+
57
+ def test_assert_hosts_compare_equal
58
+ assert Host.new('example.com') == Host.new('example.com')
59
+ assert Host.new('example.com').eql? Host.new('example.com')
60
+ assert Host.new('example.com').equal? Host.new('example.com')
61
+ end
62
+
63
+ end
64
+
65
+ end
metadata ADDED
@@ -0,0 +1,301 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sshkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Lee Hambley
9
+ - Tom Clements
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-01-16 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: net-ssh
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: term-ansicolor
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: minitest
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.11.3
55
+ - - <
56
+ - !ruby/object:Gem::Version
57
+ version: 2.12.0
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 2.11.3
66
+ - - <
67
+ - !ruby/object:Gem::Version
68
+ version: 2.12.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: autotest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: rake
87
+ requirement: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ - !ruby/object:Gem::Dependency
102
+ name: turn
103
+ requirement: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: unindent
119
+ requirement: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ - !ruby/object:Gem::Dependency
134
+ name: mocha
135
+ requirement: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ type: :development
142
+ prerelease: false
143
+ version_requirements: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ - !ruby/object:Gem::Dependency
150
+ name: debugger
151
+ requirement: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ type: :development
158
+ prerelease: false
159
+ version_requirements: !ruby/object:Gem::Requirement
160
+ none: false
161
+ requirements:
162
+ - - ! '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: vagrant
167
+ requirement: !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ! '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: yard
183
+ requirement: !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
186
+ - - ! '>='
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ! '>='
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ - !ruby/object:Gem::Dependency
198
+ name: redcarpet
199
+ requirement: !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ! '>='
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ type: :development
206
+ prerelease: false
207
+ version_requirements: !ruby/object:Gem::Requirement
208
+ none: false
209
+ requirements:
210
+ - - ! '>='
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ description: A comprehensive toolkit for remotely running commands in a structured
214
+ manner on groups of servers.
215
+ email:
216
+ - lee.hambley@gmail.com
217
+ - seenmyfate@gmail.com
218
+ executables: []
219
+ extensions: []
220
+ extra_rdoc_files: []
221
+ files:
222
+ - .gitignore
223
+ - .travis.yml
224
+ - .yardoc/checksums
225
+ - .yardoc/object_types
226
+ - .yardoc/objects/root.dat
227
+ - .yardoc/proxy_types
228
+ - .yardopts
229
+ - CHANGELOG.md
230
+ - EXAMPLES.md
231
+ - FAQ.md
232
+ - Gemfile
233
+ - Gemfile.lock
234
+ - LICENSE.md
235
+ - README.md
236
+ - Rakefile
237
+ - Vagrantfile
238
+ - assets/images/logo.png
239
+ - example.rb
240
+ - lib/core_ext/array.rb
241
+ - lib/core_ext/hash.rb
242
+ - lib/sshkit.rb
243
+ - lib/sshkit/all.rb
244
+ - lib/sshkit/backends/abstract.rb
245
+ - lib/sshkit/backends/netssh.rb
246
+ - lib/sshkit/backends/printer.rb
247
+ - lib/sshkit/command.rb
248
+ - lib/sshkit/configuration.rb
249
+ - lib/sshkit/connection_manager.rb
250
+ - lib/sshkit/dsl.rb
251
+ - lib/sshkit/host.rb
252
+ - lib/sshkit/version.rb
253
+ - sshkit.gemspec
254
+ - test/functional/test_connection_manager.rb
255
+ - test/functional/test_ssh_server_comes_up_for_functional_tests.rb
256
+ - test/helper.rb
257
+ - test/integration/backends/test_netssh.rb
258
+ - test/unit/backends/test_netssh.rb
259
+ - test/unit/backends/test_printer.rb
260
+ - test/unit/core_ext/test_string.rb
261
+ - test/unit/test_command.rb
262
+ - test/unit/test_configuration.rb
263
+ - test/unit/test_connection_manager.rb
264
+ - test/unit/test_host.rb
265
+ homepage: http://wacku.github.com/sshkit
266
+ licenses: []
267
+ post_install_message:
268
+ rdoc_options: []
269
+ require_paths:
270
+ - lib
271
+ required_ruby_version: !ruby/object:Gem::Requirement
272
+ none: false
273
+ requirements:
274
+ - - ! '>='
275
+ - !ruby/object:Gem::Version
276
+ version: '0'
277
+ required_rubygems_version: !ruby/object:Gem::Requirement
278
+ none: false
279
+ requirements:
280
+ - - ! '>='
281
+ - !ruby/object:Gem::Version
282
+ version: '0'
283
+ requirements: []
284
+ rubyforge_project:
285
+ rubygems_version: 1.8.23
286
+ signing_key:
287
+ specification_version: 3
288
+ summary: SSHKit makes it easy to write structured, testable SSH commands in Ruby
289
+ test_files:
290
+ - test/functional/test_connection_manager.rb
291
+ - test/functional/test_ssh_server_comes_up_for_functional_tests.rb
292
+ - test/helper.rb
293
+ - test/integration/backends/test_netssh.rb
294
+ - test/unit/backends/test_netssh.rb
295
+ - test/unit/backends/test_printer.rb
296
+ - test/unit/core_ext/test_string.rb
297
+ - test/unit/test_command.rb
298
+ - test/unit/test_configuration.rb
299
+ - test/unit/test_connection_manager.rb
300
+ - test/unit/test_host.rb
301
+ has_rdoc: