solutious-rudy 0.8.2 → 0.8.3

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/lib/rudy/routines.rb CHANGED
@@ -8,8 +8,11 @@ module Rudy
8
8
 
9
9
  class Base
10
10
  include Rudy::Huxtable
11
-
12
- def initialize(*args)
11
+
12
+ # * +cmdname+ The name of the command specified on the command line
13
+ # * +option+ An OpenStruct of named command line options
14
+ # * +argv+ An Array of command line argument
15
+ def initialize(cmdname, option, argv, *args)
13
16
  a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
14
17
  @sdb = Rudy::AWS::SDB.new(a, s, r)
15
18
  @rinst = Rudy::AWS::EC2::Instances.new(a, s, r)
@@ -17,11 +20,12 @@ module Rudy
17
20
  @rkey = Rudy::AWS::EC2::KeyPairs.new(a, s, r)
18
21
  @rvol = Rudy::AWS::EC2::Volumes.new(a, s, r)
19
22
  @rsnap = Rudy::AWS::EC2::Snapshots.new(a, s, r)
23
+ @cmdname, @option, @argv = cmdname, option, argv
24
+ @option ||= OpenStruct.new
20
25
  init(*args)
21
26
  end
22
27
 
23
- def init
24
- end
28
+ def init; raise "Must override init"; end
25
29
 
26
30
  def execute
27
31
  raise "Override execute method"
@@ -39,6 +43,8 @@ module Rudy
39
43
  # machine between the disk routine and after blocks. The block receives
40
44
  # two argument: an instance of Rudy::Machine and one of Rye::Box.
41
45
  def generic_machine_runner(machine_action, routine=nil, skip_check=false, skip_header=false, &routine_action)
46
+ is_available= false
47
+
42
48
  if @@global.offline
43
49
  rmach = Rudy::Machines::Offline.new
44
50
  skip_check = true
@@ -74,15 +80,15 @@ module Rudy
74
80
  }
75
81
 
76
82
 
77
- lbox = Rye::Box.new('localhost')
83
+ lbox = Rye::Box.new('localhost', :info => (@@global.verbose > 3), :debug => false)
78
84
  sconf = fetch_script_config
79
85
 
80
86
  enjoy_every_sandwich {
81
87
  if Rudy::Routines::ScriptHelper.before_local?(routine) # before_local
82
88
  # Runs "before_local" scripts of routines config.
83
- puts task_separator("LOCAL SHELL")
89
+ task_separator("LOCAL SHELL")
84
90
  lbox.cd Dir.pwd # Run local command block from current working directory
85
- Rudy::Routines::ScriptHelper.before_local(routine, sconf, lbox)
91
+ Rudy::Routines::ScriptHelper.before_local(routine, sconf, lbox, @option, @argv)
86
92
  end
87
93
  }
88
94
 
@@ -90,9 +96,9 @@ module Rudy
90
96
  if Rudy::Routines::ScriptHelper.script_local?(routine) # script_local
91
97
  # Runs "script_local" scripts of routines config.
92
98
  # NOTE: This is synonymous with before_local
93
- puts task_separator("LOCAL SHELL")
99
+ task_separator("LOCAL SHELL")
94
100
  lbox.cd Dir.pwd # Run local command block from current working directory
95
- Rudy::Routines::ScriptHelper.script_local(routine, sconf, lbox)
101
+ Rudy::Routines::ScriptHelper.script_local(routine, sconf, lbox, @option, @argv)
96
102
  end
97
103
  }
98
104
 
@@ -131,80 +137,86 @@ module Rudy
131
137
  next # The short circuit
132
138
  end
133
139
 
134
- unless skip_check
135
- msg = preliminary_separator("Waiting for SSH daemon...")
136
- Rudy::Utils.waiter(2, 60, STDOUT, msg, 0) {
137
- Rudy::Utils.service_available?(machine.dns_public, 22)
140
+ if !skip_check && has_remote_task?(routine)
141
+ enjoy_every_sandwich {
142
+ msg = preliminary_separator("Waiting for SSH daemon...")
143
+ ret = Rudy::Utils.waiter(2, 1, STDOUT, msg, 0) {
144
+ Rudy::Utils.service_available?(machine.dns_public, 22)
145
+ }
146
+ is_available = ret
138
147
  }
139
148
  end
140
149
 
141
- # TODO: trap rbox errors. We could get an authentication error.
142
- opts = { :keys => root_keypairpath, :user => remote_user, :info => @@global.verbose > 0 }
143
- begin
144
- rbox = Rye::Box.new(machine.dns_public, opts)
145
- rbox.connect
146
- rescue Rye::NoHost => ex
147
- STDERR.puts "No host: #{ex.message}"
148
- exit 65
149
- end
150
+ if is_available
151
+ # TODO: trap rbox errors. We could get an authentication error.
152
+ opts = { :keys => root_keypairpath, :user => remote_user, :info => @@global.verbose > 0 }
153
+ begin
154
+ rbox = Rye::Box.new(machine.dns_public, opts)
155
+ Rudy::Utils.waiter(2, 10, STDOUT, nil, 0) { rbox.connect }
156
+ rescue Rye::NoHost => ex
157
+ STDERR.puts "No host: #{ex.message}"
158
+ exit 65
159
+ end
150
160
 
151
- unless skip_check
152
- # Set the hostname if specified in the machines config.
153
- # :rudy -> change to Rudy's machine name
154
- # :default -> leave the hostname as it is
155
- # Anything else other than nil -> change to that value
156
- # NOTE: This will set hostname every time a routine is
157
- # run so we may want to make this an explicit action.
161
+ unless skip_check
162
+ # Set the hostname if specified in the machines config.
163
+ # :rudy -> change to Rudy's machine name
164
+ # :default -> leave the hostname as it is
165
+ # Anything else other than nil -> change to that value
166
+ # NOTE: This will set hostname every time a routine is
167
+ # run so we may want to make this an explicit action.
168
+ enjoy_every_sandwich {
169
+ hn = current_machine_hostname || :rudy
170
+ if hn != :default
171
+ hn = machine.name if hn == :rudy
172
+ print preliminary_separator("Setting hostname to #{hn}... ")
173
+ rbox.hostname(hn)
174
+ puts "done"
175
+ end
176
+ }
177
+ end
178
+
179
+
180
+ ## NOTE: This prevents shutdown from doing its thing and prob
181
+ ## isn't necessary.
182
+ ##unless has_remote_task?(routine)
183
+ ## puts "[no remote tasks]"
184
+ ## next
185
+ ##end
186
+
158
187
  enjoy_every_sandwich {
159
- hn = current_machine_hostname || :rudy
160
- if hn != :default
161
- hn = machine.name if hn == :rudy
162
- print preliminary_separator("Setting hostame to #{hn}... ")
163
- rbox.hostname(hn)
164
- puts "done"
188
+ if Rudy::Routines::UserHelper.adduser?(routine) # adduser
189
+ task_separator("ADD USER")
190
+ Rudy::Routines::UserHelper.adduser(routine, machine, rbox)
165
191
  end
166
192
  }
167
- end
168
193
 
169
- ## NOTE: This prevents shutdown from doing its thing and prob
170
- ## isn't necessary.
171
- ##unless has_remote_task?(routine)
172
- ## puts "[no remote tasks]"
173
- ## next
174
- ##end
175
-
176
- enjoy_every_sandwich {
177
- if Rudy::Routines::UserHelper.adduser?(routine) # adduser
178
- puts task_separator("ADD USER")
179
- Rudy::Routines::UserHelper.adduser(routine, machine, rbox)
180
- end
181
- }
182
-
183
- enjoy_every_sandwich {
184
- if Rudy::Routines::UserHelper.authorize?(routine) # authorize
185
- puts task_separator("AUTHORIZE USER")
186
- Rudy::Routines::UserHelper.authorize(routine, machine, rbox)
187
- end
188
- }
194
+ enjoy_every_sandwich {
195
+ if Rudy::Routines::UserHelper.authorize?(routine) # authorize
196
+ task_separator("AUTHORIZE USER")
197
+ Rudy::Routines::UserHelper.authorize(routine, machine, rbox)
198
+ end
199
+ }
189
200
 
190
- enjoy_every_sandwich {
191
- if Rudy::Routines::ScriptHelper.before?(routine) # before
192
- puts task_separator("REMOTE SHELL")
193
- Rudy::Routines::ScriptHelper.before(routine, sconf, machine, rbox)
194
- end
195
- }
201
+ enjoy_every_sandwich {
202
+ if Rudy::Routines::ScriptHelper.before?(routine) # before
203
+ task_separator("REMOTE SHELL")
204
+ Rudy::Routines::ScriptHelper.before(routine, sconf, machine, rbox, @option, @argv)
205
+ end
206
+ }
196
207
 
197
- enjoy_every_sandwich {
198
- if Rudy::Routines::DiskHelper.disks?(routine) # disk
199
- puts task_separator("DISKS")
200
- if rbox.ostype == "sunos"
201
- puts "Sorry, Solaris disks are not supported yet!"
202
- else
203
- Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
204
- end
205
- end
206
- }
208
+ enjoy_every_sandwich {
209
+ if Rudy::Routines::DiskHelper.disks?(routine) # disk
210
+ task_separator("DISKS")
211
+ if rbox.ostype == "sunos"
212
+ puts "Sorry, Solaris disks are not supported yet!"
213
+ else
214
+ Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
215
+ end
216
+ end
217
+ }
207
218
 
219
+ end
208
220
 
209
221
  enjoy_every_sandwich {
210
222
  # Startup, shutdown, release, deploy, etc...
@@ -212,38 +224,40 @@ module Rudy
212
224
  }
213
225
 
214
226
 
215
- # The "after" blocks are synonymous with "script" blocks.
216
- # For some routines, like startup, it makes sense to an
217
- # "after" block b/c "script" is ambiguous. In generic
218
- # routines, there is no concept of before or after. The
219
- # definition is the entire routine so we use "script".
220
- # NOTE: If both after and script are supplied they will
221
- # both be executed.
222
- enjoy_every_sandwich {
223
- if Rudy::Routines::ScriptHelper.script?(routine) # script
224
- puts task_separator("REMOTE SHELL")
225
- # Runs "after" scripts of routines config
226
- Rudy::Routines::ScriptHelper.script(routine, sconf, machine, rbox)
227
- end
228
- }
227
+ if is_available
228
+ # The "after" blocks are synonymous with "script" blocks.
229
+ # For some routines, like startup, it makes sense to an
230
+ # "after" block b/c "script" is ambiguous. In generic
231
+ # routines, there is no concept of before or after. The
232
+ # definition is the entire routine so we use "script".
233
+ # NOTE: If both after and script are supplied they will
234
+ # both be executed.
235
+ enjoy_every_sandwich {
236
+ if Rudy::Routines::ScriptHelper.script?(routine) # script
237
+ task_separator("REMOTE SHELL")
238
+ # Runs "after" scripts of routines config
239
+ Rudy::Routines::ScriptHelper.script(routine, sconf, machine, rbox, @option, @argv)
240
+ end
241
+ }
229
242
 
230
- enjoy_every_sandwich {
231
- if Rudy::Routines::ScriptHelper.after?(routine) # after
232
- puts task_separator("REMOTE SHELL")
233
- # Runs "after" scripts of routines config
234
- Rudy::Routines::ScriptHelper.after(routine, sconf, machine, rbox)
235
- end
236
- }
243
+ enjoy_every_sandwich {
244
+ if Rudy::Routines::ScriptHelper.after?(routine) # after
245
+ task_separator("REMOTE SHELL")
246
+ # Runs "after" scripts of routines config
247
+ Rudy::Routines::ScriptHelper.after(routine, sconf, machine, rbox, @option, @argv)
248
+ end
249
+ }
237
250
 
238
- rbox.disconnect
251
+ rbox.disconnect
252
+ end
239
253
  end
240
-
254
+
241
255
  enjoy_every_sandwich {
242
256
  if Rudy::Routines::ScriptHelper.after_local?(routine) # after_local
243
- puts task_separator("LOCAL SHELL")
257
+ task_separator("LOCAL SHELL")
244
258
  lbox.cd Dir.pwd # Run local command block from current working directory
245
259
  # Runs "after_local" scripts of routines config
246
- Rudy::Routines::ScriptHelper.after_local(routine, sconf, lbox)
260
+ Rudy::Routines::ScriptHelper.after_local(routine, sconf, lbox, @option, @argv)
247
261
  end
248
262
  }
249
263
 
@@ -259,7 +273,7 @@ module Rudy
259
273
  return unless depends
260
274
  unless depends.empty?
261
275
  depends.each_with_index do |d, index|
262
- puts task_separator("DEPENDENCY: #{d}")
276
+ task_separator("DEPENDENCY: #{d}")
263
277
  routine_dependency = fetch_routine_config(d)
264
278
  unless routine_dependency
265
279
  STDERR.puts " Unknown routine: #{d}".color(:red)
@@ -302,7 +316,7 @@ module Rudy
302
316
  def task_separator(title)
303
317
  dashes = 59 - title.size
304
318
  dashes = 0 if dashes < 1
305
- ("%s--- %s %s" % [$/, title, '-'*dashes])
319
+ puts ("%s--- %s %s" % [$/, title, '-'*dashes]) if @@global.verbose > 2
306
320
  end
307
321
 
308
322
  def machine_separator(name, awsid)
@@ -323,7 +337,14 @@ module Rudy
323
337
  rescue => ex
324
338
  STDERR.puts " Error: #{ex.message}".color(:red)
325
339
  STDERR.puts ex.backtrace if Rudy.debug?
326
- exit 12 unless keep_going?
340
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
341
+ if choice.match(/\AS/i)
342
+ return
343
+ elsif choice.match(/\AR/i)
344
+ retry
345
+ else
346
+ exit 12
347
+ end
327
348
  rescue Interrupt
328
349
  puts "Aborting..."
329
350
  exit 12
@@ -331,10 +352,6 @@ module Rudy
331
352
  ret
332
353
  end
333
354
 
334
- def keep_going?
335
- Annoy.pose_question(" Keep going?\a ", /yes|y|ya|sure|you bet!/i, STDERR)
336
- end
337
-
338
355
  end
339
356
  end
340
357
  end
@@ -13,14 +13,35 @@ module Rudy
13
13
  print_response(ret)
14
14
  rescue IOError => ex
15
15
  STDERR.puts " Connection Error (#{ex.message})".color(:red)
16
- exit 12 unless keep_going?
16
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
17
+ if choice.match(/\AS/i)
18
+ return
19
+ elsif choice.match(/\AR/i)
20
+ retry
21
+ else
22
+ exit 12
23
+ end
17
24
  rescue Rye::CommandError => ex
18
25
  print_response(ex)
19
- exit 12 unless keep_going?
26
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
27
+ if choice.match(/\AS/i)
28
+ return
29
+ elsif choice.match(/\AR/i)
30
+ retry
31
+ else
32
+ exit 12
33
+ end
20
34
  rescue Rye::CommandNotFound => ex
21
35
  STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
22
36
  STDERR.puts ex.backtrace if Rudy.debug?
23
- exit 12 unless keep_going?
37
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
38
+ if choice.match(/\AS/i)
39
+ return
40
+ elsif choice.match(/\AR/i)
41
+ retry
42
+ else
43
+ exit 12
44
+ end
24
45
  end
25
46
 
26
47
  ret
@@ -31,11 +52,11 @@ module Rudy
31
52
  end
32
53
 
33
54
  # Returns a formatted string for printing command info
34
- def command_separator(cmd, user)
55
+ def command_separator(cmd, user, host)
35
56
  cmd ||= ""
36
57
  cmd, user = cmd.to_s, user.to_s
37
58
  prompt = user == "root" ? "#" : "$"
38
- ("%s%s%s %s" % [$/, user, prompt, cmd.bright])
59
+ ("%s@%s%s %s" % [user, host, prompt, cmd.bright])
39
60
  end
40
61
 
41
62
  private
@@ -13,8 +13,8 @@ module Rudy; module Routines;
13
13
 
14
14
  # TODO: refactor using this_method
15
15
 
16
- def before_local(routine, sconf, rbox)
17
- execute_command(:before_local, routine, sconf, 'localhost', rbox)
16
+ def before_local(routine, sconf, rbox, option=nil, argv=nil)
17
+ execute_command(:before_local, routine, sconf, 'localhost', rbox, option, argv)
18
18
  end
19
19
  def before_local?(routine)
20
20
  # before_local generally doesn't take a user name like the remote
@@ -24,8 +24,8 @@ module Rudy; module Routines;
24
24
  } if routine[:before_local].is_a?(Proc)
25
25
  execute_command?(:before_local, routine)
26
26
  end
27
- def script_local(routine, sconf, rbox)
28
- execute_command(:script_local, routine, sconf, 'localhost', rbox)
27
+ def script_local(routine, sconf, rbox, option=nil, argv=nil)
28
+ execute_command(:script_local, routine, sconf, 'localhost', rbox, option, argv)
29
29
  end
30
30
  def script_local?(routine)
31
31
  # before_local generally doesn't take a user name like the remote
@@ -36,8 +36,8 @@ module Rudy; module Routines;
36
36
  execute_command?(:script_local, routine)
37
37
  end
38
38
 
39
- def after_local(routine, sconf, rbox)
40
- execute_command(:after_local, routine, sconf, 'localhost', rbox)
39
+ def after_local(routine, sconf, rbox, option=nil, argv=nil)
40
+ execute_command(:after_local, routine, sconf, 'localhost', rbox, option, argv)
41
41
  end
42
42
  def after_local?(routine)
43
43
  routine[:after_local] = { # See before_local note
@@ -46,21 +46,21 @@ module Rudy; module Routines;
46
46
  execute_command?(:after_local, routine)
47
47
  end
48
48
 
49
- def before(routine, sconf, machine, rbox)
49
+ def before(routine, sconf, machine, rbox, option=nil, argv=nil)
50
50
  raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
51
- execute_command(:before, routine, sconf, machine.name, rbox)
51
+ execute_command(:before, routine, sconf, machine.name, rbox, option, argv)
52
52
  end
53
53
  def before?(routine); execute_command?(:before, routine); end
54
54
 
55
- def after(routine, sconf, machine, rbox)
55
+ def after(routine, sconf, machine, rbox, option=nil, argv=nil)
56
56
  raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
57
- execute_command(:after, routine, sconf, machine.name, rbox)
57
+ execute_command(:after, routine, sconf, machine.name, rbox, option, argv)
58
58
  end
59
59
  def after?(routine); execute_command?(:after, routine); end
60
60
 
61
- def script(routine, sconf, machine, rbox)
61
+ def script(routine, sconf, machine, rbox, option=nil, argv=nil)
62
62
  raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
63
- execute_command(:script, routine, sconf, machine.name, rbox)
63
+ execute_command(:script, routine, sconf, machine.name, rbox, option, argv)
64
64
  end
65
65
  def script?(routine); execute_command?(:script, routine); end
66
66
 
@@ -76,7 +76,12 @@ module Rudy; module Routines;
76
76
  return false unless hasconf
77
77
  unless routine[timing].kind_of?(Hash)
78
78
  STDERR.puts "No user supplied for #{timing} block".color(:red)
79
- exit 12 unless keep_going?
79
+ choice = Annoy.get_user_input('(S)kip (A)bort: ')
80
+ if choice.match(/\AS/i)
81
+ return
82
+ else
83
+ exit 12
84
+ end
80
85
  return false
81
86
  end
82
87
  routine[timing].each_pair do |user,proc|
@@ -95,13 +100,13 @@ module Rudy; module Routines;
95
100
  # * +sconf+ is a config hash from machines config (ignored if nil)
96
101
  # * +hostname+ machine hostname that we're working on
97
102
  # * +rbox+ a Rye::Box instance for the machine we're working on
98
- def execute_command(timing, routine, sconf, hostname, rbox)
103
+ def execute_command(timing, routine, sconf, hostname, rbox, option=nil, argv=nil)
99
104
  raise "ScriptHelper: Not a Rye::Box" unless rbox.is_a?(Rye::Box)
100
105
  raise "ScriptHelper: #{timing}?" unless @@script_types.member?(timing)
101
106
 
102
107
  # The config file that gets created on each remote machine
103
108
  # will be created in the user's home directory.
104
- script_config_remote_path = File.join(rbox.getenv['HOME'], @@script_config_file_name)
109
+ script_config_remote_path = File.join(rbox.getenv['HOME'] || '', @@script_config_file_name)
105
110
 
106
111
  if sconf && !sconf.empty?
107
112
  tf = Tempfile.new(@@script_config_file_name)
@@ -148,32 +153,52 @@ module Rudy; module Routines;
148
153
  }
149
154
 
150
155
  begin
151
- # We define hooks so we can call the script block as a batch.
152
- # We intentionally set and unset the hooks so the other commands
153
- # (config file copy) don't get printed.
154
- #
155
- # This block gets called for every command method call.
156
- rbox.pre_command_hook do |cmd, args, user|
157
- puts command_separator(rbox.preview_command(cmd, args), user)
156
+ # We define hooks so we can still print each command and its output
157
+ # when running the command blocks. NOTE: We only print this in
158
+ # verbosity mode. We intentionally set and unset the hooks
159
+ # so the other commands (config file copy) don't get printed.
160
+ if @@global.verbose > 0
161
+ # This block gets called for every command method call.
162
+ rbox.pre_command_hook do |cmd, args, user, host|
163
+ puts command_separator(rbox.preview_command(cmd, args), user, host)
164
+ end
158
165
  end
159
- # And this one gets called after each command method call.
160
- rbox.post_command_hook do |ret|
161
- puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
162
- print_response(ret)
166
+ if @@global.verbose > 1
167
+ # And this one gets called after each command method call.
168
+ rbox.post_command_hook do |ret|
169
+ puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
170
+ print_response(ret)
171
+ end
163
172
  end
164
173
 
165
174
  ### EXECUTE THE COMMANDS BLOCK
166
- rbox.batch(&proc)
175
+ rbox.batch(option, argv, &proc)
167
176
 
168
- rbox.pre_command_hook = nil
169
- rbox.post_command_hook = nil
170
177
  rescue Rye::CommandError => ex
171
178
  print_response(ex)
172
- exit 12 unless keep_going?
179
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
180
+ if choice.match(/\AS/i)
181
+ return
182
+ elsif choice.match(/\AR/i)
183
+ retry
184
+ else
185
+ exit 12
186
+ end
173
187
  rescue Rye::CommandNotFound => ex
174
188
  STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
175
189
  STDERR.puts ex.backtrace if Rudy.debug?
176
- exit 12 unless keep_going?
190
+ choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
191
+ if choice.match(/\AS/i)
192
+ return
193
+ elsif choice.match(/\AR/i)
194
+ retry
195
+ else
196
+ exit 12
197
+ end
198
+ ensure
199
+ rbox.pre_command_hook = nil
200
+ rbox.post_command_hook = nil
201
+ rbox.enable_safe_mode # In case it was disabled
177
202
  end
178
203
 
179
204
  rbox.cd # reset to home dir