rush 0.1 → 0.2
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/Rakefile +5 -1
- data/lib/rush.rb +4 -0
- data/lib/rush/array_ext.rb +2 -0
- data/lib/rush/box.rb +19 -0
- data/lib/rush/dir.rb +13 -3
- data/lib/rush/entry.rb +8 -3
- data/lib/rush/exceptions.rb +26 -0
- data/lib/rush/file.rb +6 -2
- data/lib/rush/find_by.rb +37 -0
- data/lib/rush/local.rb +100 -15
- data/lib/rush/process.rb +19 -4
- data/lib/rush/remote.rb +47 -6
- data/lib/rush/server.rb +48 -12
- data/lib/rush/shell.rb +23 -14
- data/lib/rush/ssh_tunnel.rb +21 -12
- data/spec/box_spec.rb +25 -0
- data/spec/dir_spec.rb +5 -0
- data/spec/entry_spec.rb +2 -2
- data/spec/file_spec.rb +4 -0
- data/spec/find_by_spec.rb +55 -0
- data/spec/local_spec.rb +80 -13
- data/spec/process_spec.rb +32 -3
- data/spec/remote_spec.rb +46 -0
- data/spec/shell_spec.rb +1 -1
- data/spec/ssh_tunnel_spec.rb +22 -6
- metadata +33 -4
data/spec/local_spec.rb
CHANGED
@@ -27,6 +27,11 @@ describe Rush::Connection::Local do
|
|
27
27
|
@con.receive(:action => 'destroy', :full_path => 'file')
|
28
28
|
end
|
29
29
|
|
30
|
+
it "receive -> purge(dir)" do
|
31
|
+
@con.should_receive(:purge).with('dir')
|
32
|
+
@con.receive(:action => 'purge', :full_path => 'dir')
|
33
|
+
end
|
34
|
+
|
30
35
|
it "receive -> create_dir(path)" do
|
31
36
|
@con.should_receive(:create_dir).with('dir')
|
32
37
|
@con.receive(:action => 'create_dir', :full_path => 'dir')
|
@@ -79,7 +84,12 @@ describe Rush::Connection::Local do
|
|
79
84
|
|
80
85
|
it "receive -> kill_process" do
|
81
86
|
@con.should_receive(:kill_process).with(123).and_return(true)
|
82
|
-
@con.receive(:action => 'kill_process', :pid => 123)
|
87
|
+
@con.receive(:action => 'kill_process', :pid => '123')
|
88
|
+
end
|
89
|
+
|
90
|
+
it "receive -> bash" do
|
91
|
+
@con.should_receive(:bash).with('cmd').and_return('output')
|
92
|
+
@con.receive(:action => 'bash', :payload => 'cmd').should == 'output'
|
83
93
|
end
|
84
94
|
|
85
95
|
it "receive -> unknown action exception" do
|
@@ -99,6 +109,11 @@ describe Rush::Connection::Local do
|
|
99
109
|
@con.file_contents(fname).should == "stuff\n"
|
100
110
|
end
|
101
111
|
|
112
|
+
it "file_contents raises DoesNotExist if the file does not exist" do
|
113
|
+
fname = "#{@sandbox_dir}/does_not_exist"
|
114
|
+
lambda { @con.file_contents(fname) }.should raise_error(Rush::DoesNotExist, fname)
|
115
|
+
end
|
116
|
+
|
102
117
|
it "destroy to destroy a file or dir" do
|
103
118
|
fname = "#{@sandbox_dir}/delete_me"
|
104
119
|
system "touch #{fname}"
|
@@ -106,6 +121,20 @@ describe Rush::Connection::Local do
|
|
106
121
|
File.exists?(fname).should be_false
|
107
122
|
end
|
108
123
|
|
124
|
+
it "purge to purge a dir" do
|
125
|
+
system "cd #{@sandbox_dir}; touch {1,2}; mkdir 3; touch 3/4"
|
126
|
+
@con.purge(@sandbox_dir)
|
127
|
+
File.exists?(@sandbox_dir).should be_true
|
128
|
+
Dir.glob("#{@sandbox_dir}/*").should == []
|
129
|
+
end
|
130
|
+
|
131
|
+
it "purge kills hidden (dotfile) entries too" do
|
132
|
+
system "cd #{@sandbox_dir}; touch .killme"
|
133
|
+
@con.purge(@sandbox_dir)
|
134
|
+
File.exists?(@sandbox_dir).should be_true
|
135
|
+
`cd #{@sandbox_dir}; ls -lA | wc -l`.to_i.should == 0
|
136
|
+
end
|
137
|
+
|
109
138
|
it "create_dir creates a directory" do
|
110
139
|
fname = "#{@sandbox_dir}/a/b/c/"
|
111
140
|
@con.create_dir(fname)
|
@@ -127,6 +156,14 @@ describe Rush::Connection::Local do
|
|
127
156
|
File.exists?("#{@sandbox_dir}/subdir/a").should be_true
|
128
157
|
end
|
129
158
|
|
159
|
+
it "copy raises DoesNotExist with source path if it doesn't exist or otherwise can't be accessed" do
|
160
|
+
lambda { @con.copy('/does/not/exist', '/tmp') }.should raise_error(Rush::DoesNotExist, '/does/not/exist')
|
161
|
+
end
|
162
|
+
|
163
|
+
it "copy raises DoesNotExist with destination path if it can't access the destination" do
|
164
|
+
lambda { @con.copy('/tmp', '/does/not/exist') }.should raise_error(Rush::DoesNotExist, '/does/not')
|
165
|
+
end
|
166
|
+
|
130
167
|
it "read_archive to pull an archive of a dir into a byte stream" do
|
131
168
|
system "touch #{@sandbox_dir}/a"
|
132
169
|
@con.read_archive(@sandbox_dir).size.should > 50
|
@@ -150,11 +187,20 @@ describe Rush::Connection::Local do
|
|
150
187
|
@con.index(@sandbox_dir, '*.rb').should == [ 'a.rb' ]
|
151
188
|
end
|
152
189
|
|
190
|
+
it "index raises DoesNotExist when the base path is invalid" do
|
191
|
+
lambda { @con.index('/does/not/exist', '*') }.should raise_error(Rush::DoesNotExist, '/does/not/exist')
|
192
|
+
end
|
193
|
+
|
153
194
|
it "stat gives file stats like size and timestamps" do
|
154
195
|
@con.stat(@sandbox_dir).should have_key(:ctime)
|
155
196
|
@con.stat(@sandbox_dir).should have_key(:size)
|
156
197
|
end
|
157
198
|
|
199
|
+
it "stat raises DoesNotExist if the entry does not exist" do
|
200
|
+
fname = "#{@sandbox_dir}/does_not_exist"
|
201
|
+
lambda { @con.stat(fname) }.should raise_error(Rush::DoesNotExist, fname)
|
202
|
+
end
|
203
|
+
|
158
204
|
if !RUBY_PLATFORM.match(/darwin/) # doesn't work on OS X 'cause du switches are different
|
159
205
|
it "size gives size of a directory and all its contents recursively" do
|
160
206
|
system "mkdir -p #{@sandbox_dir}/a/b/; echo 1234 > #{@sandbox_dir}/a/b/c"
|
@@ -163,11 +209,12 @@ describe Rush::Connection::Local do
|
|
163
209
|
end
|
164
210
|
|
165
211
|
it "parses ps output on os x" do
|
166
|
-
@con.parse_ps("21712 501 1236 0 /usr/bin/vi somefile.rb").should == {
|
212
|
+
@con.parse_ps("21712 501 21711 1236 0 /usr/bin/vi somefile.rb").should == {
|
167
213
|
:pid => "21712",
|
168
214
|
:uid => "501",
|
169
|
-
:
|
170
|
-
:
|
215
|
+
:parent_pid => 21711,
|
216
|
+
:mem => 1236,
|
217
|
+
:cpu => 0,
|
171
218
|
:command => '/usr/bin/vi',
|
172
219
|
:cmdline => '/usr/bin/vi somefile.rb',
|
173
220
|
}
|
@@ -175,22 +222,42 @@ describe Rush::Connection::Local do
|
|
175
222
|
|
176
223
|
it "gets the list of processes on os x via the ps command" do
|
177
224
|
@con.should_receive(:os_x_raw_ps).and_return <<EOPS
|
178
|
-
PID UID RSS CPU COMMAND
|
179
|
-
1 0
|
180
|
-
2 501
|
225
|
+
PID UID PPID RSS CPU COMMAND
|
226
|
+
1 0 1 1111 0 cmd1 args
|
227
|
+
2 501 1 222 1 cmd2
|
181
228
|
EOPS
|
182
229
|
@con.os_x_processes.should == [
|
183
|
-
{ :pid => "1", :uid => "0", :
|
184
|
-
{ :pid => "2", :uid => "501", :
|
230
|
+
{ :pid => "1", :uid => "0", :parent_pid => 1, :mem => 1111, :cpu => 0, :command => "cmd1", :cmdline => "cmd1 args" },
|
231
|
+
{ :pid => "2", :uid => "501", :parent_pid => 1, :mem => 222, :cpu => 1, :command => "cmd2", :cmdline => "cmd2" },
|
185
232
|
]
|
186
233
|
end
|
187
234
|
|
188
|
-
it "
|
189
|
-
@con.process_alive(Process.pid).should
|
235
|
+
it "the current process should be alive" do
|
236
|
+
@con.process_alive(Process.pid).should be_true
|
237
|
+
end
|
238
|
+
|
239
|
+
it "a made-up process should not be alive" do
|
240
|
+
@con.process_alive(99999).should be_false
|
190
241
|
end
|
191
242
|
|
192
243
|
it "kills a process by pid" do
|
193
|
-
::Process.should_receive(:kill).
|
194
|
-
@con.kill_process(
|
244
|
+
::Process.should_receive(:kill).at_least(:once)
|
245
|
+
@con.kill_process(123)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "executes a bash command, returning stdout when successful" do
|
249
|
+
@con.bash("echo test").should == "test\n"
|
250
|
+
end
|
251
|
+
|
252
|
+
it "executes a bash command, raising and error (with stderr as the message) when return value is nonzero" do
|
253
|
+
lambda { @con.bash("no_such_bin") }.should raise_error(Rush::BashFailed, /command not found/)
|
254
|
+
end
|
255
|
+
|
256
|
+
it "ensure_tunnel to match with remote connection" do
|
257
|
+
@con.ensure_tunnel
|
258
|
+
end
|
259
|
+
|
260
|
+
it "always returns true on alive?" do
|
261
|
+
@con.should be_alive
|
195
262
|
end
|
196
263
|
end
|
data/spec/process_spec.rb
CHANGED
@@ -12,6 +12,13 @@ describe Rush::Process do
|
|
12
12
|
system "kill -9 #{@pid}"
|
13
13
|
end
|
14
14
|
|
15
|
+
if !RUBY_PLATFORM.match(/darwin/) # OS x reports pids weird
|
16
|
+
it "knows all its child processes" do
|
17
|
+
parent = Rush::Process.all.detect { |p| p.pid == Process.pid }
|
18
|
+
parent.children.should == [ @process ]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
15
22
|
it "gets the list of all processes" do
|
16
23
|
list = Rush::Process.all
|
17
24
|
list.size.should > 5
|
@@ -34,11 +41,33 @@ describe Rush::Process do
|
|
34
41
|
@process.cmdline.should match(/process_spec.rb/)
|
35
42
|
end
|
36
43
|
|
44
|
+
it "knows the memory used" do
|
45
|
+
@process.mem.should > 0
|
46
|
+
end
|
47
|
+
|
48
|
+
it "knows the cpu used" do
|
49
|
+
@process.cpu.should >= 0
|
50
|
+
end
|
51
|
+
|
52
|
+
it "knows the parent process pid" do
|
53
|
+
@process.parent_pid.should == Process.pid
|
54
|
+
end
|
55
|
+
|
56
|
+
it "knows the parent process" do
|
57
|
+
this = Rush::Box.new.processes.select { |p| p.pid == Process.pid }.first
|
58
|
+
@process.parent.should == this
|
59
|
+
end
|
60
|
+
|
37
61
|
it "can kill itself" do
|
38
62
|
system "sleep 30 &"
|
39
|
-
|
40
|
-
|
63
|
+
process = Rush::Process.all.detect { |p| p.command == "sleep" }
|
64
|
+
process.kill
|
41
65
|
sleep 0.1
|
42
|
-
|
66
|
+
process.alive?.should be_false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "if box and pid are the same, process is equal" do
|
70
|
+
other = Rush::Process.new({ :pid => @process.pid }, @process.box)
|
71
|
+
@process.should == other
|
43
72
|
end
|
44
73
|
end
|
data/spec/remote_spec.rb
CHANGED
@@ -27,6 +27,11 @@ describe Rush::Connection::Local do
|
|
27
27
|
@con.destroy('file')
|
28
28
|
end
|
29
29
|
|
30
|
+
it "transmits purge" do
|
31
|
+
@con.should_receive(:transmit).with(:action => 'purge', :full_path => 'dir')
|
32
|
+
@con.purge('dir')
|
33
|
+
end
|
34
|
+
|
30
35
|
it "transmits create_dir" do
|
31
36
|
@con.should_receive(:transmit).with(:action => 'create_dir', :full_path => 'file')
|
32
37
|
@con.create_dir('file')
|
@@ -81,4 +86,45 @@ describe Rush::Connection::Local do
|
|
81
86
|
@con.should_receive(:transmit).with(:action => 'kill_process', :pid => 123)
|
82
87
|
@con.kill_process(123)
|
83
88
|
end
|
89
|
+
|
90
|
+
it "transmits bash" do
|
91
|
+
@con.should_receive(:transmit).with(:action => 'bash', :payload => 'cmd').and_return('output')
|
92
|
+
@con.bash('cmd').should == 'output'
|
93
|
+
end
|
94
|
+
|
95
|
+
it "an http result code of 401 raises NotAuthorized" do
|
96
|
+
lambda { @con.process_result("401", "") }.should raise_error(Rush::NotAuthorized)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "an http result code of 400 raises the exception passed in the result body" do
|
100
|
+
@con.stub!(:parse_exception).and_return(Rush::DoesNotExist, "message")
|
101
|
+
lambda { @con.process_result("400", "") }.should raise_error(Rush::DoesNotExist)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "an http result code of 501 (or anything other than the other defined codes) raises FailedTransmit" do
|
105
|
+
lambda { @con.process_result("501", "") }.should raise_error(Rush::FailedTransmit)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "parse_exception takes the class from the first line and the message from the second" do
|
109
|
+
@con.parse_exception("Rush::DoesNotExist\nthe message\n").should == [ Rush::DoesNotExist, "the message" ]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "parse_exception rejects unrecognized exceptions" do
|
113
|
+
lambda { @con.parse_exception("NotARushException\n") }.should raise_error
|
114
|
+
end
|
115
|
+
|
116
|
+
it "passes through ensure_tunnel" do
|
117
|
+
@con.tunnel.should_receive(:ensure_tunnel)
|
118
|
+
@con.ensure_tunnel
|
119
|
+
end
|
120
|
+
|
121
|
+
it "is alive if the box is responding to commands" do
|
122
|
+
@con.should_receive(:index).and_return(:dummy)
|
123
|
+
@con.should be_alive
|
124
|
+
end
|
125
|
+
|
126
|
+
it "not alive if an attempted command throws an exception" do
|
127
|
+
@con.should_receive(:index).and_raise(RuntimeError)
|
128
|
+
@con.should_not be_alive
|
129
|
+
end
|
84
130
|
end
|
data/spec/shell_spec.rb
CHANGED
data/spec/ssh_tunnel_spec.rb
CHANGED
@@ -58,19 +58,35 @@ describe Rush::SshTunnel do
|
|
58
58
|
@tunnel.tunnel_options.should == {
|
59
59
|
:local_port => 1234,
|
60
60
|
:remote_port => 7770,
|
61
|
-
:ssh_host => 'spec.example.com'
|
62
|
-
:stall_command => 'sleep 9000'
|
61
|
+
:ssh_host => 'spec.example.com'
|
63
62
|
}
|
64
63
|
end
|
65
64
|
|
66
|
-
it "
|
65
|
+
it "ssh_stall_command uses an infinite loop for :timeout => :infinite" do
|
66
|
+
@tunnel.ssh_stall_command(:timeout => :infinite).should match(/while .* sleep .* done/)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "ssh_stall_command sleeps for the number of seconds given as the :timeout option" do
|
70
|
+
@tunnel.ssh_stall_command(:timeout => 123).should == "sleep 123"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "ssh_stall_command uses the default timeout when no options are given" do
|
74
|
+
@tunnel.ssh_stall_command.should == "sleep 9000"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "constructs the ssh tunnel command (everything but stall) from the options hash" do
|
67
78
|
@tunnel.should_receive(:tunnel_options).at_least(:once).and_return(
|
68
79
|
:local_port => 123,
|
69
80
|
:remote_port => 456,
|
70
|
-
:ssh_host => 'example.com'
|
71
|
-
:stall_command => 'stall'
|
81
|
+
:ssh_host => 'example.com'
|
72
82
|
)
|
73
|
-
@tunnel.
|
83
|
+
@tunnel.ssh_tunnel_command_without_stall.should == "ssh -f -L 123:127.0.0.1:456 example.com"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "combines the tunnel command without stall and the stall command into the final command" do
|
87
|
+
@tunnel.should_receive(:ssh_tunnel_command_without_stall).and_return('ssh command')
|
88
|
+
@tunnel.should_receive(:ssh_stall_command).and_return('sleep 123')
|
89
|
+
@tunnel.ssh_tunnel_command.should == 'ssh command "sleep 123"'
|
74
90
|
end
|
75
91
|
|
76
92
|
it "ssh_tunnel_command request that the port be set" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.2"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Wiggins
|
@@ -9,10 +9,36 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-03-12 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mongrel
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: rspec
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: session
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
16
42
|
description: A Ruby replacement for bash+ssh, providing both an interactive shell and a library. Manage both local and remote unix systems from a single client.
|
17
43
|
email: adam@heroku.com
|
18
44
|
executables:
|
@@ -33,7 +59,9 @@ files:
|
|
33
59
|
- lib/rush/config.rb
|
34
60
|
- lib/rush/dir.rb
|
35
61
|
- lib/rush/entry.rb
|
62
|
+
- lib/rush/exceptions.rb
|
36
63
|
- lib/rush/file.rb
|
64
|
+
- lib/rush/find_by.rb
|
37
65
|
- lib/rush/fixnum_ext.rb
|
38
66
|
- lib/rush/head_tail.rb
|
39
67
|
- lib/rush/local.rb
|
@@ -53,6 +81,7 @@ files:
|
|
53
81
|
- spec/dir_spec.rb
|
54
82
|
- spec/entry_spec.rb
|
55
83
|
- spec/file_spec.rb
|
84
|
+
- spec/find_by_spec.rb
|
56
85
|
- spec/fixnum_ext_spec.rb
|
57
86
|
- spec/local_spec.rb
|
58
87
|
- spec/process_spec.rb
|