rexec 1.1.10

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.
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module RExec
17
+ module VERSION #:nodoc:
18
+ MAJOR = 1
19
+ MINOR = 1
20
+ TINY = 10
21
+
22
+ STRING = [MAJOR, MINOR, TINY].join('.')
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ $connection.run do |object|
17
+ case(object[0])
18
+ when :bounce
19
+ $stderr.puts("Bouncing #{object[1].inspect}...")
20
+ $connection.send_object(object[1])
21
+ when :exception
22
+ $stderr.puts("Raising exception...")
23
+ raise Exception.new("I love exceptions!")
24
+ when :stop
25
+ $stderr.puts("Stopping connection manually...")
26
+ $connection.stop
27
+ when :stderr
28
+ $stderr.puts object[1]
29
+ $stderr.flush
30
+ end
31
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'pathname'
21
+
22
+ require 'rexec'
23
+ require 'rexec/daemon'
24
+
25
+ require 'webrick'
26
+ require 'webrick/https'
27
+ require 'xmlrpc/server'
28
+
29
+ # Very simple XMLRPC daemon
30
+ class TestDaemon < RExec::Daemon::Base
31
+ @@var_directory = "/tmp/ruby-test/var"
32
+
33
+ def self.run
34
+ puts "Starting server..."
35
+
36
+ @@rpc_server = WEBrick::HTTPServer.new(
37
+ :Port => 11235,
38
+ :BindAddress => "0.0.0.0",
39
+ :SSLEnable => true,
40
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
41
+ :SSLCertName => [["CN", WEBrick::Utils::getservername]])
42
+
43
+ @@listener = XMLRPC::WEBrickServlet.new
44
+
45
+ @@listener.add_handler("add") do |amount|
46
+ @@count ||= 0
47
+ @@count += amount
48
+ end
49
+
50
+ @@listener.add_handler("total") do
51
+ @@count
52
+ end
53
+
54
+ @@rpc_server.mount("/RPC2", @@listener)
55
+
56
+ $stdout.flush
57
+ $stderr.flush
58
+
59
+ @@rpc_server.start
60
+ end
61
+
62
+ def self.shutdown
63
+ puts "Shutting down server..."
64
+ @@rpc_server.shutdown
65
+ end
66
+ end
67
+
68
+ TestDaemon.daemonize
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+ require 'pathname'
20
+ require 'xmlrpc/client'
21
+ require 'test/unit'
22
+
23
+ class DaemonTest < Test::Unit::TestCase
24
+ DAEMON = (Pathname.new(__FILE__).dirname + "./daemon.rb").realpath
25
+ def setup
26
+ system(DAEMON, "start")
27
+
28
+ # Daemon takes a moment to become fully operational
29
+ sleep(5)
30
+ end
31
+
32
+ def teardown
33
+ system(DAEMON, "stop")
34
+ end
35
+
36
+ def test_connection
37
+ rpc = XMLRPC::Client.new_from_uri("https://localhost:11235")
38
+ rpc.call("add", 10)
39
+
40
+ total = rpc.call("total")
41
+
42
+ assert_equal 10, total
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+ require 'rexec'
20
+
21
+ CLIENT = <<EOF
22
+
23
+ $connection.run do |path|
24
+ listing = []
25
+
26
+ IO.popen("ls -la " + path.dump, "r+") do |ls|
27
+ listing = ls.readlines
28
+ end
29
+
30
+ $connection.send_object(listing)
31
+ end
32
+
33
+ EOF
34
+
35
+ command = ARGV[0] || "ruby"
36
+
37
+ puts "Starting server..."
38
+ RExec::start_server(CLIENT, command) do |conn, pid|
39
+ puts "Sending path..."
40
+ conn.send_object("/")
41
+
42
+ puts "Waiting for response..."
43
+ listing = conn.receive_object
44
+
45
+ puts "Received listing:"
46
+ listing.each do |entry|
47
+ puts "\t#{entry}"
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # This script is used to test actual remote connections
19
+ # e.g. ./test_remote.rb "ssh haru.oriontransfer.org"
20
+
21
+ require 'rubygems'
22
+
23
+ require 'test/unit'
24
+ require 'fileutils'
25
+ require 'pathname'
26
+ require 'rexec'
27
+
28
+ if $0.match("remote_server_test.rb") and ARGV.size > 0
29
+ COMMAND = ARGV.join(" ")
30
+ else
31
+ COMMAND = "ruby"
32
+ end
33
+
34
+ BOUNCE = "Apples and Oranges"
35
+
36
+ class RemoteServerTest < Test::Unit::TestCase
37
+ def test_block_execution
38
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
39
+
40
+ RExec::start_server(code.read, COMMAND, :passthrough => []) do |conn, pid|
41
+ conn.send_object([:bounce, BOUNCE])
42
+
43
+ assert_equal BOUNCE, conn.receive_object
44
+
45
+ conn.dump_errors
46
+
47
+ conn.stop
48
+ end
49
+ end
50
+
51
+ def test_result_execution
52
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
53
+
54
+ conn, pid = RExec::start_server(code.read, COMMAND, :passthrough => [])
55
+
56
+ conn.send_object([:bounce, BOUNCE])
57
+ assert_equal BOUNCE, conn.receive_object
58
+
59
+ conn.dump_errors
60
+
61
+ conn.stop
62
+ end
63
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'test/unit'
21
+ require 'fileutils'
22
+ require 'pathname'
23
+ require 'rexec'
24
+
25
+ class ServerTest < Test::Unit::TestCase
26
+ def test_local_execution
27
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
28
+ sobj = [1, 2, "three", 4]
29
+ stderr_text = "There was no error.. maybe?"
30
+ connection_started = false
31
+ object_received = false
32
+
33
+ RExec::start_server(code.read, "ruby", :passthrough => []) do |conn, pid|
34
+ connection_started = true
35
+ conn.send_object([:bounce, sobj])
36
+
37
+ assert_equal sobj, conn.receive_object
38
+
39
+ assert_raises(Exception) do
40
+ conn.send_object([:exception])
41
+ obj = conn.receive_object
42
+
43
+ puts "Received object which should have been exception: #{obj.inspect}"
44
+ end
45
+
46
+ conn.dump_errors
47
+ conn.send_object([:stderr, stderr_text])
48
+
49
+ puts "Attemping to read from #{conn.error.to_i}..."
50
+ assert_equal stderr_text, conn.error.readline.chomp
51
+
52
+ conn.stop
53
+ end
54
+
55
+ assert(connection_started, "Connection started")
56
+ end
57
+
58
+ def test_shell_execution
59
+ connection_started = false
60
+ code = Pathname.new(__FILE__).dirname + "client.rb"
61
+
62
+ test_obj = [1, 2, 3, 4, "five"]
63
+
64
+ RExec::start_server(code.read, "/bin/sh -c ruby", :passthrough => []) do |conn, pid|
65
+ connection_started = true
66
+ conn.send_object([:bounce, test_obj])
67
+
68
+ assert_equal test_obj, conn.receive_object
69
+
70
+ conn.stop
71
+ end
72
+
73
+ assert(connection_started, "Connection started")
74
+ end
75
+
76
+ def test_shell_execution_non_block
77
+ connection_started = false
78
+ code = Pathname.new(__FILE__).dirname + "client.rb"
79
+
80
+ test_obj = [1, 2, 3, 4, "five"]
81
+
82
+ conn, pid = RExec::start_server(code.read, "/bin/sh -c ruby", :passthrough => [])
83
+ conn.send_object([:bounce, test_obj])
84
+
85
+ assert_equal test_obj, conn.receive_object
86
+
87
+ conn.stop
88
+ end
89
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ input = $stdin.readline.chomp
19
+
20
+ $stdout.puts("STDOUT: " + input)
21
+ $stdout.flush
22
+
23
+ $stderr.puts("STDERR: " + input)
24
+ $stderr.flush
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'test/unit'
21
+ require 'fileutils'
22
+ require 'pathname'
23
+ require 'rexec'
24
+
25
+ require 'timeout'
26
+
27
+ class TaskTest < Test::Unit::TestCase
28
+ TASK_PATH = Pathname.new(__FILE__).dirname + "./task.rb"
29
+ TEXT = "The quick brown fox jumped over the lazy dog."
30
+ STDOUT_TEXT = "STDOUT: " + TEXT
31
+ STDERR_TEXT = "STDERR: " + TEXT
32
+
33
+ def test_script_execution
34
+ RExec::Task.open(TASK_PATH) do |task|
35
+ task.input.puts(TEXT)
36
+ task.input.close
37
+
38
+ assert_equal STDOUT_TEXT, task.output.readline.chomp
39
+ assert_equal STDERR_TEXT, task.error.readline.chomp
40
+ end
41
+ end
42
+
43
+ def test_ruby_execution
44
+ RExec::Task.open("ruby") do |task|
45
+ task.input.puts(TASK_PATH.read)
46
+ task.input.puts("\004")
47
+
48
+ task.input.puts(TEXT)
49
+ task.input.close
50
+
51
+ assert_equal STDOUT_TEXT, task.output.readline.chomp
52
+ assert_equal STDERR_TEXT, task.error.readline.chomp
53
+ end
54
+ end
55
+
56
+ def test_spawn_child
57
+ rd, wr = IO.pipe
58
+ pid = RExec::Task.spawn_child do
59
+ rd.close
60
+ wr.write(TEXT)
61
+ wr.close
62
+ exit(10)
63
+ end
64
+
65
+ wr.close
66
+
67
+ pid, status = Process.wait2(pid)
68
+
69
+ assert_equal rd.read, TEXT
70
+ assert_equal status, status
71
+ end
72
+
73
+ def test_spawn_daemon
74
+ rd, wr = IO.pipe
75
+
76
+ # We launch one daemon to start another. The first daemon will exit, but the second will keep on running.
77
+ ppid = RExec::Task.spawn_daemon do
78
+ RExec::Task.spawn_daemon do
79
+ rd.close
80
+ sleep 0.5
81
+ wr.puts(TEXT, Process.pid)
82
+ wr.close
83
+ sleep 0.5
84
+ end
85
+ end
86
+
87
+ wr.close
88
+
89
+ Timeout::timeout(5) do
90
+ until !RExec::Task.running?(ppid) do
91
+ sleep(0.1)
92
+ end
93
+
94
+ text = rd.readline.chomp
95
+ pid = rd.readline.chomp.to_i
96
+
97
+ assert_raises(EOFError) do
98
+ rd.readline
99
+ end
100
+
101
+ assert_equal text, TEXT
102
+ assert RExec::Task.running?(pid)
103
+
104
+ until !RExec::Task.running?(pid) do
105
+ sleep(0.1)
106
+ end
107
+ end
108
+ end
109
+
110
+ def test_task
111
+ test_results = Proc.new do |input, output, error|
112
+ input.puts TEXT
113
+ input.flush
114
+
115
+ assert_equal output.readline.chomp, STDOUT_TEXT
116
+ assert_equal error.readline.chomp, STDERR_TEXT
117
+ end
118
+
119
+ RExec::Task.open(TASK_PATH) do |task|
120
+ test_results.call(task.input, task.output, task.error)
121
+ end
122
+
123
+ rd, wr = IO.pipe
124
+
125
+ RExec::Task.open(TASK_PATH, :in => rd) do |task|
126
+ test_results.call(wr, task.output, task.error)
127
+ end
128
+
129
+ assert rd.closed?
130
+
131
+ assert_raises(Errno::EPIPE) do
132
+ wr.puts "The pipe is closed on the other side.."
133
+ end
134
+
135
+ in_rd, in_wr = IO.pipe
136
+ out_rd, out_wr = IO.pipe
137
+ err_rd, err_wr = IO.pipe
138
+
139
+ spawn_child_daemon = Proc.new do
140
+ task = RExec::Task.open(TASK_PATH, :in => in_rd, :out => out_wr, :err => err_wr, :daemonize => true)
141
+ end
142
+
143
+ task = RExec::Task.open(spawn_child_daemon, :daemonize => true)
144
+
145
+ until !task.running? do
146
+ sleep 0.1
147
+ end
148
+
149
+ test_results.call(in_wr, out_rd, err_rd)
150
+
151
+ assert !task.running?
152
+ end
153
+
154
+ def test_task_passthrough
155
+ script = "echo " + "Hello World!".dump + " | #{TASK_PATH.realpath.to_s.dump}"
156
+
157
+ RExec::Task.open(script, :passthrough => :all) do
158
+
159
+ end
160
+
161
+ [$stdin, $stdout, $stderr].each do |io|
162
+ assert !io.closed?
163
+ end
164
+ end
165
+ end