deep_test_pre 2.0
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/CHANGELOG +47 -0
- data/README.rdoc +199 -0
- data/Rakefile +137 -0
- data/lib/deep_test.rb +78 -0
- data/lib/deep_test/agent.rb +108 -0
- data/lib/deep_test/central_command.rb +165 -0
- data/lib/deep_test/cpu_info.rb +22 -0
- data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
- data/lib/deep_test/database/setup_listener.rb +116 -0
- data/lib/deep_test/deadlock_detector.rb +7 -0
- data/lib/deep_test/demon.rb +25 -0
- data/lib/deep_test/distributed/beachhead.rb +104 -0
- data/lib/deep_test/distributed/dispatch_controller.rb +60 -0
- data/lib/deep_test/distributed/establish_beachhead.rb +19 -0
- data/lib/deep_test/distributed/filename_resolver.rb +40 -0
- data/lib/deep_test/distributed/landing_fleet.rb +30 -0
- data/lib/deep_test/distributed/landing_ship.rb +60 -0
- data/lib/deep_test/distributed/remote_deployment.rb +56 -0
- data/lib/deep_test/distributed/rsync.rb +50 -0
- data/lib/deep_test/distributed/shell_environment.rb +50 -0
- data/lib/deep_test/distributed/ssh_client_connection_info.rb +14 -0
- data/lib/deep_test/extensions/object_extension.rb +40 -0
- data/lib/deep_test/failure_message.rb +19 -0
- data/lib/deep_test/lib_root.rb +4 -0
- data/lib/deep_test/listener_list.rb +17 -0
- data/lib/deep_test/local_deployment.rb +46 -0
- data/lib/deep_test/logger.rb +32 -0
- data/lib/deep_test/main.rb +41 -0
- data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
- data/lib/deep_test/metrics/data.rb +34 -0
- data/lib/deep_test/metrics/measurement.rb +39 -0
- data/lib/deep_test/null_listener.rb +62 -0
- data/lib/deep_test/options.rb +113 -0
- data/lib/deep_test/proxy_io.rb +77 -0
- data/lib/deep_test/rake_tasks.rb +13 -0
- data/lib/deep_test/result_reader.rb +40 -0
- data/lib/deep_test/rspec_detector.rb +21 -0
- data/lib/deep_test/spec.rb +17 -0
- data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
- data/lib/deep_test/spec/extensions/example_methods.rb +52 -0
- data/lib/deep_test/spec/extensions/options.rb +43 -0
- data/lib/deep_test/spec/extensions/spec_task.rb +21 -0
- data/lib/deep_test/spec/runner.rb +72 -0
- data/lib/deep_test/spec/work_result.rb +35 -0
- data/lib/deep_test/spec/work_unit.rb +59 -0
- data/lib/deep_test/test.rb +10 -0
- data/lib/deep_test/test/extensions/error.rb +14 -0
- data/lib/deep_test/test/run_test_suite.rb +5 -0
- data/lib/deep_test/test/runner.rb +24 -0
- data/lib/deep_test/test/supervised_test_suite.rb +48 -0
- data/lib/deep_test/test/work_result.rb +35 -0
- data/lib/deep_test/test/work_unit.rb +40 -0
- data/lib/deep_test/test_task.rb +47 -0
- data/lib/deep_test/ui/console.rb +74 -0
- data/lib/deep_test/ui/null.rb +17 -0
- data/lib/deep_test/warlock.rb +146 -0
- data/lib/telegraph.rb +29 -0
- data/lib/telegraph/ack_sequence.rb +14 -0
- data/lib/telegraph/logging.rb +20 -0
- data/lib/telegraph/message.rb +39 -0
- data/lib/telegraph/operator.rb +47 -0
- data/lib/telegraph/switchboard.rb +57 -0
- data/lib/telegraph/wire.rb +73 -0
- data/test/deep_test/agent_test.rb +175 -0
- data/test/deep_test/central_command_test.rb +147 -0
- data/test/deep_test/cpu_info_test.rb +33 -0
- data/test/deep_test/database/mysql_setup_listener_test.rb +18 -0
- data/test/deep_test/demon_test.rb +23 -0
- data/test/deep_test/distributed/beachhead_test.rb +67 -0
- data/test/deep_test/distributed/dispatch_controller_test.rb +162 -0
- data/test/deep_test/distributed/filename_resolver_test.rb +56 -0
- data/test/deep_test/distributed/landing_fleet_test.rb +55 -0
- data/test/deep_test/distributed/landing_ship_test.rb +48 -0
- data/test/deep_test/distributed/remote_deployment_test.rb +134 -0
- data/test/deep_test/distributed/rsync_test.rb +47 -0
- data/test/deep_test/distributed/shell_environment_test.rb +108 -0
- data/test/deep_test/distributed/ssh_client_connection_info_test.rb +34 -0
- data/test/deep_test/extensions/object_extension_test.rb +37 -0
- data/test/deep_test/listener_list_test.rb +22 -0
- data/test/deep_test/local_deployment_test.rb +19 -0
- data/test/deep_test/logger_test.rb +38 -0
- data/test/deep_test/main_test.rb +12 -0
- data/test/deep_test/marshallable_exception_wrapper_test.rb +46 -0
- data/test/deep_test/metrics/data_test.rb +22 -0
- data/test/deep_test/metrics/measurement_test.rb +18 -0
- data/test/deep_test/proxy_io_test.rb +104 -0
- data/test/deep_test/result_reader_test.rb +128 -0
- data/test/deep_test/test/extensions/error_test.rb +42 -0
- data/test/deep_test/test/runner_test.rb +11 -0
- data/test/deep_test/test/supervised_test_suite_test.rb +107 -0
- data/test/deep_test/test/work_result_test.rb +85 -0
- data/test/deep_test/test/work_unit_test.rb +63 -0
- data/test/deep_test/test_task_test.rb +15 -0
- data/test/deep_test/ui/console_test.rb +13 -0
- data/test/deep_test/warlock_test.rb +40 -0
- data/test/test_helper.rb +30 -0
- data/test/test_task_test.rb +75 -0
- metadata +156 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Demon
|
|
3
|
+
def forked(name, options, demon_args)
|
|
4
|
+
options.connect_to_central_command do |wire|
|
|
5
|
+
ProxyIO.replace_stdout_stderr!(wire) do
|
|
6
|
+
begin
|
|
7
|
+
catch(:exit_demon) do
|
|
8
|
+
Signal.trap("TERM") { throw :exit_demon }
|
|
9
|
+
execute *demon_args
|
|
10
|
+
end
|
|
11
|
+
rescue SystemExit => e
|
|
12
|
+
raise
|
|
13
|
+
rescue Exception => e
|
|
14
|
+
FailureMessage.show self.class.name, "Process #{Process.pid} exiting with excetion: #{e.class}: #{e.message}"
|
|
15
|
+
raise
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def execute(*args)
|
|
22
|
+
raise "#{self.class} must implement the execute method to be a Demon"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class Beachhead < LocalDeployment
|
|
4
|
+
include Demon
|
|
5
|
+
|
|
6
|
+
MERCY_KILLING_GRACE_PERIOD = 10 * 60 unless defined?(MERCY_KILLING_GRACE_PERIOD)
|
|
7
|
+
|
|
8
|
+
def initialize(base_path, options)
|
|
9
|
+
super options
|
|
10
|
+
@base_path = base_path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def launch_mercy_killer(grace_period)
|
|
14
|
+
Thread.new do
|
|
15
|
+
sleep grace_period
|
|
16
|
+
exit(0) unless agents_deployed?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load_files(files)
|
|
21
|
+
spec_support_path = File.expand_path(File.dirname(__FILE__) + "/../spec")
|
|
22
|
+
Dir.chdir @base_path
|
|
23
|
+
resolver = FilenameResolver.new(@base_path)
|
|
24
|
+
files.each do |file|
|
|
25
|
+
load resolver.resolve(file)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Load rspec support if rspec is available now that we've loaded the host project files
|
|
29
|
+
#
|
|
30
|
+
DeepTest::RSpecDetector.if_rspec_available do
|
|
31
|
+
require spec_support_path
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def deploy_agents
|
|
36
|
+
@agents_deployed = true
|
|
37
|
+
super
|
|
38
|
+
warlock.exit_when_none_running
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def agents_deployed?
|
|
42
|
+
@agents_deployed
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def forked(*args)
|
|
46
|
+
$stdout.reopen("/dev/null")
|
|
47
|
+
$stderr.reopen("/dev/null")
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def execute(innie, outie, grace_period)
|
|
52
|
+
innie.close
|
|
53
|
+
|
|
54
|
+
switchboard = Telegraph::Switchboard.new
|
|
55
|
+
operator = Telegraph::Operator.listen "0.0.0.0", 0, switchboard
|
|
56
|
+
|
|
57
|
+
DeepTest.logger.debug { "Beachhead started on port #{operator.port}" }
|
|
58
|
+
|
|
59
|
+
outie.write operator.port
|
|
60
|
+
outie.close
|
|
61
|
+
|
|
62
|
+
launch_mercy_killer grace_period
|
|
63
|
+
|
|
64
|
+
loop do
|
|
65
|
+
begin
|
|
66
|
+
switchboard.process_messages :timeout => 1 do |message, wire|
|
|
67
|
+
case message.body
|
|
68
|
+
when LoadFiles
|
|
69
|
+
load_files message.body.files
|
|
70
|
+
when DeployAgents
|
|
71
|
+
deploy_agents
|
|
72
|
+
wire.send_message Done
|
|
73
|
+
operator.shutdown
|
|
74
|
+
break
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def daemonize(grace_period = MERCY_KILLING_GRACE_PERIOD)
|
|
82
|
+
innie, outie = IO.pipe
|
|
83
|
+
|
|
84
|
+
warlock.start "Beachhead", self, innie, outie, grace_period
|
|
85
|
+
|
|
86
|
+
outie.close
|
|
87
|
+
port = innie.gets
|
|
88
|
+
innie.close
|
|
89
|
+
port.to_i
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
unless defined? DeployAgents
|
|
93
|
+
DeployAgents = "DeployAgents"
|
|
94
|
+
Done = "Done"
|
|
95
|
+
class LoadFiles
|
|
96
|
+
attr_reader :files
|
|
97
|
+
def initialize(files)
|
|
98
|
+
@files = files
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class DispatchController
|
|
4
|
+
def initialize(options, receivers)
|
|
5
|
+
@options = options
|
|
6
|
+
@receivers = receivers
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dispatch(method_name, *args)
|
|
10
|
+
dispatch_with_options(method_name, {}, *args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dispatch_with_options(method_name, options, *args)
|
|
14
|
+
raise NoDispatchReceiversError if @receivers.empty?
|
|
15
|
+
|
|
16
|
+
@options.ui_instance.dispatch_starting(method_name)
|
|
17
|
+
|
|
18
|
+
threads = @receivers.map do |r|
|
|
19
|
+
Thread.new do
|
|
20
|
+
begin
|
|
21
|
+
Thread.current[:receiver] = r
|
|
22
|
+
r.send method_name, *args
|
|
23
|
+
rescue Exception => e
|
|
24
|
+
Thread.current[:original_exception] = e
|
|
25
|
+
raise
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
results = []
|
|
31
|
+
threads.each do |t|
|
|
32
|
+
begin
|
|
33
|
+
results << t.value
|
|
34
|
+
rescue Timeout::Error
|
|
35
|
+
@receivers.delete t[:receiver]
|
|
36
|
+
DeepTest.logger.error { "Timeout dispatching #{method_name} to #{description t[:receiver]}" }
|
|
37
|
+
rescue Exception => this_exception
|
|
38
|
+
@receivers.delete t[:receiver]
|
|
39
|
+
DeepTest.logger.error { "Exception while dispatching #{method_name} to #{description t[:receiver]}:" }
|
|
40
|
+
|
|
41
|
+
e = t[:original_exception] || this_exception
|
|
42
|
+
DeepTest.logger.error { "#{e.class}: #{e.message}" }
|
|
43
|
+
e.backtrace.each {|l| DeepTest.logger.error { l } }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
results
|
|
48
|
+
ensure
|
|
49
|
+
@options.ui_instance.dispatch_finished(method_name)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def description(receiver)
|
|
53
|
+
receiver.inspect
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class NoDispatchReceiversError < StandardError; end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../deep_test"
|
|
2
|
+
options = DeepTest::Options.from_command_line(ENV['OPTIONS'])
|
|
3
|
+
ENV['DEEP_TEST_LOG_LEVEL'] = options.environment_log_level
|
|
4
|
+
options.ssh_client_connection_info = DeepTest::Distributed::SshClientConnectionInfo.new
|
|
5
|
+
|
|
6
|
+
DeepTest.logger.debug { "mirror establish_beachhead for #{options.origin_hostname}" }
|
|
7
|
+
|
|
8
|
+
STDIN.close
|
|
9
|
+
|
|
10
|
+
beachhead_port = DeepTest::Distributed::Beachhead.new(
|
|
11
|
+
File.join(options.mirror_path, File.basename(options.sync_options[:source])),
|
|
12
|
+
options
|
|
13
|
+
).daemonize
|
|
14
|
+
|
|
15
|
+
puts "Beachhead port: #{beachhead_port}"
|
|
16
|
+
$stdout.flush
|
|
17
|
+
|
|
18
|
+
exit!(0)
|
|
19
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class FilenameResolver
|
|
4
|
+
def initialize(base_path)
|
|
5
|
+
@base_path = base_path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def resolve(filename)
|
|
9
|
+
return resolve("/" + filename) unless filename[0] == ?/
|
|
10
|
+
|
|
11
|
+
return filename.sub(@cached_replaced_path, @base_path) if @cached_replaced_path
|
|
12
|
+
|
|
13
|
+
each_potential_filename(filename) do |potential_filename|
|
|
14
|
+
if File.exist?(potential_filename)
|
|
15
|
+
cache_resolution(filename, potential_filename)
|
|
16
|
+
return potential_filename
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
raise "Filename resolution failed. Cannot resolve #{filename} within #{@base_path}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cache_resolution(original_filename, resolved_filename)
|
|
24
|
+
@cached_replaced_path = original_filename.sub(
|
|
25
|
+
resolved_filename.sub(@base_path, ""), ""
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def each_potential_filename(filename)
|
|
30
|
+
basename = File.basename(filename)
|
|
31
|
+
dirs = File.dirname(filename).split('/')
|
|
32
|
+
|
|
33
|
+
begin
|
|
34
|
+
dirs.shift
|
|
35
|
+
yield [@base_path, dirs, basename].flatten.join('/')
|
|
36
|
+
end until dirs.empty?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class LandingFleet
|
|
4
|
+
def initialize(options, slaves)
|
|
5
|
+
DeepTest.logger.debug { "LandingFleet#initialize #{slaves.length} slaves" }
|
|
6
|
+
@slave_controller = DispatchController.new(options, slaves)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def establish_beachhead(options)
|
|
10
|
+
DeepTest.logger.debug { "dispatch establish_beachhead for #{options.origin_hostname}" }
|
|
11
|
+
@slave_controller.dispatch :establish_beachhead, options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def push_code(options)
|
|
15
|
+
DeepTest.logger.debug { "dispatch push_code for #{options.origin_hostname}" }
|
|
16
|
+
@slave_controller.dispatch :push_code, options
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def load_files(files)
|
|
20
|
+
DeepTest.logger.debug { "dispatch load_files" }
|
|
21
|
+
@slave_controller.dispatch :load_files, files
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deploy_agents
|
|
25
|
+
DeepTest.logger.debug { "dispatch deploy_agents" }
|
|
26
|
+
@slave_controller.dispatch :deploy_agents
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class LandingShip
|
|
4
|
+
def initialize(config)
|
|
5
|
+
@config = config
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def push_code(options)
|
|
9
|
+
RSync.push(@config[:address], options.sync_options, options.mirror_path)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def establish_beachhead(options)
|
|
13
|
+
command = "#{ssh_command(options)} '#{spawn_command(options)}' 2>&1"
|
|
14
|
+
DeepTest.logger.debug { "Establishing Beachhead: #{command}" }
|
|
15
|
+
|
|
16
|
+
output = `#{command}`
|
|
17
|
+
output.each do |line|
|
|
18
|
+
if DeepTest.logger.level == Logger::DEBUG
|
|
19
|
+
puts output
|
|
20
|
+
end
|
|
21
|
+
if line =~ /Beachhead port: (.+)/
|
|
22
|
+
@wire = Telegraph::Wire.connect(@config[:address], $1.to_i)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
raise "LandingShip unable to establish Beachhead. Output from #{@config[:address]} was:\n#{output}" unless @wire
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def load_files(files)
|
|
29
|
+
@wire.send_message Beachhead::LoadFiles.new(files)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def deploy_agents
|
|
33
|
+
@wire.send_message Beachhead::DeployAgents
|
|
34
|
+
begin
|
|
35
|
+
message = @wire.next_message :timeout => 1
|
|
36
|
+
raise "Unexpected message from Beachhead: #{message.inspect}" unless message.body == Beachhead::Done
|
|
37
|
+
rescue Telegraph::NoMessageAvailable
|
|
38
|
+
retry
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def ssh_command(options)
|
|
43
|
+
username_option = if options.sync_options[:username]
|
|
44
|
+
" -l #{options.sync_options[:username]}"
|
|
45
|
+
else
|
|
46
|
+
""
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
"ssh -4 #{@config[:address]}#{username_option}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def spawn_command(options)
|
|
53
|
+
"#{ShellEnvironment.like_login} && " +
|
|
54
|
+
"cd #{options.mirror_path} && " +
|
|
55
|
+
"OPTIONS=#{options.to_command_line} " +
|
|
56
|
+
"ruby lib/deep_test/distributed/establish_beachhead.rb"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class RemoteDeployment
|
|
4
|
+
def initialize(options, landing_fleet, failover_deployment)
|
|
5
|
+
@failover_deployment = failover_deployment
|
|
6
|
+
@options = options
|
|
7
|
+
@landing_fleet = landing_fleet
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def load_files(filelist)
|
|
11
|
+
# load one file before calling listeners to make sure environment has
|
|
12
|
+
# been initialized as expected
|
|
13
|
+
#
|
|
14
|
+
load filelist.first
|
|
15
|
+
@options.new_listener_list.before_sync
|
|
16
|
+
|
|
17
|
+
t = Thread.new do
|
|
18
|
+
@landing_fleet.push_code(@options)
|
|
19
|
+
@landing_fleet.establish_beachhead(@options)
|
|
20
|
+
@landing_fleet.load_files filelist
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
filelist[1..-1].each {|f| load f}
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
t.join
|
|
27
|
+
rescue => e
|
|
28
|
+
# The failover here doesn't invoke load_files on the failover_deployment
|
|
29
|
+
# because it will be a LocalDeployment, which forks from the current
|
|
30
|
+
# process. The fact that we depend in this here is damp...
|
|
31
|
+
#
|
|
32
|
+
fail_over("load_files", e)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def deploy_agents
|
|
37
|
+
DeepTest.logger.debug { "RemoteDeployment deploying agents with #{@landing_fleet}" }
|
|
38
|
+
@landing_fleet.deploy_agents
|
|
39
|
+
rescue => e
|
|
40
|
+
raise if failed_over?
|
|
41
|
+
fail_over("deploy_agents", e)
|
|
42
|
+
retry
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def fail_over(method, exception)
|
|
46
|
+
DeepTest.logger.debug { "RemoteDeployment failing over on #{method}." }
|
|
47
|
+
@options.ui_instance.distributed_failover_to_local(method, exception)
|
|
48
|
+
@landing_fleet = @failover_deployment
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def failed_over?
|
|
52
|
+
@landing_fleet == @failover_deployment
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class RSync
|
|
4
|
+
def self.push(address, sync_options, destination)
|
|
5
|
+
sync(:push, address, sync_options, destination)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.sync(operation, address, sync_options, destination)
|
|
9
|
+
command = Args.new(address, sync_options).send("#{operation}_command",
|
|
10
|
+
destination)
|
|
11
|
+
|
|
12
|
+
DeepTest.logger.debug { "rsycing: #{command}" }
|
|
13
|
+
successful = system command
|
|
14
|
+
raise "RSync Failed!!" unless successful
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Args
|
|
18
|
+
def initialize(address, sync_options)
|
|
19
|
+
@address = address
|
|
20
|
+
@sync_options = sync_options
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def pull_command(destination)
|
|
24
|
+
command remote_location(@sync_options[:source]), destination
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def push_command(destination)
|
|
28
|
+
command @sync_options[:source], remote_location(destination)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def command(source, destination)
|
|
32
|
+
# The '/' after source tells rsync to copy the contents
|
|
33
|
+
# of source to destination, rather than the source directory
|
|
34
|
+
# itself
|
|
35
|
+
"rsync -az --delete #{@sync_options[:rsync_options]} #{DeepTest::LIB_ROOT} #{source} #{destination}".strip.squeeze(" ")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def remote_location(path)
|
|
39
|
+
source = ""
|
|
40
|
+
unless @sync_options[:local]
|
|
41
|
+
source << @sync_options[:username] << '@' if @sync_options[:username]
|
|
42
|
+
source << @address
|
|
43
|
+
source << (@sync_options[:daemon] ? '::' : ':')
|
|
44
|
+
end
|
|
45
|
+
source << path
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|