sshkit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: