screwcap 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +0 -1
- data/Rakefile +1 -1
- data/lib/exts.rb +1 -7
- data/lib/screwcap.rb +4 -2
- data/lib/screwcap/base.rb +0 -42
- data/lib/screwcap/deployer.rb +7 -6
- data/lib/screwcap/server.rb +1 -1
- data/lib/screwcap/task.rb +15 -65
- data/screwcap.gemspec +1 -1
- data/spec/command_set_spec.rb +7 -1
- data/spec/deployer_spec.rb +5 -3
- data/spec/sequence_spec.rb +1 -0
- data/spec/server_spec.rb +3 -6
- data/spec/spec_helper.rb +21 -7
- data/spec/task_spec.rb +16 -9
- data/test/config/command_sets.rb +8 -0
- data/test/config/expect.rb +4 -18
- metadata +4 -5
- data/lib/screwcap/command_set.rb +0 -56
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ Hoe.plugin :newgem
|
|
11
11
|
# Generate all the Rake tasks
|
12
12
|
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
13
|
$hoe = Hoe.spec 'screwcap' do
|
14
|
-
self.version = '0.
|
14
|
+
self.version = '0.3'
|
15
15
|
self.developer 'Grant Ammons', 'grant@pipelinedeals.com'
|
16
16
|
self.rubyforge_name = self.name # TODO this is default value
|
17
17
|
self.extra_deps = [['net-ssh','>= 2.0.23'],['net-ssh-gateway','>=1.0.1'], ['net-scp','>=1.0.4']]
|
data/lib/exts.rb
CHANGED
data/lib/screwcap.rb
CHANGED
@@ -8,15 +8,16 @@ require 'ostruct'
|
|
8
8
|
require 'logger'
|
9
9
|
|
10
10
|
require 'exts'
|
11
|
+
require 'screwcap/message_logger'
|
11
12
|
require 'screwcap/base'
|
12
|
-
require 'screwcap/command_set'
|
13
13
|
require 'screwcap/task'
|
14
14
|
require 'screwcap/server'
|
15
|
+
require 'screwcap/runner'
|
15
16
|
require 'screwcap/sequence'
|
16
17
|
require 'screwcap/deployer'
|
17
18
|
|
18
19
|
module Screwcap
|
19
|
-
VERSION='0.
|
20
|
+
VERSION='0.3'
|
20
21
|
|
21
22
|
class TaskNotFound < RuntimeError; end
|
22
23
|
class NoServersDefined < Exception; end
|
@@ -25,5 +26,6 @@ module Screwcap
|
|
25
26
|
class IncludeFileNotFound < Exception; end
|
26
27
|
class InvalidServer < Exception; end
|
27
28
|
class CommandSetDependencyError < Exception; end
|
29
|
+
class CommandError < Exception; end
|
28
30
|
end
|
29
31
|
|
data/lib/screwcap/base.rb
CHANGED
@@ -10,47 +10,5 @@ module Screwcap
|
|
10
10
|
def set(var, *args)
|
11
11
|
method_missing((var.to_s + "=").to_sym, args.first)
|
12
12
|
end
|
13
|
-
|
14
|
-
def log(msg, options = {})
|
15
|
-
$stdout << msg unless self.__options[:silent] == true
|
16
|
-
end
|
17
|
-
|
18
|
-
def errorlog(msg)
|
19
|
-
$stderr << msg unless self.__options[:silent] == true
|
20
|
-
end
|
21
|
-
|
22
|
-
def bluebold(msg, options = {:clear => true})
|
23
|
-
if self.__options[:nocolor] == true
|
24
|
-
msg
|
25
|
-
else
|
26
|
-
"\033[1;36m#{msg}#{"\033[0m" if options[:clear]}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def blue(msg, options = {:clear => true})
|
31
|
-
if self.__options[:nocolor] == true
|
32
|
-
msg
|
33
|
-
else
|
34
|
-
"\033[0;36m#{msg}#{"\033[0m" if options[:clear]}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
def red(msg)
|
40
|
-
if self.__options[:nocolor] == true
|
41
|
-
msg
|
42
|
-
else
|
43
|
-
"\033[0;31m#{msg}\033[0m"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def green(msg)
|
48
|
-
if self.__options[:nocolor] == true
|
49
|
-
msg
|
50
|
-
else
|
51
|
-
"\033[0;32m#{msg}\033[0m"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
13
|
end
|
56
14
|
end
|
data/lib/screwcap/deployer.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# The deployer can be thought of as the "global scope" of your tasks file.
|
4
4
|
class Deployer < Screwcap::Base
|
5
|
+
include MessageLogger
|
5
6
|
|
6
7
|
# create a new deployer.
|
7
8
|
def initialize(opts = {})
|
@@ -16,7 +17,7 @@ class Deployer < Screwcap::Base
|
|
16
17
|
# ensure that deployer options will not be passed to tasks
|
17
18
|
opts.each_key {|k| self.delete_field(k) }
|
18
19
|
|
19
|
-
log "Reading #{self.__options[:recipe_file]}\n" unless self.__options[:silent] == true
|
20
|
+
Deployer.log "Reading #{self.__options[:recipe_file]}\n" unless self.__options[:silent] == true
|
20
21
|
|
21
22
|
file = File.open(File.expand_path("./#{self.__options[:recipe_file]}"))
|
22
23
|
data = file.read
|
@@ -27,14 +28,14 @@ class Deployer < Screwcap::Base
|
|
27
28
|
|
28
29
|
# create a task. Minimally, a task needs a :server specified to run the task on.
|
29
30
|
def task_for name, options = {}, &block
|
30
|
-
t = Task.new(options.merge(:name => name, :nocolor => self.__options[:nocolor], :silent => self.__options[:silent], :deployment_servers => self.__servers), &block)
|
31
|
+
t = Task.new(options.merge(:name => name, :nocolor => self.__options[:nocolor], :silent => self.__options[:silent], :deployment_servers => self.__servers, :command_sets => self.__command_sets), &block)
|
31
32
|
clone_table_for(t)
|
32
33
|
t.instance_eval(&block)
|
33
34
|
self.__tasks << t
|
34
35
|
end
|
35
36
|
|
36
37
|
def command_set(name,options = {},&block)
|
37
|
-
t =
|
38
|
+
t = Task.new(options.merge(:name => name, :validate => false, :command_set => true, :command_sets => self.__command_sets), &block)
|
38
39
|
clone_table_for(t)
|
39
40
|
self.__command_sets << t
|
40
41
|
end
|
@@ -66,9 +67,9 @@ class Deployer < Screwcap::Base
|
|
66
67
|
tasks.each do |t|
|
67
68
|
sequence = self.__sequences.find {|s| s.__name == t }
|
68
69
|
if sequence
|
69
|
-
sequence.__task_names.each {|task_name| self.__tasks.find {|task| task.__name == task_name }.
|
70
|
+
sequence.__task_names.each {|task_name| Runner.execute! self.__tasks.find {|task| task.__name == task_name }, self.__options}
|
70
71
|
else
|
71
|
-
self.__tasks.select {|task| task.name.to_s == t.to_s }.first.
|
72
|
+
Runner.execute! self.__tasks.select {|task| task.name.to_s == t.to_s }.first, self.__options
|
72
73
|
end
|
73
74
|
end
|
74
75
|
$stdout << "\033[0m"
|
@@ -98,7 +99,7 @@ class Deployer < Screwcap::Base
|
|
98
99
|
|
99
100
|
def clone_table_for(object)
|
100
101
|
self.table.each do |k,v|
|
101
|
-
object.set(k, v) unless [:__options, :__tasks, :__servers].include?(k)
|
102
|
+
object.set(k, v) unless [:__options, :__tasks, :__servers, :__command_sets].include?(k)
|
102
103
|
end
|
103
104
|
end
|
104
105
|
end
|
data/lib/screwcap/server.rb
CHANGED
@@ -32,7 +32,7 @@ class Server < Screwcap::Base
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def __upload_to!(address, local, remote)
|
35
|
-
|
35
|
+
self.__with_connection_for(address) {|ssh| ssh.scp.upload! local, remote }
|
36
36
|
end
|
37
37
|
|
38
38
|
protected
|
data/lib/screwcap/task.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
class Task < Screwcap::Base
|
2
|
+
include MessageLogger
|
3
|
+
|
2
4
|
def initialize(opts = {}, &block)
|
3
5
|
super
|
4
6
|
self.__name = opts[:name]
|
5
7
|
self.__options = opts
|
6
8
|
self.__commands = []
|
7
|
-
self.__command_sets = []
|
9
|
+
self.__command_sets = opts[:command_sets] || []
|
8
10
|
self.__server_names = []
|
11
|
+
self.__block = block if opts[:command_set] == true
|
9
12
|
|
10
13
|
|
11
14
|
if opts[:server] and opts[:servers].nil?
|
@@ -14,15 +17,16 @@ class Task < Screwcap::Base
|
|
14
17
|
self.__server_names = opts[:servers]
|
15
18
|
end
|
16
19
|
|
17
|
-
validate(opts[:deployment_servers])
|
20
|
+
validate(opts[:deployment_servers]) unless opts[:validate] == false
|
18
21
|
end
|
19
22
|
|
20
23
|
# run a command. basically just pass it a string containing the command you want to run.
|
21
24
|
def run arg, options = {}
|
25
|
+
|
22
26
|
if arg.class == Symbol
|
23
|
-
self.__commands << {:command => self.send(arg), :type => :remote}
|
27
|
+
self.__commands << options.merge({:command => self.send(arg), :type => :remote, :from => self.__name})
|
24
28
|
else
|
25
|
-
self.__commands << {:command => arg, :type => :remote}
|
29
|
+
self.__commands << options.merge({:command => arg, :type => :remote, :from => self.__name})
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
@@ -33,25 +37,15 @@ class Task < Screwcap::Base
|
|
33
37
|
# run a command. basically just pass it a string containing the command you want to run.
|
34
38
|
def local arg, options = {}
|
35
39
|
if arg.class == Symbol
|
36
|
-
self.__commands << {:command => self.send(arg), :type => :local}
|
40
|
+
self.__commands << options.merge({:command => self.send(arg), :type => :local, :from => self.__name})
|
37
41
|
else
|
38
|
-
self.__commands << {:command => arg, :type => :local}
|
42
|
+
self.__commands << options.merge({:command => arg, :type => :local, :from => self.__name})
|
39
43
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def execute!
|
44
|
-
threads = []
|
45
|
-
self.__servers.each do |_server|
|
46
|
-
_server.__addresses.each do |_address|
|
47
|
-
if self.__options[:parallel] == false
|
48
|
-
execute_on(_server, _address)
|
49
|
-
else
|
50
|
-
threads << Thread.new(_server, _address) { |server, address| execute_on(server, address) }
|
51
|
-
end
|
44
|
+
if failure_cmd = self.__commands.last[:onfailure]
|
45
|
+
unless self.__command_sets.find {|cs| cs.__name == failure_cmd }
|
46
|
+
raise ScrewCap::ConfigurationError, "Could not find failure command set named '#{failure_cmd}' for task '#{self.__name}'"
|
52
47
|
end
|
53
48
|
end
|
54
|
-
threads.each {|t| t.join }
|
55
49
|
end
|
56
50
|
|
57
51
|
protected
|
@@ -60,7 +54,7 @@ class Task < Screwcap::Base
|
|
60
54
|
if m.to_s[0..1] == "__" or [:run].include?(m) or m.to_s.reverse[0..0] == "="
|
61
55
|
super(m, args.first)
|
62
56
|
else
|
63
|
-
if cs = self.__command_sets.find {|cs| cs.
|
57
|
+
if cs = self.__command_sets.find {|cs| cs.__name == m }
|
64
58
|
# eval what is in the block
|
65
59
|
clone_table_for(cs)
|
66
60
|
cs.__commands = []
|
@@ -76,7 +70,7 @@ class Task < Screwcap::Base
|
|
76
70
|
|
77
71
|
def clone_table_for(object)
|
78
72
|
self.table.each do |k,v|
|
79
|
-
object.set(k, v) unless [:
|
73
|
+
object.set(k, v) unless [:__block, :__tasks, :__name, :__command_sets, :__commands, :__options].include?(k)
|
80
74
|
end
|
81
75
|
end
|
82
76
|
|
@@ -91,48 +85,4 @@ class Task < Screwcap::Base
|
|
91
85
|
self.__servers = self.__server_names.map {|name| servers.find {|s| s.name == name } }
|
92
86
|
end
|
93
87
|
|
94
|
-
def execute_on(server, address)
|
95
|
-
begin
|
96
|
-
log blue("\n*** BEGIN executing task #{self.__name} on #{server.name} with address #{address}\n") unless self.__options[:silent] == true
|
97
|
-
|
98
|
-
server.__with_connection_for(address) do |ssh|
|
99
|
-
error = false
|
100
|
-
self.__commands.each do |command|
|
101
|
-
next if error and self.__options[:stop_on_errors]
|
102
|
-
|
103
|
-
if command[:type] == :remote
|
104
|
-
log green(" I: (#{address}): #{command[:command]}\n")
|
105
|
-
|
106
|
-
ssh.exec! command[:command] do |ch,stream,data|
|
107
|
-
if stream == :stderr
|
108
|
-
error = true
|
109
|
-
errorlog red(" E: (#{address}): #{data}")
|
110
|
-
else
|
111
|
-
log green(" O: (#{address}): #{data}")
|
112
|
-
end
|
113
|
-
end # ssh.exec
|
114
|
-
elsif command[:type] == :local
|
115
|
-
ret = `#{command[:command]}`
|
116
|
-
if $?.to_i == 0
|
117
|
-
log blue(" I: (local): #{command[:command]}\n")
|
118
|
-
log blue(" O: (local): #{ret}\n")
|
119
|
-
else
|
120
|
-
log blue(" I: (local): #{command[:command]}\n")
|
121
|
-
errorlog red(" O: (local): #{ret}\n")
|
122
|
-
end
|
123
|
-
elsif command[:type] == :scp
|
124
|
-
server.__upload_to!(address, command[:local], command[:remote])
|
125
|
-
log green(" I: (#{address}): SCP #{command[:local]} to #{server.__user}@#{address}:#{command[:remote]}")
|
126
|
-
end
|
127
|
-
end # commands.each
|
128
|
-
end # net.ssh start
|
129
|
-
rescue Net::SSH::AuthenticationFailed => e
|
130
|
-
raise Net::SSH::AuthenticationFailed, "Authentication failed for server named #{server.name}. Please check your authentication credentials."
|
131
|
-
rescue Exception => e
|
132
|
-
errorlog red(" F: (#{address}): #{e}")
|
133
|
-
ensure
|
134
|
-
log blue("*** END executing task #{self.__name} on #{server.name} with address #{address}\n\n") unless self.__options[:silent] == true
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
88
|
end
|
data/screwcap.gemspec
CHANGED
data/spec/command_set_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Command sets" do
|
|
4
4
|
before(:all) do
|
5
5
|
@stdout = []
|
6
6
|
Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg}
|
7
|
-
@deployer = Deployer.new(:recipe_file => "./test/config/command_sets.rb", :silent =>
|
7
|
+
@deployer = Deployer.new(:recipe_file => "./test/config/command_sets.rb", :silent => true)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should be able to define a generic list of commands" do
|
@@ -48,4 +48,10 @@ describe "Command sets" do
|
|
48
48
|
task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
|
49
49
|
task.__commands.map {|c| c[:command]}.should == %w(birdo nested birdo task)
|
50
50
|
end
|
51
|
+
|
52
|
+
it "should be able to call scp just like a task" do
|
53
|
+
task = @deployer.__tasks.find {|t| t.__name == :task_use_scp}
|
54
|
+
task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
|
55
|
+
task.__commands.map {|c| c[:command]}.should == [nil]
|
56
|
+
end
|
51
57
|
end
|
data/spec/deployer_spec.rb
CHANGED
@@ -3,6 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe "Deployers" do
|
4
4
|
before(:all) do
|
5
5
|
Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
|
6
|
+
Runner.stubs(:ssh_exec!).returns(["ok","",0,nil])
|
6
7
|
end
|
7
8
|
|
8
9
|
it "should complain if no server was defined" do
|
@@ -40,7 +41,7 @@ describe "Deployers" do
|
|
40
41
|
|
41
42
|
it "should be able to define command sets" do
|
42
43
|
deployer = Deployer.new(:recipe_file => "./test/config/command_sets.rb", :silent => true)
|
43
|
-
deployer.should have(
|
44
|
+
deployer.should have(9).__command_sets
|
44
45
|
end
|
45
46
|
|
46
47
|
it "should be able to define gateways" do
|
@@ -51,12 +52,13 @@ describe "Deployers" do
|
|
51
52
|
|
52
53
|
it "should be able to define sequences" do
|
53
54
|
deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
|
54
|
-
deployer.should have
|
55
|
+
deployer.should have(1).__sequences
|
55
56
|
end
|
56
57
|
|
57
58
|
it "should be able to run a single task" do
|
58
59
|
deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
|
59
|
-
|
60
|
+
deployer.run! :task1
|
61
|
+
#lambda { deployer.run! :task1 }.should_not raise_error
|
60
62
|
end
|
61
63
|
|
62
64
|
it "should be able to run multiple tasks" do
|
data/spec/sequence_spec.rb
CHANGED
data/spec/server_spec.rb
CHANGED
@@ -4,11 +4,8 @@ describe "Servers" do
|
|
4
4
|
before(:each) do
|
5
5
|
@stdout = []
|
6
6
|
@stderr = []
|
7
|
-
|
8
|
-
|
9
|
-
Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg }
|
10
|
-
Deployer.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
|
11
|
-
|
7
|
+
Runner.stubs(:log).with() { |msg,opts| @stdout << msg }
|
8
|
+
Runner.stubs(:errorlog).with() { |msg,opts| @stderr << msg }
|
12
9
|
Net::SSH::Gateway.stubs(:new).returns(SSHObject.new)
|
13
10
|
end
|
14
11
|
|
@@ -34,7 +31,7 @@ describe "Servers" do
|
|
34
31
|
end
|
35
32
|
|
36
33
|
it "should provide a connection to the server with a gateway" do
|
37
|
-
@deployer = Deployer.new(:recipe_file => "./test/config/gateway.rb", :silent =>
|
34
|
+
@deployer = Deployer.new(:recipe_file => "./test/config/gateway.rb", :silent => true)
|
38
35
|
server = @deployer.__servers.find {|s| s.__name == :test}
|
39
36
|
gateway = @deployer.__servers.find {|s| s.__name == :gateway1}
|
40
37
|
|
data/spec/spec_helper.rb
CHANGED
@@ -7,19 +7,33 @@ require 'mocha'
|
|
7
7
|
require 'ruby-debug' rescue nil
|
8
8
|
require 'net/ssh'
|
9
9
|
|
10
|
-
class SSHObject
|
10
|
+
class SSHObject < OpenStruct
|
11
11
|
attr_accessor :options
|
12
12
|
|
13
13
|
def initialize(options = {})
|
14
|
-
@options = {:return_stream => :stdout}
|
15
|
-
@options = options
|
16
14
|
end
|
17
15
|
|
18
|
-
def
|
19
|
-
yield
|
16
|
+
def on_data
|
17
|
+
yield SSHObject.new, ""
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
23
|
-
yield
|
20
|
+
def on_extended_data
|
21
|
+
yield SSHObject.new, "", ""
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_long
|
25
|
+
""
|
26
|
+
end
|
27
|
+
|
28
|
+
def upload!(from, to)
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def scp
|
33
|
+
SSHObject.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_request(item)
|
37
|
+
yield SSHObject.new, SSHObject.new
|
24
38
|
end
|
25
39
|
end
|
data/spec/task_spec.rb
CHANGED
@@ -4,16 +4,15 @@ describe "Tasks" do
|
|
4
4
|
before(:each) do
|
5
5
|
@stdout = []
|
6
6
|
@stderr = []
|
7
|
-
|
8
|
-
|
9
|
-
Deployer.
|
10
|
-
Deployer.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
|
11
|
-
@deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => false)
|
7
|
+
Runner.stubs(:log).with() { |msg,opts| @stdout << msg }
|
8
|
+
Runner.stubs(:errorlog).with() { |msg,opts| @stderr << msg }
|
9
|
+
@deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
|
12
10
|
end
|
13
11
|
|
14
12
|
before(:all) do
|
15
13
|
Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
|
16
14
|
Net::SCP.stubs(:upload!).returns(nil)
|
15
|
+
Runner.stubs(:ssh_exec!).returns(["ok","",0,nil])
|
17
16
|
end
|
18
17
|
|
19
18
|
it "should be able to create variables" do
|
@@ -28,9 +27,9 @@ describe "Tasks" do
|
|
28
27
|
|
29
28
|
it "should be able to execute statements on a remote server" do
|
30
29
|
task = @deployer.__tasks.find {|t| t.name == :task1 }
|
31
|
-
|
30
|
+
Runner.execute! task, @deployer.__options
|
32
31
|
@stderr.should == []
|
33
|
-
@stdout.size.should ==
|
32
|
+
@stdout.size.should == 26
|
34
33
|
end
|
35
34
|
|
36
35
|
it "should be able to use variables in the run statement" do
|
@@ -52,11 +51,11 @@ describe "Tasks" do
|
|
52
51
|
end
|
53
52
|
|
54
53
|
it "should complain if you do not pass the task a server argument" do
|
55
|
-
lambda { Deployer.new(:recipe_file => "./test/config/no_server.rb", :silent =>
|
54
|
+
lambda { Deployer.new(:recipe_file => "./test/config/no_server.rb", :silent => true)}.should raise_error(Screwcap::ConfigurationError)
|
56
55
|
end
|
57
56
|
|
58
57
|
it "should complain if you pass a server that is not defined" do
|
59
|
-
lambda { Deployer.new(:recipe_file => "./test/config/undefined_server.rb", :silent =>
|
58
|
+
lambda { Deployer.new(:recipe_file => "./test/config/undefined_server.rb", :silent => true)}.should raise_error(Screwcap::ConfigurationError)
|
60
59
|
end
|
61
60
|
|
62
61
|
it "should be able to disable parallel running" do
|
@@ -72,4 +71,12 @@ describe "Tasks" do
|
|
72
71
|
deployer = Deployer.new(:recipe_file => "./test/config/upload.rb", :silent => true)
|
73
72
|
deployer.run! :upload
|
74
73
|
end
|
74
|
+
|
75
|
+
it "should respond to onfailure" do
|
76
|
+
deployer = Deployer.new(:recipe_file => "./test/config/expect.rb", :silent => true)
|
77
|
+
t = deployer.__tasks.find {|t| t.__name == :expect }
|
78
|
+
Runner.stubs(:ssh_exec!).returns(["","fail",1,nil]).then.returns(["ok","",0,nil])
|
79
|
+
Runner.execute! t, deployer.__options
|
80
|
+
t.__commands.map {|c| [c[:command], c[:from]] }.first.should == ["echo 'we failed'", :failover]
|
81
|
+
end
|
75
82
|
end
|
data/test/config/command_sets.rb
CHANGED
@@ -47,6 +47,10 @@ command_set :nested_outside_with_var do
|
|
47
47
|
run :nested_var
|
48
48
|
end
|
49
49
|
|
50
|
+
command_set :use_scp do
|
51
|
+
scp :local => "/tmp/test", :remote => "/tmp/test"
|
52
|
+
end
|
53
|
+
|
50
54
|
|
51
55
|
task_for :use_command_set_no_override, :server => :test do
|
52
56
|
push_to_thang
|
@@ -85,3 +89,7 @@ task_for :nested_scoping, :server => :test do
|
|
85
89
|
nested_outside_with_var
|
86
90
|
run :nested_var
|
87
91
|
end
|
92
|
+
|
93
|
+
task_for :task_use_scp, :server => :test do
|
94
|
+
use_scp
|
95
|
+
end
|
data/test/config/expect.rb
CHANGED
@@ -5,26 +5,12 @@ command_set :revert do
|
|
5
5
|
run "revert"
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
when 1
|
11
|
-
run "1"
|
12
|
-
when 2
|
13
|
-
run "2"
|
14
|
-
else
|
15
|
-
run "none"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
command_set :fail do
|
20
|
-
run "ls"
|
21
|
-
end
|
22
|
-
|
23
|
-
command_set :success do
|
24
|
-
run "ls"
|
8
|
+
command_set :failover do
|
9
|
+
run "echo 'we failed'"
|
25
10
|
end
|
26
11
|
|
27
12
|
task_for :expect, :server => :test do
|
28
|
-
run "
|
13
|
+
run "this will fail", :onfailure => :failover
|
14
|
+
run "ls"
|
29
15
|
end
|
30
16
|
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: screwcap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 3
|
9
|
+
version: "0.3"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Grant Ammons
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-25 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -122,7 +122,6 @@ files:
|
|
122
122
|
- lib/exts.rb
|
123
123
|
- lib/screwcap.rb
|
124
124
|
- lib/screwcap/base.rb
|
125
|
-
- lib/screwcap/command_set.rb
|
126
125
|
- lib/screwcap/deployer.rb
|
127
126
|
- lib/screwcap/sequence.rb
|
128
127
|
- lib/screwcap/server.rb
|
data/lib/screwcap/command_set.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
class CommandSet < Screwcap::Base
|
2
|
-
def initialize(opts = {}, &block)
|
3
|
-
super
|
4
|
-
self.__name = opts[:name]
|
5
|
-
self.__options = opts
|
6
|
-
self.__commands = []
|
7
|
-
self.__command_sets = []
|
8
|
-
self.__block = block
|
9
|
-
end
|
10
|
-
|
11
|
-
# run a command. basically just pass it a string containing the command you want to run.
|
12
|
-
def run arg, options = {}
|
13
|
-
if arg.class == Symbol
|
14
|
-
self.__commands << {:command => self.send(arg), :type => :remote}
|
15
|
-
else
|
16
|
-
self.__commands << {:command => arg, :type => :remote}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# run a command. basically just pass it a string containing the command you want to run.
|
21
|
-
def local arg, options = {}
|
22
|
-
if arg.class == Symbol
|
23
|
-
self.__commands << {:command => self.send(arg), :type => :local}
|
24
|
-
else
|
25
|
-
self.__commands << {:command => arg, :type => :local}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
protected
|
31
|
-
|
32
|
-
def method_missing(m, *args)
|
33
|
-
if m.to_s[0..1] == "__" or [:run].include?(m) or m.to_s.reverse[0..0] == "="
|
34
|
-
super(m, args.first)
|
35
|
-
else
|
36
|
-
if cs = self.__command_sets.find {|cs| cs.name == m }
|
37
|
-
# eval what is in the block
|
38
|
-
clone_table_for(cs)
|
39
|
-
cs.__commands = []
|
40
|
-
cs.instance_eval(&cs.__block)
|
41
|
-
self.__commands += cs.__commands
|
42
|
-
else
|
43
|
-
raise NoMethodError, "Undefined method '#{m.to_s}' for Command Set :#{self.name.to_s}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def clone_table_for(object)
|
51
|
-
self.table.each do |k,v|
|
52
|
-
object.set(k, v) unless [:__command_sets, :name, :__commands, :__options, :__block].include?(k)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|