rudy 0.7.0 → 0.7.1
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/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
|