rudy 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +16 -1
- data/README.rdoc +3 -3
- data/Rakefile +2 -0
- data/Rudyfile +11 -4
- data/bin/rudy +5 -1
- data/lib/rudy.rb +1 -1
- data/lib/rudy/cli.rb +11 -2
- data/lib/rudy/cli/routines.rb +16 -12
- data/lib/rudy/config.rb +3 -0
- data/lib/rudy/config/objects.rb +21 -31
- data/lib/rudy/disks.rb +7 -1
- data/lib/rudy/global.rb +4 -4
- data/lib/rudy/huxtable.rb +3 -2
- data/lib/rudy/machines.rb +16 -0
- data/lib/rudy/routines.rb +41 -3
- data/lib/rudy/routines/helper.rb +7 -2
- data/lib/rudy/routines/helpers/diskhelper.rb +50 -25
- data/lib/rudy/routines/helpers/scripthelper.rb +79 -38
- data/lib/rudy/routines/helpers/userhelper.rb +4 -4
- data/lib/rudy/routines/passthrough.rb +1 -1
- data/lib/rudy/routines/shutdown.rb +1 -1
- data/lib/rudy/routines/startup.rb +4 -0
- data/lib/rudy/scm/git.rb +4 -2
- data/rudy.gemspec +4 -4
- metadata +5 -5
data/CHANGES.txt
CHANGED
@@ -8,7 +8,22 @@ RUDY, CHANGES
|
|
8
8
|
* TODO: Tests for AWS HTTPS
|
9
9
|
|
10
10
|
|
11
|
-
#### 0.7.
|
11
|
+
#### 0.7.1 (2009-04-04) ###############################
|
12
|
+
|
13
|
+
* FIXED: rudy wasn't honouring -C option for specifying a config file
|
14
|
+
* FIXED: Was disabling, but not enabling colour
|
15
|
+
* FIXED: Symbol errors in 1.8
|
16
|
+
* FIXED: Command blocks for root user are always run first now in Routines config.
|
17
|
+
* ADDED: "script" keyword to routines config.
|
18
|
+
* CHANGE: routines before, after, and script blocks are now processed by Rye::Box.batch as Procs.
|
19
|
+
* CHANGE: deny was removed from commands config (it will come back later).
|
20
|
+
* ADDED: examples/
|
21
|
+
* CHANGE: Rudy now checks the current working directory for machines, commands, etc... configs
|
22
|
+
* ADDED: script_local
|
23
|
+
* ADDED: Routine now checks whether there are any remote tasks. If not, it doesn't loop through machines.
|
24
|
+
|
25
|
+
|
26
|
+
#### 0.7.0 (2009-04-02) ###############################
|
12
27
|
|
13
28
|
* CHANGE: Upgrade to Drydock 0.6, Caesars 0.6, and Rye 0.6
|
14
29
|
* CHANGE: Updated Routines configuration syntax for specifying shell commands
|
data/README.rdoc
CHANGED
@@ -29,7 +29,7 @@ All configuration is organized into the zones, environments, and roles that you
|
|
29
29
|
* Powerful command-line tools
|
30
30
|
* <tt>$ rudy -u root ssh</tt>
|
31
31
|
* <tt>$ rudy -e testing -r database startup</tt>
|
32
|
-
* Use
|
32
|
+
* Use _any Linux_ Amazon machine image (AMI) (partial Solaris support)
|
33
33
|
* Complete command-line interface for EC2. See <tt>bin/rudy-ec2</tt>.
|
34
34
|
|
35
35
|
== Installation
|
@@ -40,8 +40,8 @@ Via Rubygems, one of:
|
|
40
40
|
$ sudo gem install solutious-rudy --source http://gems.github.com/
|
41
41
|
|
42
42
|
or via download:
|
43
|
-
* rudy-latest.tar.gz[http://github.com/solutious/rudy/tarball/
|
44
|
-
* rudy-latest.zip[http://github.com/solutious/rudy/zipball/
|
43
|
+
* rudy-latest.tar.gz[http://github.com/solutious/rudy/tarball/latest]
|
44
|
+
* rudy-latest.zip[http://github.com/solutious/rudy/zipball/latest]
|
45
45
|
|
46
46
|
NOTE: <em>If you are not installing via RubyGems, you need to make sure the dependencies are in your LOAD_PATH (<tt>$:</tt>). Ryan Tomayko wrote a gist[http://gist.github.com/54177] about it.</em>
|
47
47
|
|
data/Rakefile
CHANGED
data/Rudyfile
CHANGED
@@ -81,13 +81,20 @@ end
|
|
81
81
|
|
82
82
|
|
83
83
|
# ----------------------------------------------------------- COMMANDS --------
|
84
|
-
# The commands block defines shell commands
|
85
|
-
# default list defined by Rye::Cmd (Rudy
|
86
|
-
#
|
84
|
+
# The commands block defines shell commands that can be used in routines. The
|
85
|
+
# ones defined here are added to the default list defined by Rye::Cmd (Rudy
|
86
|
+
# executes all SSH commands via Rye).
|
87
|
+
#
|
88
|
+
# Usage:
|
89
|
+
#
|
90
|
+
# allow COMMAND-NAME
|
91
|
+
# allow COMMAND-NAME, '/path/2/COMMAND'
|
92
|
+
# allow COMMAND-NAME, '/path/2/COMMAND', 'default argument', 'another arg'
|
93
|
+
#
|
87
94
|
commands do
|
95
|
+
allow :make
|
88
96
|
allow :gem_install, "/usr/bin/gem", "install", :V, "--no-rdoc", "--no-ri"
|
89
97
|
allow :apt_get, "/usr/bin/apt-get", :y, :q
|
90
|
-
deny :kill
|
91
98
|
end
|
92
99
|
|
93
100
|
|
data/bin/rudy
CHANGED
@@ -23,7 +23,7 @@ require 'rudy/cli'
|
|
23
23
|
# Command-line interface for /bin/rudy
|
24
24
|
class RudyCLI < Rudy::CLI::Base
|
25
25
|
|
26
|
-
debug :
|
26
|
+
debug :off
|
27
27
|
default :machines
|
28
28
|
trawler :passthrough
|
29
29
|
|
@@ -86,6 +86,10 @@ class RudyCLI < Rudy::CLI::Base
|
|
86
86
|
usage "rudy shutdown"
|
87
87
|
command :shutdown => Rudy::CLI::Routines
|
88
88
|
|
89
|
+
#about "Restart a machine group"
|
90
|
+
#usage "rudy restart"
|
91
|
+
#command :restart => Rudy::CLI::Routines
|
92
|
+
|
89
93
|
about "Create a release"
|
90
94
|
usage "rudy release"
|
91
95
|
command :release => Rudy::CLI::Routines
|
data/lib/rudy.rb
CHANGED
data/lib/rudy/cli.rb
CHANGED
@@ -26,8 +26,7 @@ module Rudy
|
|
26
26
|
protected
|
27
27
|
def init
|
28
28
|
|
29
|
-
|
30
|
-
Rudy::Huxtable.update_config
|
29
|
+
#Caesars.enable_debug
|
31
30
|
|
32
31
|
# The CLI wants output!
|
33
32
|
Rudy::Huxtable.update_logger STDOUT
|
@@ -35,6 +34,16 @@ module Rudy
|
|
35
34
|
# Send The Huxtables the global values from the command-line
|
36
35
|
Rudy::Huxtable.update_global @global
|
37
36
|
|
37
|
+
# Reload configuration. This must come after update_global
|
38
|
+
# so it will catch the @@global.config path (if supplied).
|
39
|
+
begin
|
40
|
+
Rudy::Huxtable.update_config
|
41
|
+
rescue Caesars::SyntaxError => ex
|
42
|
+
STDERR.puts ex.message
|
43
|
+
STDERR.puts ex.backtrace if @@global.verbose > 0
|
44
|
+
exit 81
|
45
|
+
end
|
46
|
+
|
38
47
|
unless @@global.accesskey && @@global.secretkey
|
39
48
|
STDERR.puts "No AWS credentials. Check your configs!"
|
40
49
|
STDERR.puts "Try: rudy init"
|
data/lib/rudy/cli/routines.rb
CHANGED
@@ -9,21 +9,25 @@ module Rudy; module CLI;
|
|
9
9
|
true
|
10
10
|
end
|
11
11
|
def startup
|
12
|
-
|
13
|
-
@rr.execute
|
14
|
-
|
12
|
+
machines = @rr.execute
|
15
13
|
puts $/, "The following machines are now available:"
|
16
|
-
|
17
|
-
rmach.list do |machine|
|
14
|
+
machines.each do |machine|
|
18
15
|
puts machine.to_s
|
19
16
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
def restart_valid?
|
20
|
+
@rr = Rudy::Routines::Restart.new
|
21
|
+
@rr.raise_early_exceptions
|
22
|
+
true
|
23
|
+
end
|
24
|
+
def restart
|
25
|
+
#machines = @rr.execute
|
26
|
+
#puts $/, "The following machines have been restarted:"
|
27
|
+
#machines.each do |machine|
|
28
|
+
# puts machine.to_s
|
29
|
+
#end
|
30
|
+
#puts "Restart is disabled"
|
27
31
|
end
|
28
32
|
|
29
33
|
def release_valid?
|
data/lib/rudy/config.rb
CHANGED
@@ -61,10 +61,13 @@ module Rudy
|
|
61
61
|
break
|
62
62
|
end
|
63
63
|
|
64
|
+
typelist = self.keys.collect { |g| "#{g}.rb" }.join(',')
|
65
|
+
|
64
66
|
# Rudy then looks for the rest of the config in these locations
|
65
67
|
@paths += Dir.glob(File.join(cwd, 'Rudyfile')) || []
|
66
68
|
@paths += Dir.glob(File.join(cwd, 'config', 'rudy', '*.rb')) || []
|
67
69
|
@paths += Dir.glob(File.join(cwd, '.rudy', '*.rb')) || []
|
70
|
+
@paths += Dir.glob(File.join(cwd, "{#{typelist}}")) || []
|
68
71
|
@paths += Dir.glob(File.join('/etc', 'rudy', '*.rb')) || []
|
69
72
|
@paths &&= @paths.uniq
|
70
73
|
|
data/lib/rudy/config/objects.rb
CHANGED
@@ -91,21 +91,16 @@ class Rudy::Config
|
|
91
91
|
arg.is_a?(Symbol) ? ":#{arg}" : "'#{arg}'"
|
92
92
|
end
|
93
93
|
hard_args = args.empty? ? "*args" : "#{args.join(', ')}, *args"
|
94
|
-
|
95
|
-
#
|
96
|
-
Rudy::Config::Routines.forced_array cmd
|
94
|
+
|
95
|
+
# TODO: Use define_method
|
97
96
|
Rye::Cmd.module_eval %Q{
|
98
97
|
def #{cmd}(*args); cmd(:'#{path}', #{hard_args}); end
|
99
98
|
}
|
99
|
+
|
100
100
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
# We don't remove the method from Rye:Cmd because we
|
105
|
-
# may need elsewhere in Rudy. Forced ignore ensures
|
106
|
-
# the config is not stored anyhow.
|
107
|
-
end
|
108
|
-
raise Caesars::Config::ForceRefresh.new(:routines)
|
101
|
+
## NOTE: We now process command blocks as Procs rather than individual commands.
|
102
|
+
# There's currently no need to ForceRefresh here
|
103
|
+
##raise Caesars::Config::ForceRefresh.new(:routines)
|
109
104
|
end
|
110
105
|
end
|
111
106
|
|
@@ -124,31 +119,26 @@ class Rudy::Config
|
|
124
119
|
forced_hash :restore
|
125
120
|
forced_hash :mount
|
126
121
|
|
127
|
-
#
|
128
|
-
forced_hash :before
|
129
|
-
forced_hash :
|
130
|
-
forced_hash :
|
131
|
-
forced_hash :
|
122
|
+
# Script blocks
|
123
|
+
forced_hash :before
|
124
|
+
forced_hash :after
|
125
|
+
forced_hash :script_local
|
126
|
+
forced_hash :before_local
|
127
|
+
forced_hash :after_local # We force hash the script keywords
|
128
|
+
forced_hash :script # b/c we want them to store the usernames
|
129
|
+
chill :before # as hash keys.
|
130
|
+
chill :after # We also chill them b/c we want to execute
|
131
|
+
chill :before_local # the command blocks with an instance_eval
|
132
|
+
chill :after_local # inside a Rye::Box object.
|
133
|
+
chill :script
|
134
|
+
chill :script_local
|
132
135
|
|
133
136
|
# Version control systems
|
134
137
|
forced_hash :git
|
135
138
|
forced_hash :svn
|
136
139
|
|
137
|
-
def init
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
# Add remote shell commands to the DSL as forced Arrays.
|
142
|
-
# Example:
|
143
|
-
# ls :a, :l, "/tmp" # => :ls => [[:a, :l, "/tmp"]]
|
144
|
-
# ls :o # => :ls => [[:a, :l, "/tmp"], [:o]]
|
145
|
-
# NOTE: Beware of namespace conflicts in other areas of the DSL,
|
146
|
-
# specifically shell commands that have the same name as a keyword
|
147
|
-
# we want to use in the DSL. This includes commands that were added
|
148
|
-
# to Rye::Cmd before Rudy is 'require'd.
|
149
|
-
Rye::Cmd.instance_methods.sort.each do |cmd|
|
150
|
-
forced_array cmd
|
140
|
+
def init
|
151
141
|
end
|
152
|
-
|
142
|
+
|
153
143
|
end
|
154
144
|
end
|
data/lib/rudy/disks.rb
CHANGED
@@ -4,6 +4,7 @@ module Rudy
|
|
4
4
|
class Disk < Storable
|
5
5
|
include Rudy::MetaData::ObjectBase
|
6
6
|
|
7
|
+
|
7
8
|
field :rtype
|
8
9
|
field :awsid
|
9
10
|
field :status
|
@@ -20,6 +21,11 @@ class Disk < Storable
|
|
20
21
|
field :size
|
21
22
|
#field :backups => Array
|
22
23
|
|
24
|
+
# Is the associated volume formatted? One of: true, false, [empty].
|
25
|
+
# [empty] means we don't know and it's the default.
|
26
|
+
field :raw
|
27
|
+
|
28
|
+
field :fstype
|
23
29
|
field :mounted
|
24
30
|
|
25
31
|
def init(path=nil, size=nil, device=nil, position=nil)
|
@@ -46,7 +52,6 @@ class Disk < Storable
|
|
46
52
|
|
47
53
|
def to_s(with_titles=true)
|
48
54
|
update
|
49
|
-
puts "FUCK" if @mounted
|
50
55
|
mtd = @mounted == true ? "mounted" : @status
|
51
56
|
"%s; %3sGB; %s; %s" % [liner_note, @size, @device, mtd]
|
52
57
|
end
|
@@ -75,6 +80,7 @@ class Disk < Storable
|
|
75
80
|
raise "#{name} is already running" if exists?
|
76
81
|
vol = @rvol.create(@size, @zone, snapshot)
|
77
82
|
@awsid = vol.awsid
|
83
|
+
@raw = true
|
78
84
|
self.save
|
79
85
|
self
|
80
86
|
end
|
data/lib/rudy/global.rb
CHANGED
@@ -42,7 +42,7 @@ module Rudy
|
|
42
42
|
postprocess
|
43
43
|
# These attributes MUST have values.
|
44
44
|
@verbose ||= 0
|
45
|
-
@nocolor = true unless @nocolor == "false" || @nocolor
|
45
|
+
@nocolor = true unless @nocolor == "false" || @nocolor == false
|
46
46
|
@quiet ||= false
|
47
47
|
@format ||= :string # as in, to_s
|
48
48
|
@print_header = true if @print_header == nil
|
@@ -97,9 +97,9 @@ module Rudy
|
|
97
97
|
@position &&= @position.to_s.rjust(2, '0')
|
98
98
|
@format &&= @format.to_sym rescue nil
|
99
99
|
|
100
|
-
String.disable_color
|
101
|
-
Rudy.enable_quiet
|
102
|
-
Annoy.enable_skip
|
100
|
+
@nocolor ? String.disable_color : String.enable_color
|
101
|
+
@quiet ? Rudy.enable_quiet : Rudy.disable_quiet
|
102
|
+
@yes ? Annoy.enable_skip : Annoy.disable_skip
|
103
103
|
end
|
104
104
|
|
105
105
|
def apply_environment_variables
|
data/lib/rudy/huxtable.rb
CHANGED
@@ -38,8 +38,9 @@ module Rudy
|
|
38
38
|
#def logger; @@logger; end
|
39
39
|
|
40
40
|
def self.update_config(path=nil)
|
41
|
-
|
42
|
-
|
41
|
+
@@config.verbose = (@@global.verbose > 0)
|
42
|
+
# nil and bad paths sent to look_and_load are ignored
|
43
|
+
@@config.look_and_load(path || @@global.config)
|
43
44
|
@@global.apply_config(@@config)
|
44
45
|
end
|
45
46
|
|
data/lib/rudy/machines.rb
CHANGED
@@ -144,6 +144,9 @@ module Rudy
|
|
144
144
|
super
|
145
145
|
end
|
146
146
|
|
147
|
+
def restart
|
148
|
+
@ec2inst.restart(@awsid) if running?
|
149
|
+
end
|
147
150
|
|
148
151
|
def Machine.generate_machine_data
|
149
152
|
data = { # Give the machine an identity
|
@@ -223,6 +226,19 @@ module Rudy
|
|
223
226
|
end
|
224
227
|
end
|
225
228
|
|
229
|
+
|
230
|
+
def restart(&each_mach)
|
231
|
+
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
232
|
+
raise MachineGroupNotRunning, current_machine_group unless running?
|
233
|
+
machines = list
|
234
|
+
machines.each do |mach|
|
235
|
+
each_mach.call(mach) if each_mach
|
236
|
+
puts "Restarting #{mach.name}"
|
237
|
+
mach.restart
|
238
|
+
end
|
239
|
+
machines
|
240
|
+
end
|
241
|
+
|
226
242
|
def list(more=[], less=[], &each_mach)
|
227
243
|
machines = list_as_hash(more, less, &each_mach)
|
228
244
|
machines &&= machines.values
|
data/lib/rudy/routines.rb
CHANGED
@@ -50,12 +50,23 @@ module Rudy
|
|
50
50
|
|
51
51
|
if Rudy::Routines::ScriptHelper.before_local?(@routine) # before_local
|
52
52
|
# Runs "before_local" scripts of routines config.
|
53
|
-
# NOTE: Does not run "before" scripts b/c there are no remote machines
|
54
53
|
puts task_separator("LOCAL SHELL")
|
55
54
|
Rudy::Routines::ScriptHelper.before_local(@routine, sconf, lbox)
|
56
55
|
end
|
57
56
|
|
58
|
-
|
57
|
+
if Rudy::Routines::ScriptHelper.script_local?(@routine) # before_local
|
58
|
+
# Runs "script_local" scripts of routines config.
|
59
|
+
# NOTE: This is synonymous with before_local
|
60
|
+
puts task_separator("LOCAL SHELL")
|
61
|
+
Rudy::Routines::ScriptHelper.script_local(@routine, sconf, lbox)
|
62
|
+
end
|
63
|
+
|
64
|
+
unless has_remote_task?(@routine)
|
65
|
+
puts "[no remote tasks]"
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
# Execute the action (create, list, destroy, restart) & apply the block to each
|
59
70
|
rmach.send(machine_action) do |machine|
|
60
71
|
puts machine_separator(machine.name, machine.awsid)
|
61
72
|
|
@@ -131,7 +142,21 @@ module Rudy
|
|
131
142
|
|
132
143
|
# Startup, shutdown, release, deploy, etc...
|
133
144
|
routine_action.call(machine, rbox) if routine_action
|
134
|
-
|
145
|
+
|
146
|
+
# The "after" blocks are synonymous with "script" blocks.
|
147
|
+
# For some routines, like startup, it makes sense to an
|
148
|
+
# "after" block b/c "script" is ambiguous. In generic
|
149
|
+
# routines, there is no concept of before or after. The
|
150
|
+
# definition is the entire routine so we use "script".
|
151
|
+
# NOTE: If both after and script are supplied they will
|
152
|
+
# both be executed.
|
153
|
+
if Rudy::Routines::ScriptHelper.script?(@routine) # script
|
154
|
+
puts task_separator("REMOTE SHELL")
|
155
|
+
# Runs "after" scripts of routines config
|
156
|
+
Rudy::Routines::ScriptHelper.script(@routine, sconf, machine, rbox)
|
157
|
+
end
|
158
|
+
|
159
|
+
|
135
160
|
if Rudy::Routines::ScriptHelper.after?(@routine) # after
|
136
161
|
puts task_separator("REMOTE SHELL")
|
137
162
|
# Runs "after" scripts of routines config
|
@@ -156,6 +181,19 @@ module Rudy
|
|
156
181
|
|
157
182
|
end
|
158
183
|
|
184
|
+
# Does the given +routine+ define any remote tasks?
|
185
|
+
def has_remote_task?(routine)
|
186
|
+
any = [Rudy::Routines::DiskHelper.disks?(routine),
|
187
|
+
Rudy::Routines::ScriptHelper.before?(routine),
|
188
|
+
Rudy::Routines::ScriptHelper.after?(routine),
|
189
|
+
Rudy::Routines::ScriptHelper.script?(routine),
|
190
|
+
Rudy::Routines::UserHelper.authorize?(routine),
|
191
|
+
Rudy::Routines::UserHelper.adduser?(routine)]
|
192
|
+
# Throw away all false answers (and nil answers)
|
193
|
+
any = any.compact.select { |success| success }
|
194
|
+
!any.empty? # Returns true if any element contains true
|
195
|
+
end
|
196
|
+
|
159
197
|
def preliminary_separator(msg)
|
160
198
|
# TODO: Count number messages printed 1/3. ie:
|
161
199
|
# m-us-east-1b-stage-app-01
|
data/lib/rudy/routines/helper.rb
CHANGED
@@ -7,9 +7,13 @@ module Rudy
|
|
7
7
|
|
8
8
|
def execute_rbox_command(ret=nil, &command)
|
9
9
|
begin
|
10
|
-
ret = command.call
|
10
|
+
ret = command.call if command
|
11
|
+
return unless ret.is_a?(Rye::Rap)
|
11
12
|
puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
|
12
13
|
print_response(ret)
|
14
|
+
rescue IOError => ex
|
15
|
+
STDERR.puts " Connection Error (#{ex.message})".color(:red)
|
16
|
+
exit 12 unless keep_going?
|
13
17
|
rescue Rye::CommandError => ex
|
14
18
|
print_response(ex)
|
15
19
|
exit 12 unless keep_going?
|
@@ -39,7 +43,8 @@ module Rudy
|
|
39
43
|
colour = rap.exit_code != 0 ? :red : :normal
|
40
44
|
[:stderr].each do |sumpin|
|
41
45
|
next if rap.send(sumpin).empty?
|
42
|
-
STDERR.puts
|
46
|
+
STDERR.puts
|
47
|
+
STDERR.puts((" #{sumpin.to_s.upcase} " << '-'*38).color(colour).bright)
|
43
48
|
STDERR.puts " " << rap.send(sumpin).join("#{$/} ").color(colour)
|
44
49
|
end
|
45
50
|
STDERR.puts " Exit code: #{rap.exit_code}".color(colour) if rap.exit_code != 0
|
@@ -7,7 +7,7 @@ module Rudy; module Routines;
|
|
7
7
|
|
8
8
|
def disks?(routine)
|
9
9
|
(routine.is_a?(Caesars::Hash) && routine.disks &&
|
10
|
-
routine.disks.is_a?(Caesars::Hash) && !routine.disks.empty?)
|
10
|
+
routine.disks.is_a?(Caesars::Hash) && !routine.disks.empty?) ? true : false
|
11
11
|
end
|
12
12
|
|
13
13
|
def paths(routine)
|
@@ -25,18 +25,24 @@ module Rudy; module Routines;
|
|
25
25
|
|
26
26
|
# We need to add mkfs since it's not enabled by default.
|
27
27
|
# We add it only to this instance we're using.
|
28
|
-
|
28
|
+
# We give it a funny name so we can delete it.
|
29
|
+
def @rbox.rudy_mkfs(*args); cmd('mkfs', args); end
|
29
30
|
|
30
|
-
return unless disks?(routine)
|
31
31
|
|
32
|
+
return unless disks?(routine)
|
33
|
+
|
34
|
+
modified = []
|
32
35
|
routine.disks.each_pair do |action, disks|
|
33
36
|
unless DiskHelper.respond_to?(action)
|
34
37
|
STDERR.puts %Q(DiskHelper: unknown action "#{action}")
|
35
38
|
next
|
36
39
|
end
|
37
40
|
send(action, disks) # create, copy, destroy, ...
|
41
|
+
modified << disks
|
38
42
|
end
|
39
43
|
|
44
|
+
# TODO: remove rudy_mkfs method
|
45
|
+
|
40
46
|
end
|
41
47
|
|
42
48
|
def create(disks)
|
@@ -46,17 +52,26 @@ module Rudy; module Routines;
|
|
46
52
|
disk = Rudy::Disk.new(path, props[:size], props[:device], @machine.position)
|
47
53
|
olddisk = rdisk.get(disk.name)
|
48
54
|
if olddisk && olddisk.exists?
|
49
|
-
|
50
|
-
|
55
|
+
olddisk.update
|
56
|
+
puts "Disk found: #{olddisk.name}"
|
57
|
+
if olddisk.attached?
|
58
|
+
puts "In use. Skipping...".color(:red)
|
59
|
+
return
|
60
|
+
else
|
61
|
+
disk = olddisk
|
62
|
+
end
|
63
|
+
else
|
64
|
+
puts "Creating #{disk.name} "
|
65
|
+
disk.fstype = props[:fstype] || 'ext3'
|
51
66
|
end
|
52
67
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
68
|
+
unless disk.exists? # Checks the EBS volume
|
69
|
+
msg = "Creating volume... "
|
70
|
+
disk.create
|
71
|
+
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
72
|
+
disk.available?
|
73
|
+
}
|
74
|
+
end
|
60
75
|
|
61
76
|
msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
|
62
77
|
disk.attach(@machine.awsid)
|
@@ -71,30 +86,40 @@ module Rudy; module Routines;
|
|
71
86
|
|
72
87
|
# TODO: Cleanup. See ScriptHelper
|
73
88
|
begin
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
89
|
+
if disk.raw == true
|
90
|
+
print "Creating #{disk.fstype} filesystem for #{disk.device}... "
|
91
|
+
@rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
|
92
|
+
disk.raw = false
|
93
|
+
disk.save
|
79
94
|
puts "done"
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
95
|
+
end
|
96
|
+
|
97
|
+
@rbox.mkdir(:p, disk.path)
|
98
|
+
|
99
|
+
print "Mounting at #{disk.path}... "
|
100
|
+
|
101
|
+
ret = @rbox.mount(:t, disk.fstype, disk.device, disk.path)
|
102
|
+
print_response ret
|
103
|
+
if ret.exit_code > 0
|
104
|
+
STDERR.puts "Error creating disk".color(:red)
|
105
|
+
return
|
106
|
+
else
|
107
|
+
puts "done"
|
108
|
+
end
|
85
109
|
disk.mounted = true
|
86
110
|
disk.save
|
111
|
+
|
87
112
|
rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
|
88
113
|
STDERR.puts "Error creating disk".color(:red)
|
89
114
|
STDERR.puts ex.message.color(:red)
|
90
115
|
rescue Rye::CommandNotFound => ex
|
91
116
|
puts " CommandNotFound: #{ex.message}".color(:red)
|
117
|
+
|
92
118
|
rescue
|
93
119
|
STDERR.puts "Error creating disk" .color(:red)
|
94
120
|
Rudy::Utils.bug
|
95
121
|
end
|
96
|
-
|
97
|
-
|
122
|
+
|
98
123
|
end
|
99
124
|
end
|
100
125
|
|
@@ -127,7 +152,7 @@ module Rudy; module Routines;
|
|
127
152
|
sleep 0.5
|
128
153
|
end
|
129
154
|
|
130
|
-
puts "Destroying metadata... "
|
155
|
+
puts "Destroying volume and metadata... "
|
131
156
|
disk.destroy
|
132
157
|
|
133
158
|
end
|
@@ -8,28 +8,43 @@ module Rudy; module Routines;
|
|
8
8
|
include Rudy::Routines::HelperBase # TODO: use execute_rbox_command
|
9
9
|
extend self
|
10
10
|
|
11
|
-
@@script_types = [:after, :before, :after_local, :before_local]
|
11
|
+
@@script_types = [:after, :before, :after_local, :before_local, :script, :script_local]
|
12
12
|
@@script_config_file = "rudy-config.yml"
|
13
13
|
|
14
|
+
# TODO: refactor using this_method
|
15
|
+
|
14
16
|
def before_local(routine, sconf, rbox)
|
15
|
-
|
17
|
+
execute_command(:before_local, routine, sconf, 'localhost', rbox)
|
18
|
+
end
|
19
|
+
def before_local?(routine)
|
16
20
|
# before_local generally doesn't take a user name like the remote
|
17
21
|
# before block so we add it here (unless the user did specify it)
|
18
22
|
routine[:before_local] = {
|
19
|
-
|
20
|
-
}
|
21
|
-
execute_command(:before_local, routine
|
23
|
+
Rudy.sysinfo.user.to_sym => routine.delete(:before_local)
|
24
|
+
} if routine[:before_local].is_a?(Proc)
|
25
|
+
execute_command?(:before_local, routine)
|
22
26
|
end
|
23
|
-
def
|
24
|
-
|
27
|
+
def script_local(routine, sconf, rbox)
|
28
|
+
execute_command(:script_local, routine, sconf, 'localhost', rbox)
|
29
|
+
end
|
30
|
+
def script_local?(routine)
|
31
|
+
# before_local generally doesn't take a user name like the remote
|
32
|
+
# before block so we add it here (unless the user did specify it)
|
33
|
+
routine[:script_local] = {
|
34
|
+
Rudy.sysinfo.user.to_sym => routine.delete(:script_local)
|
35
|
+
} if routine[:script_local].is_a?(Proc)
|
36
|
+
execute_command?(:script_local, routine)
|
37
|
+
end
|
38
|
+
|
25
39
|
def after_local(routine, sconf, rbox)
|
26
|
-
routine[:after_local] = { # See before_local note
|
27
|
-
rbox.user.to_sym => routine.delete(:after_local)
|
28
|
-
} unless routine.has_key?(rbox.user.to_sym)
|
29
40
|
execute_command(:after_local, routine, sconf, 'localhost', rbox)
|
30
41
|
end
|
31
|
-
def after_local?(routine)
|
32
|
-
|
42
|
+
def after_local?(routine)
|
43
|
+
routine[:after_local] = { # See before_local note
|
44
|
+
Rudy.sysinfo.user.to_sym => routine.delete(:after_local)
|
45
|
+
} if routine[:after_local].is_a?(Proc)
|
46
|
+
execute_command?(:after_local, routine)
|
47
|
+
end
|
33
48
|
|
34
49
|
def before(routine, sconf, machine, rbox)
|
35
50
|
raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
|
@@ -43,6 +58,12 @@ module Rudy; module Routines;
|
|
43
58
|
end
|
44
59
|
def after?(routine); execute_command?(:after, routine); end
|
45
60
|
|
61
|
+
def script(routine, sconf, machine, rbox)
|
62
|
+
raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
|
63
|
+
execute_command(:script, routine, sconf, machine.name, rbox)
|
64
|
+
end
|
65
|
+
def script?(routine); execute_command?(:script, routine); end
|
66
|
+
|
46
67
|
|
47
68
|
private
|
48
69
|
|
@@ -53,8 +74,9 @@ module Rudy; module Routines;
|
|
53
74
|
def execute_command?(timing, routine)
|
54
75
|
hasconf = (routine.is_a?(Caesars::Hash) && routine.has_key?(timing))
|
55
76
|
return false unless hasconf
|
56
|
-
routine[timing].each_pair do |user,
|
57
|
-
|
77
|
+
routine[timing].each_pair do |user,proc|
|
78
|
+
#p [timing, user, proc].join(', ')
|
79
|
+
if proc.nil? || !proc.is_a?(Proc)
|
58
80
|
STDERR.puts "Empty #{timing} config for #{user}"
|
59
81
|
else
|
60
82
|
return true
|
@@ -77,16 +99,22 @@ module Rudy; module Routines;
|
|
77
99
|
Rudy::Utils.write_to_file(tf.path, sconf.to_hash.to_yaml, 'w')
|
78
100
|
end
|
79
101
|
|
80
|
-
# We need to explicitly add the rm command for rbox so we
|
81
|
-
# can delete the script config file when we're done. This
|
82
|
-
# add the method on for the instance of rbox we are using.
|
83
|
-
def rbox.rm(*args); cmd('rm', args); end
|
84
|
-
|
85
102
|
if execute_command?(timing, routine) # i.e. before_local?
|
103
|
+
|
104
|
+
# We need to explicitly add the rm command for rbox so we
|
105
|
+
# can delete the script config file when we're done. This
|
106
|
+
# adds the method to this instance of rbox only.
|
107
|
+
# We give it a funny so we can delete it knowing we're not
|
108
|
+
# deleting a method added somewhere else.
|
109
|
+
def rbox.rudy_tmp_rm(*args); cmd('rm', args); end
|
86
110
|
|
87
111
|
original_user = rbox.user
|
88
|
-
|
89
|
-
users
|
112
|
+
user_blocks = routine[timing] || {}
|
113
|
+
users = user_blocks.keys
|
114
|
+
# Root stuff is always run first.
|
115
|
+
users.unshift(users.delete(:root)) if users.member?(:root)
|
116
|
+
users.each do |user|
|
117
|
+
proc = user_blocks[user]
|
90
118
|
|
91
119
|
begin
|
92
120
|
rbox.switch_user user # does nothing if it's the same user
|
@@ -108,32 +136,45 @@ module Rudy; module Routines;
|
|
108
136
|
rbox.upload(conf_str, @@script_config_file)
|
109
137
|
rbox.chmod(600, @@script_config_file)
|
110
138
|
}
|
111
|
-
|
112
|
-
|
113
|
-
#
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
next
|
139
|
+
|
140
|
+
begin
|
141
|
+
# We define hooks so we can call the script block as a batch.
|
142
|
+
# We intentionally set and unset the hooks so the other commands
|
143
|
+
# (config file copy) don't get printed.
|
144
|
+
#
|
145
|
+
# This block gets called for every command method call.
|
146
|
+
rbox.pre_command_hook do |cmd, args, user|
|
147
|
+
puts command_separator(rbox.preview_command(cmd, args), user)
|
121
148
|
end
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
execute_rbox_command { ret = rbox.send(command, args) }
|
149
|
+
# And this one gets called after each command method call.
|
150
|
+
rbox.post_command_hook do |ret|
|
151
|
+
puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
|
152
|
+
print_response(ret)
|
127
153
|
end
|
154
|
+
|
155
|
+
### EXECUTE THE COMMANDS BLOCK
|
156
|
+
rbox.batch(&proc)
|
157
|
+
|
158
|
+
rbox.pre_command_hook = nil
|
159
|
+
rbox.post_command_hook = nil
|
160
|
+
rescue Rye::CommandError => ex
|
161
|
+
print_response(ex)
|
162
|
+
exit 12 unless keep_going?
|
163
|
+
rescue Rye::CommandNotFound => ex
|
164
|
+
STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
|
165
|
+
STDERR.puts ex.backtrace if Rudy.debug?
|
166
|
+
exit 12 unless keep_going?
|
128
167
|
end
|
129
168
|
|
130
169
|
# I was gettings errors about script_config_file not existing. There
|
131
170
|
# might be a race condition when the rm command is called too quickly.
|
132
171
|
# It's also quite possible I'm off my rocker!
|
133
|
-
|
172
|
+
## NOTE: I believe this was an issue with Rye. I fixed it when I was
|
173
|
+
## noticing the same error in another place. It hasn't repeated.
|
174
|
+
## sleep 0.1
|
134
175
|
|
135
176
|
rbox.cd # reset to home dir
|
136
|
-
|
177
|
+
rbox.rudy_tmp_rm(@@script_config_file)
|
137
178
|
end
|
138
179
|
|
139
180
|
# Return the borrowed rbox instance to the user it was provided with
|
@@ -5,7 +5,7 @@ module Rudy; module Routines;
|
|
5
5
|
extend self
|
6
6
|
|
7
7
|
def adduser?(routine)
|
8
|
-
(!routine.adduser.nil? && !routine.adduser.empty?)
|
8
|
+
(!routine.adduser.nil? && !routine.adduser.to_s.empty?)
|
9
9
|
end
|
10
10
|
def adduser(routine, machine, rbox)
|
11
11
|
|
@@ -13,7 +13,7 @@ module Rudy; module Routines;
|
|
13
13
|
# explicitly so we do it for linux too for fun.
|
14
14
|
homedir = rbox.guess_user_home(routine.adduser.to_s)
|
15
15
|
args = [:m, :d, homedir, :s, '/bin/bash', routine.adduser.to_s]
|
16
|
-
puts command_separator(rbox.preview_command(:useradd, args),
|
16
|
+
puts command_separator(rbox.preview_command(:useradd, args), rbox.user)
|
17
17
|
|
18
18
|
# NOTE: We'll may to use platform specific code here.
|
19
19
|
# Linux has adduser and useradd commands:
|
@@ -24,10 +24,10 @@ module Rudy; module Routines;
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def authorize?(routine)
|
27
|
-
(!routine.authorize.nil? && !routine.authorize.empty?)
|
27
|
+
(!routine.authorize.nil? && !routine.authorize.to_s.empty?)
|
28
28
|
end
|
29
29
|
def authorize(routine, machine, rbox)
|
30
|
-
puts command_separator(:authorize_keys_remote,
|
30
|
+
puts command_separator(:authorize_keys_remote, rbox.user)
|
31
31
|
execute_rbox_command { rbox.authorize_keys_remote(routine.authorize) }
|
32
32
|
end
|
33
33
|
|
@@ -14,7 +14,7 @@ module Rudy; module Routines;
|
|
14
14
|
def execute(&each_mach)
|
15
15
|
routine_separator(@routine_name)
|
16
16
|
machines = []
|
17
|
-
generic_machine_runner(:list) do |machine|
|
17
|
+
generic_machine_runner(:list) do |machine,rbox|
|
18
18
|
puts $/ #, "[routine: #{@routine_name}]"
|
19
19
|
machines << machine
|
20
20
|
end
|
@@ -16,8 +16,12 @@ module Rudy; module Routines;
|
|
16
16
|
STDERR.puts "[this is a generic startup routine]"
|
17
17
|
@routine = {}
|
18
18
|
end
|
19
|
+
machines = []
|
19
20
|
generic_machine_runner(:create) do |machine,rbox|
|
21
|
+
puts $/, "Starting up...", $/
|
22
|
+
machines << machine
|
20
23
|
end
|
24
|
+
machines
|
21
25
|
end
|
22
26
|
|
23
27
|
# Called by generic_machine_runner
|
data/lib/rudy/scm/git.rb
CHANGED
@@ -17,6 +17,7 @@ module Rudy
|
|
17
17
|
attr_reader :rtag
|
18
18
|
attr_reader :user
|
19
19
|
attr_reader :pkey
|
20
|
+
attr_reader :commit
|
20
21
|
|
21
22
|
# * +args+ a hash of params from the git block in the routines config
|
22
23
|
#
|
@@ -26,10 +27,11 @@ module Rudy
|
|
26
27
|
:remote => :origin,
|
27
28
|
:branch => :master,
|
28
29
|
:user => :root,
|
30
|
+
:commit => :enforce,
|
29
31
|
:path => nil
|
30
32
|
}.merge(args)
|
31
33
|
@remote, @branch, @path = args[:remote], args[:branch], args[:path]
|
32
|
-
@user, @pkey = args[:user], args[:privatekey]
|
34
|
+
@user, @pkey, @commit = args[:user], args[:privatekey], args[:commit]
|
33
35
|
@repo = Repo.new(Dir.pwd) if GIT.working_copy?
|
34
36
|
end
|
35
37
|
|
@@ -196,7 +198,7 @@ module Rudy
|
|
196
198
|
|
197
199
|
def raise_early_exceptions
|
198
200
|
raise NotAWorkingCopy, :git unless working_copy?
|
199
|
-
|
201
|
+
raise DirtyWorkingCopy, :git unless @commit.to_s == 'ignore' || clean_working_copy?
|
200
202
|
raise NoRemoteURI, "remote.#{@remote}.url not set" if get_remote_uri.nil?
|
201
203
|
raise NoRemotePath, :git if @path.nil?
|
202
204
|
raise PrivateKeyNotFound, @pkey if @pkey && !File.exists?(@pkey)
|
data/rudy.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "rudy"
|
3
3
|
s.rubyforge_project = 'rudy'
|
4
|
-
s.version = "0.7.
|
4
|
+
s.version = "0.7.1"
|
5
5
|
s.summary = "Rudy: Not your grandparents' EC2 deployment tool."
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
@@ -14,9 +14,9 @@
|
|
14
14
|
s.require_paths = %w[lib]
|
15
15
|
s.rubygems_version = '1.1.1'
|
16
16
|
|
17
|
-
s.add_dependency 'drydock', '>= 0.6.
|
18
|
-
s.add_dependency 'caesars', '>= 0.6.
|
19
|
-
s.add_dependency 'rye', '>= 0.6.
|
17
|
+
s.add_dependency 'drydock', '>= 0.6.1'
|
18
|
+
s.add_dependency 'caesars', '>= 0.6.3'
|
19
|
+
s.add_dependency 'rye', '>= 0.6.4'
|
20
20
|
|
21
21
|
s.add_dependency 'grit'
|
22
22
|
s.add_dependency 'echoe'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rudy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-04 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.6.
|
23
|
+
version: 0.6.1
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: caesars
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.6.
|
33
|
+
version: 0.6.3
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rye
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.6.
|
43
|
+
version: 0.6.4
|
44
44
|
version:
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: grit
|