gorgon 0.4.5 → 0.5.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/lib/gorgon/originator.rb +6 -1
- data/lib/gorgon/progress_bar_view.rb +1 -1
- data/lib/gorgon/rsync_daemon.rb +59 -0
- data/lib/gorgon/source_tree_syncer.rb +1 -1
- data/lib/gorgon/unknown_runner.rb +9 -9
- data/lib/gorgon/version.rb +1 -1
- data/spec/originator_spec.rb +23 -1
- data/spec/rsync_daemon_spec.rb +75 -0
- data/spec/source_tree_syncer_spec.rb +0 -18
- metadata +8 -12
data/.gitignore
CHANGED
data/lib/gorgon/originator.rb
CHANGED
@@ -4,6 +4,7 @@ require 'gorgon/job_state'
|
|
4
4
|
require 'gorgon/progress_bar_view'
|
5
5
|
require 'gorgon/originator_logger'
|
6
6
|
require 'gorgon/failures_printer'
|
7
|
+
require 'gorgon/rsync_daemon'
|
7
8
|
|
8
9
|
require 'awesome_print'
|
9
10
|
require 'etc'
|
@@ -14,6 +15,7 @@ class Originator
|
|
14
15
|
|
15
16
|
def initialize
|
16
17
|
@configuration = nil
|
18
|
+
@rsync_daemon = RsyncDaemon.new
|
17
19
|
end
|
18
20
|
|
19
21
|
def originate
|
@@ -44,11 +46,13 @@ class Originator
|
|
44
46
|
@job_state.cancel
|
45
47
|
|
46
48
|
@protocol.disconnect
|
49
|
+
@rsync_daemon.stop
|
47
50
|
end
|
48
51
|
|
49
52
|
def publish
|
50
53
|
@logger = OriginatorLogger.new configuration[:originator_log_file]
|
51
54
|
@protocol = OriginatorProtocol.new @logger
|
55
|
+
@rsync_daemon.start
|
52
56
|
|
53
57
|
EventMachine.run do
|
54
58
|
@logger.log "Connecting..."
|
@@ -72,6 +76,7 @@ class Originator
|
|
72
76
|
if @job_state.is_job_complete?
|
73
77
|
@logger.log "Job is done"
|
74
78
|
@protocol.disconnect
|
79
|
+
@rsync_daemon.stop
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
@@ -123,7 +128,7 @@ class Originator
|
|
123
128
|
def job_definition
|
124
129
|
job_config = configuration[:job]
|
125
130
|
if !job_config.has_key?(:source_tree_path)
|
126
|
-
job_config[:source_tree_path] = "
|
131
|
+
job_config[:source_tree_path] = "rsync://#{local_ip_addr}:43434/src"
|
127
132
|
end
|
128
133
|
JobDefinition.new(configuration[:job])
|
129
134
|
end
|
@@ -66,7 +66,7 @@ private
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def output_gorgon_crash_message payload
|
69
|
-
$stderr.puts "\nA #{'crash'.red}
|
69
|
+
$stderr.puts "\nA #{'crash'.red} occurred at '#{payload[:hostname].colorize Colors::HOST}':"
|
70
70
|
$stderr.puts payload[:stdout].yellow unless payload[:stdout].to_s.strip.length == 0
|
71
71
|
$stderr.puts payload[:stderr].yellow unless payload[:stderr].to_s.strip.length == 0
|
72
72
|
if @progress_bar.nil?
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
|
3
|
+
class RsyncDaemon
|
4
|
+
#for now, creates a readonly rsync daemon for the current directory on the mountpath "src"
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@project_directory = Dir.pwd
|
8
|
+
@started = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def start
|
12
|
+
return if @started
|
13
|
+
@tmpdir = Dir.mktmpdir("gorgon")
|
14
|
+
success = nil
|
15
|
+
Dir.chdir(@tmpdir) do
|
16
|
+
File.write("rsyncd.conf", rsyncd_config_string(@project_directory))
|
17
|
+
|
18
|
+
success = Kernel.system("rsync --daemon --config rsyncd.conf")
|
19
|
+
end
|
20
|
+
|
21
|
+
if success
|
22
|
+
@started = true
|
23
|
+
return true
|
24
|
+
else
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop
|
30
|
+
return unless @started
|
31
|
+
|
32
|
+
success = nil
|
33
|
+
Dir.chdir(@tmpdir) do
|
34
|
+
pid = File.read("rsync.pid")
|
35
|
+
success = Kernel.system("kill #{pid}")
|
36
|
+
end
|
37
|
+
|
38
|
+
if success
|
39
|
+
@started = false
|
40
|
+
return true
|
41
|
+
else
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def rsyncd_config_string(shared_dir)
|
49
|
+
return <<-EOF
|
50
|
+
port = 43434
|
51
|
+
pid file = rsync.pid
|
52
|
+
|
53
|
+
[src]
|
54
|
+
path = #{@project_directory}
|
55
|
+
read only = true
|
56
|
+
use chroot = false
|
57
|
+
EOF
|
58
|
+
end
|
59
|
+
end
|
@@ -5,7 +5,7 @@ class SourceTreeSyncer
|
|
5
5
|
attr_reader :sys_command, :output, :errors
|
6
6
|
|
7
7
|
SYS_COMMAND = 'rsync'
|
8
|
-
OPTS = "-azr --timeout=5
|
8
|
+
OPTS = "-azr --timeout=5"
|
9
9
|
EXCLUDE_OPT = "--exclude"
|
10
10
|
|
11
11
|
def initialize source_tree_path
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
class UnknownRunner
|
2
|
+
UNKNOWN_FRAMEWORK_MSG = "Unknown Test Framework. Gorgon only supports Test::Unit, MiniTest, and RSpec"
|
3
|
+
def self.run_file(filename)
|
4
|
+
raise UNKNOWN_FRAMEWORK_MSG
|
5
|
+
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def self.runner
|
8
|
+
:unknown_framework
|
9
|
+
end
|
10
|
+
end
|
data/lib/gorgon/version.rb
CHANGED
data/spec/originator_spec.rb
CHANGED
@@ -10,9 +10,11 @@ describe Originator do
|
|
10
10
|
:add_observer => nil)}
|
11
11
|
let(:progress_bar_view){ stub("Progress Bar View", :show => nil)}
|
12
12
|
let(:originator_logger){ stub("Originator Logger", :log => nil, :log_message => nil)}
|
13
|
+
let(:rsync_daemon) { stub("Rsync Daemon", :start => true, :stop => true)}
|
13
14
|
|
14
15
|
before do
|
15
16
|
OriginatorLogger.stub(:new).and_return originator_logger
|
17
|
+
RsyncDaemon.stub(:new).and_return rsync_daemon
|
16
18
|
@originator = Originator.new
|
17
19
|
end
|
18
20
|
|
@@ -34,6 +36,12 @@ describe Originator do
|
|
34
36
|
progress_bar_view.should_receive(:show)
|
35
37
|
@originator.publish
|
36
38
|
end
|
39
|
+
|
40
|
+
it "starts the rsync daemon" do
|
41
|
+
rsync_daemon.should_receive(:start)
|
42
|
+
|
43
|
+
@originator.publish
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
describe "#cancel_job" do
|
@@ -54,6 +62,13 @@ describe Originator do
|
|
54
62
|
@originator.publish
|
55
63
|
@originator.cancel_job
|
56
64
|
end
|
65
|
+
|
66
|
+
it "stops the rsync daemon" do
|
67
|
+
rsync_daemon.should_receive(:stop)
|
68
|
+
|
69
|
+
@originator.publish
|
70
|
+
@originator.cancel_job
|
71
|
+
end
|
57
72
|
end
|
58
73
|
|
59
74
|
describe "#cleanup_if_job_complete" do
|
@@ -73,6 +88,13 @@ describe Originator do
|
|
73
88
|
protocol.should_receive(:disconnect)
|
74
89
|
@originator.cleanup_if_job_complete
|
75
90
|
end
|
91
|
+
|
92
|
+
it "stops the rsync daemon" do
|
93
|
+
job_state.stub!(:is_job_complete?).and_return true
|
94
|
+
rsync_daemon.should_receive(:stop)
|
95
|
+
|
96
|
+
@originator.cleanup_if_job_complete
|
97
|
+
end
|
76
98
|
end
|
77
99
|
|
78
100
|
describe "#handle_reply" do
|
@@ -123,7 +145,7 @@ describe Originator do
|
|
123
145
|
it "builds source_tree_path if it was not specified in the configuration" do
|
124
146
|
@originator.stub!(:configuration).and_return({:job => {}})
|
125
147
|
UDPSocket.any_instance.stub(:addr).and_return(["1.1.1.1"])
|
126
|
-
@originator.job_definition.source_tree_path.should == "
|
148
|
+
@originator.job_definition.source_tree_path.should == "rsync://1.1.1.1:43434/src"
|
127
149
|
end
|
128
150
|
|
129
151
|
it "returns source_tree_path specified in configuration if it is present" do
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'gorgon/rsync_daemon'
|
2
|
+
|
3
|
+
describe RsyncDaemon do
|
4
|
+
before(:each) do
|
5
|
+
Kernel.stub(:system => true)
|
6
|
+
Dir.stub(:mktmpdir => "loltmpdir", :pwd => "/lol/hax")
|
7
|
+
Dir.stub(:chdir).and_yield
|
8
|
+
File.stub(:write => 100, :read => "12345")
|
9
|
+
@r = RsyncDaemon.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "starts the rsync daemon" do
|
13
|
+
Kernel.should_receive(:system).with("rsync --daemon --config rsyncd.conf")
|
14
|
+
|
15
|
+
@r.start
|
16
|
+
end
|
17
|
+
|
18
|
+
it "creates a temporary directory for the configuration and pid files" do
|
19
|
+
Dir.should_receive(:mktmpdir).with("gorgon").and_return("loltmpdir")
|
20
|
+
Dir.should_receive(:chdir).with("loltmpdir")
|
21
|
+
|
22
|
+
@r.start
|
23
|
+
end
|
24
|
+
|
25
|
+
it "writes the config file" do
|
26
|
+
valid_config = <<-EOF
|
27
|
+
port = 43434
|
28
|
+
pid file = rsync.pid
|
29
|
+
|
30
|
+
[src]
|
31
|
+
path = /lol/hax
|
32
|
+
read only = true
|
33
|
+
use chroot = false
|
34
|
+
EOF
|
35
|
+
File.should_receive(:write).with("rsyncd.conf", valid_config)
|
36
|
+
|
37
|
+
@r.start
|
38
|
+
end
|
39
|
+
|
40
|
+
it "reports when an error has prevented startup" do
|
41
|
+
Kernel.should_receive(:system).and_return(false)
|
42
|
+
|
43
|
+
@r.start.should == false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "only starts once" do
|
47
|
+
Kernel.should_receive(:system).once
|
48
|
+
|
49
|
+
@r.start
|
50
|
+
@r.start
|
51
|
+
end
|
52
|
+
|
53
|
+
it "stops the rsync daemon" do
|
54
|
+
@r.start
|
55
|
+
|
56
|
+
File.should_receive(:read).with("rsync.pid").and_return("12345")
|
57
|
+
Kernel.should_receive(:system).with("kill 12345")
|
58
|
+
|
59
|
+
@r.stop
|
60
|
+
end
|
61
|
+
|
62
|
+
it "only tries to stop if the daemon is started" do
|
63
|
+
Kernel.should_not_receive(:system)
|
64
|
+
|
65
|
+
@r.stop
|
66
|
+
end
|
67
|
+
|
68
|
+
it "can be restarted" do
|
69
|
+
Kernel.should_receive(:system).exactly(3).times
|
70
|
+
|
71
|
+
@r.start
|
72
|
+
@r.stop
|
73
|
+
@r.start
|
74
|
+
end
|
75
|
+
end
|
@@ -57,24 +57,6 @@ describe SourceTreeSyncer.new("") do
|
|
57
57
|
@syncer.sync
|
58
58
|
end
|
59
59
|
|
60
|
-
it "use NumberOfPasswordPrompts 0 as ssh option to avoid password prompts that will hang the listener" do
|
61
|
-
opt = /--rsh='ssh .*-o NumberOfPasswordPrompts=0.*'/
|
62
|
-
Open4.should_receive(:popen4).with(opt)
|
63
|
-
@syncer.sync
|
64
|
-
end
|
65
|
-
|
66
|
-
it "set UserKnownHostsFile to /dev/null so we avoid hosts id changes and eavesdropping warnings in futures connections" do
|
67
|
-
opt = /ssh .*-o UserKnownHostsFile=\/dev\/null/
|
68
|
-
Open4.should_receive(:popen4).with(opt)
|
69
|
-
@syncer.sync
|
70
|
-
end
|
71
|
-
|
72
|
-
it "set StrictHostKeyChecking to 'no' to avoid confirmation prompt of connection to unkown host" do
|
73
|
-
opt = /ssh .*-o StrictHostKeyChecking=no/
|
74
|
-
Open4.should_receive(:popen4).with(opt)
|
75
|
-
@syncer.sync
|
76
|
-
end
|
77
|
-
|
78
60
|
it "uses io timeout to avoid listener hanging forever in case rsync asks for any input" do
|
79
61
|
opt = /--timeout=5/
|
80
62
|
Open4.should_receive(:popen4).with(opt)
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gorgon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0.rc1
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Justin Fitzsimmons
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-10-
|
16
|
+
date: 2013-10-31 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: rake
|
@@ -237,6 +237,7 @@ files:
|
|
237
237
|
- lib/gorgon/pipe_forker.rb
|
238
238
|
- lib/gorgon/progress_bar_view.rb
|
239
239
|
- lib/gorgon/rspec_runner.rb
|
240
|
+
- lib/gorgon/rsync_daemon.rb
|
240
241
|
- lib/gorgon/settings/files_content.rb
|
241
242
|
- lib/gorgon/settings/initial_files_creator.rb
|
242
243
|
- lib/gorgon/settings/rails_project_files_content.rb
|
@@ -265,6 +266,7 @@ files:
|
|
265
266
|
- spec/pipe_forker_spec.rb
|
266
267
|
- spec/progress_bar_view_spec.rb
|
267
268
|
- spec/rspec_runner_spec.rb
|
269
|
+
- spec/rsync_daemon_spec.rb
|
268
270
|
- spec/source_tree_syncer_spec.rb
|
269
271
|
- spec/unknown_runner_spec.rb
|
270
272
|
- spec/worker_manager_spec.rb
|
@@ -281,21 +283,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
281
283
|
- - ! '>='
|
282
284
|
- !ruby/object:Gem::Version
|
283
285
|
version: '0'
|
284
|
-
segments:
|
285
|
-
- 0
|
286
|
-
hash: 2798141738488026768
|
287
286
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
288
287
|
none: false
|
289
288
|
requirements:
|
290
|
-
- - ! '
|
289
|
+
- - ! '>'
|
291
290
|
- !ruby/object:Gem::Version
|
292
|
-
version:
|
293
|
-
segments:
|
294
|
-
- 0
|
295
|
-
hash: 2798141738488026768
|
291
|
+
version: 1.3.1
|
296
292
|
requirements: []
|
297
293
|
rubyforge_project: gorgon
|
298
|
-
rubygems_version: 1.8.
|
294
|
+
rubygems_version: 1.8.24
|
299
295
|
signing_key:
|
300
296
|
specification_version: 3
|
301
297
|
summary: Distributed testing for ruby with centralized management
|