rudy 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/CHANGES.txt +110 -18
  2. data/README.rdoc +40 -44
  3. data/Rudyfile +35 -50
  4. data/bin/rudy +88 -57
  5. data/bin/rudy-ec2 +2 -16
  6. data/bin/rudy-s3 +0 -10
  7. data/bin/rudy-sdb +11 -12
  8. data/lib/rudy.rb +59 -91
  9. data/lib/rudy/aws.rb +4 -45
  10. data/lib/rudy/aws/ec2.rb +57 -20
  11. data/lib/rudy/aws/ec2/address.rb +10 -11
  12. data/lib/rudy/aws/ec2/group.rb +10 -9
  13. data/lib/rudy/aws/ec2/image.rb +8 -8
  14. data/lib/rudy/aws/ec2/instance.rb +18 -19
  15. data/lib/rudy/aws/ec2/keypair.rb +14 -19
  16. data/lib/rudy/aws/ec2/snapshot.rb +16 -9
  17. data/lib/rudy/aws/ec2/volume.rb +39 -26
  18. data/lib/rudy/aws/ec2/zone.rb +5 -4
  19. data/lib/rudy/aws/s3.rb +2 -1
  20. data/lib/rudy/aws/sdb.rb +35 -86
  21. data/lib/rudy/backups.rb +24 -0
  22. data/lib/rudy/cli.rb +5 -131
  23. data/lib/rudy/cli/aws/ec2/addresses.rb +19 -27
  24. data/lib/rudy/cli/aws/ec2/candy.rb +45 -20
  25. data/lib/rudy/cli/aws/ec2/groups.rb +9 -13
  26. data/lib/rudy/cli/aws/ec2/images.rb +5 -133
  27. data/lib/rudy/cli/aws/ec2/instances.rb +25 -25
  28. data/lib/rudy/cli/aws/ec2/keypairs.rb +7 -11
  29. data/lib/rudy/cli/aws/ec2/snapshots.rb +5 -9
  30. data/lib/rudy/cli/aws/ec2/volumes.rb +22 -23
  31. data/lib/rudy/cli/aws/ec2/zones.rb +2 -3
  32. data/lib/rudy/cli/aws/sdb/domains.rb +5 -6
  33. data/lib/rudy/cli/aws/sdb/objects.rb +33 -0
  34. data/lib/rudy/cli/aws/sdb/select.rb +23 -0
  35. data/lib/rudy/cli/backups.rb +38 -0
  36. data/lib/rudy/cli/base.rb +104 -0
  37. data/lib/rudy/cli/candy.rb +1 -2
  38. data/lib/rudy/cli/config.rb +20 -7
  39. data/lib/rudy/cli/disks.rb +7 -9
  40. data/lib/rudy/cli/execbase.rb +56 -0
  41. data/lib/rudy/cli/machines.rb +242 -45
  42. data/lib/rudy/cli/metadata.rb +24 -10
  43. data/lib/rudy/cli/networks.rb +34 -0
  44. data/lib/rudy/cli/routines.rb +32 -6
  45. data/lib/rudy/cli/status.rb +60 -0
  46. data/lib/rudy/config.rb +55 -32
  47. data/lib/rudy/config/objects.rb +44 -30
  48. data/lib/rudy/disks.rb +25 -0
  49. data/lib/rudy/exceptions.rb +99 -0
  50. data/lib/rudy/global.rb +67 -28
  51. data/lib/rudy/guidelines.rb +3 -2
  52. data/lib/rudy/huxtable.rb +67 -58
  53. data/lib/rudy/machines.rb +41 -263
  54. data/lib/rudy/metadata.rb +212 -38
  55. data/lib/rudy/metadata/backup.rb +123 -78
  56. data/lib/rudy/metadata/disk.rb +153 -170
  57. data/lib/rudy/metadata/machine.rb +179 -0
  58. data/lib/rudy/mixins.rb +2 -1
  59. data/lib/rudy/mixins/hash.rb +3 -1
  60. data/lib/rudy/mixins/symbol.rb +8 -0
  61. data/lib/rudy/routines.rb +127 -344
  62. data/lib/rudy/routines/base.rb +229 -0
  63. data/lib/rudy/routines/handlers/base.rb +48 -0
  64. data/lib/rudy/routines/handlers/depends.rb +49 -0
  65. data/lib/rudy/routines/handlers/disks.rb +249 -0
  66. data/lib/rudy/routines/handlers/group.rb +44 -0
  67. data/lib/rudy/routines/handlers/host.rb +70 -0
  68. data/lib/rudy/routines/handlers/keypair.rb +70 -0
  69. data/lib/rudy/routines/handlers/machines.rb +15 -0
  70. data/lib/rudy/routines/handlers/script.rb +85 -0
  71. data/lib/rudy/routines/handlers/user.rb +45 -0
  72. data/lib/rudy/routines/passthrough.rb +19 -23
  73. data/lib/rudy/routines/reboot.rb +98 -50
  74. data/lib/rudy/routines/shutdown.rb +65 -14
  75. data/lib/rudy/routines/startup.rb +112 -17
  76. data/lib/rudy/utils.rb +35 -68
  77. data/rudy.gemspec +82 -25
  78. data/tryouts/01_mixins/01_hash_tryouts.rb +20 -0
  79. data/tryouts/10_require_time/10_rudy_tryouts.rb +33 -0
  80. data/tryouts/10_require_time/15_global_tryouts.rb +58 -0
  81. data/tryouts/12_config/10_load_config_tryouts.rb +43 -0
  82. data/tryouts/12_config/20_defaults_tryouts.rb +16 -0
  83. data/tryouts/12_config/30_accounts_tryouts.rb +17 -0
  84. data/tryouts/12_config/40_machines_tryouts.rb +53 -0
  85. data/tryouts/12_config/50_commands_tryouts.rb +17 -0
  86. data/tryouts/12_config/60_routines_tryouts.rb +16 -0
  87. data/tryouts/15_huxtable/10_huxtable_tryouts.rb +47 -0
  88. data/tryouts/15_huxtable/20_user_tryouts.rb +47 -0
  89. data/tryouts/20_simpledb/10_domains_tryouts.rb +36 -0
  90. data/tryouts/20_simpledb/20_objects_tryouts.rb +56 -0
  91. data/tryouts/25_ec2/10_keypairs_tryouts.rb +54 -0
  92. data/tryouts/25_ec2/20_groups_tryouts.rb +56 -0
  93. data/tryouts/25_ec2/21_groups_authorize_address_tryouts.rb +53 -0
  94. data/tryouts/25_ec2/22_groups_authorize_account_tryouts.rb +54 -0
  95. data/tryouts/25_ec2/30_addresses_tryouts.rb +42 -0
  96. data/tryouts/25_ec2/40_volumes_tryouts.rb +53 -0
  97. data/tryouts/25_ec2/50_snapshots_tryouts.rb +75 -0
  98. data/tryouts/26_ec2_instances/10_instance_tryouts.rb +107 -0
  99. data/tryouts/26_ec2_instances/50_images_tryouts.rb +7 -0
  100. data/tryouts/30_metadata/10_include_tryouts.rb +45 -0
  101. data/tryouts/30_metadata/13_object_tryouts.rb +19 -0
  102. data/tryouts/30_metadata/50_disk_tryouts.rb +115 -0
  103. data/tryouts/30_metadata/51_disk_digest_tryouts.rb +24 -0
  104. data/tryouts/30_metadata/53_disk_list_tryouts.rb +35 -0
  105. data/tryouts/30_metadata/56_disk_volume_tryouts.rb +68 -0
  106. data/tryouts/30_metadata/60_backup_tryouts.rb +101 -0
  107. data/tryouts/30_metadata/63_backup_list_tryouts.rb +38 -0
  108. data/tryouts/30_metadata/64_backup_disk_tryouts.rb +65 -0
  109. data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +76 -0
  110. data/tryouts/30_metadata/70_machine_tryouts.rb +85 -0
  111. data/tryouts/30_metadata/73_machine_list_tryouts.rb +58 -0
  112. data/tryouts/30_metadata/76_machine_instance_tryouts.rb +64 -0
  113. data/tryouts/30_metadata/77_machines_tryouts.rb +45 -0
  114. data/tryouts/40_routines/10_keypair_handler_tryouts.rb +52 -0
  115. data/tryouts/40_routines/11_group_handler_tryouts.rb +36 -0
  116. data/tryouts/80_cli/10_rudyec2_tryouts.rb +8 -0
  117. data/tryouts/80_cli/60_rudy_tryouts.rb +41 -0
  118. data/tryouts/exploration/console.rb +91 -0
  119. data/tryouts/exploration/machine.rb +23 -0
  120. data/tryouts/failer +6 -0
  121. metadata +116 -32
  122. data/bin/ird +0 -153
  123. data/lib/rudy/metadata/backups.rb +0 -67
  124. data/lib/rudy/metadata/debug.rb +0 -38
  125. data/lib/rudy/metadata/disks.rb +0 -67
  126. data/lib/rudy/metadata/objectbase.rb +0 -108
  127. data/lib/rudy/routines/helper.rb +0 -76
  128. data/lib/rudy/routines/helpers/dependshelper.rb +0 -34
  129. data/lib/rudy/routines/helpers/diskhelper.rb +0 -403
  130. data/lib/rudy/routines/helpers/scripthelper.rb +0 -197
  131. data/lib/rudy/routines/helpers/userhelper.rb +0 -37
  132. data/support/rudy-ec2-startup +0 -200
@@ -1,34 +0,0 @@
1
-
2
- module Rudy; module Routines;
3
- module DependsHelper
4
- include Rudy::Routines::HelperBase # TODO: use trap_rbox_errors
5
- extend self
6
-
7
- def has_depends?(timing, routine)
8
- (!routine.is_a?(Caesars::Hash) || routine[timing].is_a?(Caesars::Hash))
9
- end
10
-
11
- # Returns an Array of the dependent routines for the given +timing+ (before/after)
12
- def get(timing, routine)
13
- return if !(routine.is_a?(Caesars::Hash) || routine[timing].is_a?(Caesars::Hash))
14
-
15
- # This will produce an Array containing the routines to run. The
16
- # elements are the valid routine names.
17
- # NOTE: The "timing" elements are removed from the routines hash.
18
- dependencies = []
19
- routine[timing].each_pair do |n,v|
20
- next unless v.nil? # this skips all "script" blocks
21
- raise "#{timing}: #{n} is not a known routine" unless valid_routine?(n)
22
- routine[timing].delete(n)
23
- dependencies << n
24
- end
25
-
26
- # We need to return only the keys b/c the values are nil
27
- dependencies = nil if dependencies.empty?
28
- dependencies
29
- end
30
-
31
-
32
- end
33
-
34
- end; end
@@ -1,403 +0,0 @@
1
-
2
-
3
- module Rudy; module Routines;
4
- module DiskHelper
5
- include Rudy::Routines::HelperBase # TODO: use trap_rbox_errors
6
- extend self
7
-
8
- def disks?(routine)
9
- (routine.is_a?(Caesars::Hash) && routine.disks &&
10
- routine.disks.is_a?(Caesars::Hash) && !routine.disks.empty?) ? true : false
11
- end
12
-
13
- def paths(routine)
14
- return nil unless disks?(routine)
15
- routine.disks.values.collect { |d| d.keys }.flatten
16
- end
17
-
18
- def execute(routine, machine, rbox)
19
- return unless routine
20
- raise "Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
21
- raise "Not a Rye::Box" unless rbox.is_a?(Rye::Box)
22
-
23
- @machine = machine
24
- @rbox = rbox
25
-
26
- # We need to add mkfs since it's not enabled by default.
27
- # We add it only to this instance we're using.
28
- # We give it a funny name so we can delete it.
29
- def @rbox.rudy_mkfs(*args); cmd('mkfs', args); end
30
-
31
- unless disks?(routine)
32
- STDERR.puts "[nothing to do]"
33
- return
34
- end
35
-
36
- modified = []
37
- routine.disks.each_pair do |action, disks|
38
- unless DiskHelper.respond_to?(action)
39
- STDERR.puts %Q(DiskHelper: unknown action "#{action}")
40
- next
41
- end
42
- send(action, disks) # create, copy, destroy, ...
43
- modified << disks
44
- end
45
-
46
- # TODO: remove rudy_mkfs method
47
-
48
- end
49
-
50
- def snapshot(disks)
51
- rdisk = Rudy::Disks.new
52
- rback = Rudy::Backups.new
53
-
54
- disks.each_pair do |path, props|
55
- adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
56
- disk = rdisk.get(adisk.name)
57
- if disk == nil
58
- puts "Not found: #{adisk.name}".color(:red)
59
- return
60
- end
61
- back = disk.backup
62
- puts "Created backup: #{back.name}"
63
- end
64
- end
65
-
66
- def restore(disks)
67
- rdisk = Rudy::Disks.new
68
- rback = Rudy::Backups.new
69
-
70
- disks.each_pair do |path, props|
71
- disk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
72
-
73
- olddisk = rdisk.get(disk.name)
74
- back = nil
75
- if olddisk && olddisk.exists?
76
- olddisk.update
77
- puts "Disk found: #{olddisk.name}. Skipping...".color(:red)
78
- return
79
- else
80
- disk.fstype = props[:fstype] || 'ext3'
81
- more = [:environment, props[:environment]] if props[:environment]
82
- more += [:role, props[:role]] if props[:role]
83
- back = (rback.list(more, nil) || []).first
84
- raise "No backup found" unless back
85
- puts "Found backup #{back.name} "
86
- end
87
-
88
- unless disk.exists? # Checks the EBS volume
89
- msg = "Creating volume from snapshot (#{back.awsid})... "
90
- disk.create(back.size, @@global.zone, back.awsid)
91
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
92
- disk.available?
93
- }
94
- end
95
-
96
- msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
97
- disk.attach(@machine.awsid)
98
- Rudy::Utils.waiter(2, 10, STDOUT, msg) {
99
- disk.attached?
100
- }
101
-
102
- sleep 2
103
-
104
- begin
105
- @rbox.mkdir(:p, disk.path)
106
-
107
- print "Mounting at #{disk.path}... "
108
-
109
- ret = @rbox.mount(:t, disk.fstype, disk.device, disk.path)
110
- print_response ret
111
- if ret.exit_code > 0
112
- STDERR.puts "Error creating disk".color(:red)
113
- return
114
- else
115
- puts "done"
116
- end
117
- disk.mounted = true
118
- disk.save
119
-
120
- rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
121
- STDERR.puts "Error creating disk".color(:red)
122
- STDERR.puts ex.message.color(:red)
123
- rescue Rye::CommandNotFound => ex
124
- puts " CommandNotFound: #{ex.message}".color(:red)
125
-
126
- rescue
127
- STDERR.puts "Error creating disk" .color(:red)
128
- Rudy::Utils.bug
129
- end
130
-
131
- end
132
- end
133
-
134
-
135
- def create(disks)
136
- rdisk = Rudy::Disks.new
137
-
138
- disks.each_pair do |path, props|
139
- disk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
140
- olddisk = rdisk.get(disk.name)
141
- if olddisk && olddisk.exists?
142
- olddisk.update
143
- puts "Disk found: #{olddisk.name}"
144
- if olddisk.attached?
145
- puts "In use. Skipping...".color(:red)
146
- return
147
- else
148
- disk = olddisk
149
- end
150
- else
151
- puts "Creating #{disk.name} "
152
- disk.fstype = props[:fstype] || 'ext3'
153
- end
154
-
155
- unless disk.exists? # Checks the EBS volume
156
- msg = "Creating volume... "
157
- disk.create
158
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
159
- disk.available?
160
- }
161
- end
162
-
163
- msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
164
- disk.attach(@machine.awsid)
165
- Rudy::Utils.waiter(2, 10, STDOUT, msg) {
166
- disk.attached?
167
- }
168
-
169
- # The device needs some time.
170
- # Otherwise mkfs returns:
171
- # "No such file or directory while trying to determine filesystem size"
172
- sleep 2
173
-
174
- # TODO: Cleanup. See ScriptHelper
175
- begin
176
- if disk.raw == true
177
- print "Creating #{disk.fstype} filesystem for #{disk.device}... "
178
- @rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
179
- disk.raw = false
180
- disk.save
181
- puts "done"
182
- end
183
-
184
- @rbox.mkdir(:p, disk.path)
185
-
186
- print "Mounting at #{disk.path}... "
187
-
188
- ret = @rbox.mount(:t, disk.fstype, disk.device, disk.path)
189
- print_response ret
190
- if ret.exit_code > 0
191
- STDERR.puts "Error creating disk".color(:red)
192
- return
193
- else
194
- puts "done"
195
- end
196
- disk.mounted = true
197
- disk.save
198
-
199
- rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
200
- STDERR.puts "Error creating disk".color(:red)
201
- STDERR.puts ex.message.color(:red)
202
- rescue Rye::CommandNotFound => ex
203
- puts " CommandNotFound: #{ex.message}".color(:red)
204
-
205
- rescue
206
- STDERR.puts "Error creating disk" .color(:red)
207
- Rudy::Utils.bug
208
- end
209
-
210
- end
211
- end
212
-
213
-
214
-
215
-
216
- def attach(disks)
217
- rdisk = Rudy::Disks.new
218
-
219
- disks.each_pair do |path, props|
220
- disk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
221
- olddisk = rdisk.get(disk.name)
222
- if olddisk && olddisk.exists?
223
- disk.update
224
- puts "Disk found: #{olddisk.name}"
225
- if disk.attached?
226
- puts "In use. Skipping...".color(:red)
227
- return
228
- else
229
- disk = olddisk
230
- end
231
- else
232
- puts "Creating #{disk.name} "
233
- end
234
- p disk
235
- p [disk.exists?, disk.available?, olddisk.exists?, olddisk.available?]
236
- disk.save
237
-
238
- unless disk.exists? # Checks the EBS volume
239
- msg = "Creating volume... "
240
- disk.create
241
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
242
- disk.available?
243
- }
244
- end
245
-
246
- unless disk.attached?
247
- msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
248
- disk.attach(@machine.awsid)
249
- Rudy::Utils.waiter(2, 10, STDOUT, msg) {
250
- disk.attached?
251
- }
252
- end
253
- end
254
- end
255
-
256
- def detach(disks, destroy=false)
257
- rdisk = Rudy::Disks.new
258
- disks.each_pair do |path, props|
259
- adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
260
- disk = rdisk.get adisk.name
261
-
262
- if disk == nil
263
- puts "Not found: #{adisk.name}".color(:red)
264
- return
265
- end
266
-
267
- if disk.attached?
268
- msg = "Detaching #{disk.awsid}..."
269
- disk.detach
270
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
271
- disk.available?
272
- }
273
- end
274
-
275
- if destroy
276
- puts "Destroying volume and metadata... "
277
- disk.destroy
278
- end
279
-
280
- end
281
- end
282
-
283
- def mount(disks)
284
- rdisk = Rudy::Disks.new
285
- disks.each_pair do |path, props|
286
- adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
287
- disk = rdisk.get(adisk.name)
288
- if disk == nil
289
- puts "Not found: #{adisk.name}".color(:red)
290
- return
291
- end
292
-
293
- unless disk.attached?
294
- msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
295
- disk.attach(@machine.awsid)
296
- Rudy::Utils.waiter(2, 10, STDOUT, msg) {
297
- disk.attached?
298
- }
299
-
300
- sleep 2
301
- end
302
-
303
- begin
304
- @rbox.mkdir(:p, disk.path)
305
-
306
- print "Mounting at #{disk.path}... "
307
-
308
- ret = @rbox.mount(:t, disk.fstype, disk.device, disk.path)
309
- print_response ret
310
- if ret.exit_code > 0
311
- STDERR.puts "Error creating disk".color(:red)
312
- return
313
- else
314
- puts "done"
315
- end
316
- disk.mounted = true
317
- disk.save
318
-
319
- rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
320
- STDERR.puts "Error creating disk".color(:red)
321
- STDERR.puts ex.message.color(:red)
322
- rescue Rye::CommandNotFound => ex
323
- puts " CommandNotFound: #{ex.message}".color(:red)
324
-
325
- rescue
326
- STDERR.puts "Error creating disk" .color(:red)
327
- Rudy::Utils.bug
328
- end
329
-
330
- end
331
- end
332
-
333
-
334
- def umount(disks)
335
- rdisk = Rudy::Disks.new
336
- disks.each_pair do |path, props|
337
- adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
338
- disk = rdisk.get(adisk.name)
339
- if disk == nil
340
- puts "Not found: #{adisk.name}".color(:red)
341
- return
342
- end
343
-
344
- if disk.mounted?
345
- print "Unmounting #{disk.path}..."
346
- trap_rbox_errors { @rbox.umount(disk.path) }
347
- puts " done"
348
- sleep 0.5
349
- end
350
-
351
- sleep 2
352
-
353
- if disk.attached?
354
- msg = "Detaching #{disk.awsid}..."
355
- disk.detach
356
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
357
- disk.available?
358
- }
359
- sleep 0.5
360
- end
361
-
362
-
363
- end
364
- end
365
- alias_method :unmount, :umount
366
-
367
- def destroy(disks)
368
- rdisk = Rudy::Disks.new
369
-
370
- disks.each_pair do |path, props|
371
- adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
372
- disk = rdisk.get(adisk.name)
373
- if disk == nil
374
- puts "Not found: #{adisk.name}".color(:red)
375
- return
376
- end
377
-
378
- puts "Destroying #{disk.name}"
379
-
380
- if disk.mounted?
381
- print "Unmounting #{disk.path}..."
382
- trap_rbox_errors { @rbox.umount(disk.path) }
383
- puts " done"
384
- sleep 0.5
385
- end
386
-
387
- if disk.attached?
388
- msg = "Detaching #{disk.awsid}..."
389
- disk.detach
390
- Rudy::Utils.waiter(2, 60, STDOUT, msg) {
391
- disk.available?
392
- }
393
- sleep 0.5
394
- end
395
-
396
- puts "Destroying volume and metadata... "
397
- disk.destroy
398
-
399
- end
400
- end
401
-
402
- end
403
- end;end
@@ -1,197 +0,0 @@
1
- require 'tempfile'
2
-
3
- module Rudy; module Routines;
4
- #--
5
- # TODO: Rename to ShellHelper
6
- #++
7
- module ScriptHelper
8
- include Rudy::Routines::HelperBase # TODO: use trap_rbox_errors
9
- extend self
10
-
11
- @@script_types = [:after, :before, :after_local, :before_local, :script, :script_local]
12
-
13
-
14
- # TODO: refactor using this_method
15
-
16
- def before_local(routine, sconf, rbox, option=nil, argv=nil)
17
- execute_command(:before_local, routine, sconf, 'localhost', rbox, option, argv)
18
- end
19
- def before_local?(routine)
20
- # before_local generally doesn't take a user name like the remote
21
- # before block so we add it here (unless the user did specify it)
22
- routine[:before_local] = {
23
- Rudy.sysinfo.user.to_sym => routine.delete(:before_local)
24
- } if routine[:before_local].is_a?(Proc)
25
- execute_command?(:before_local, routine)
26
- end
27
- def script_local(routine, sconf, rbox, option=nil, argv=nil)
28
- execute_command(:script_local, routine, sconf, 'localhost', rbox, option, argv)
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
-
39
- def after_local(routine, sconf, rbox, option=nil, argv=nil)
40
- execute_command(:after_local, routine, sconf, 'localhost', rbox, option, argv)
41
- end
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
48
-
49
- def before(routine, sconf, machine, rbox, option=nil, argv=nil)
50
- raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
51
- execute_command(:before, routine, sconf, machine.name, rbox, option, argv)
52
- end
53
- def before?(routine); execute_command?(:before, routine); end
54
-
55
- def after(routine, sconf, machine, rbox, option=nil, argv=nil)
56
- raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
57
- execute_command(:after, routine, sconf, machine.name, rbox, option, argv)
58
- end
59
- def after?(routine); execute_command?(:after, routine); end
60
-
61
- def script(routine, sconf, machine, rbox, option=nil, argv=nil)
62
- raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
63
- execute_command(:script, routine, sconf, machine.name, rbox, option, argv)
64
- end
65
- def script?(routine); execute_command?(:script, routine); end
66
-
67
-
68
- private
69
-
70
- # Does the routine have the requested script type?
71
- # * +timing+ is one of: after, before, after_local, before_local
72
- # * +routine+ a single routine hash (startup, shutdown, etc...)
73
- # Prints notice to STDERR if there's an empty conf hash
74
- def execute_command?(timing, routine)
75
- hasconf = (routine.is_a?(Caesars::Hash) && routine.has_key?(timing))
76
- return false unless hasconf
77
- unless routine[timing].kind_of?(Hash)
78
- STDERR.puts "No user supplied for #{timing} block".color(:red)
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
85
- return false
86
- end
87
- routine[timing].each_pair do |user,proc|
88
- #p [timing, user, proc].join(', ')
89
- if proc.nil? || !proc.is_a?(Proc)
90
- STDERR.puts "Empty #{timing} config for #{user}"
91
- else
92
- return true
93
- end
94
- end
95
- false
96
- end
97
-
98
- # * +timing+ is one of: after, before, after_local, before_local
99
- # * +routine+ a single routine hash (startup, shutdown, etc...)
100
- # * +sconf+ is a config hash from machines config (ignored if nil)
101
- # * +hostname+ machine hostname that we're working on
102
- # * +rbox+ a Rye::Box instance for the machine we're working on
103
- def execute_command(timing, routine, sconf, hostname, rbox, option=nil, argv=nil)
104
- raise "ScriptHelper: Not a Rye::Box" unless rbox.is_a?(Rye::Box)
105
- raise "ScriptHelper: #{timing}?" unless @@script_types.member?(timing)
106
-
107
- # Do we need to run this again? It's called in generic_routine_runner
108
- ##if execute_command?(timing, routine) # i.e. before_local?
109
-
110
- # We need to explicitly add the rm command for rbox so we
111
- # can delete the script config file when we're done. This
112
- # adds the method to this instance of rbox only.
113
- # We give it a funny so we can delete it knowing we're not
114
- # deleting a method added somewhere else.
115
- def rbox.rudy_tmp_rm(*args); cmd('rm', args); end
116
-
117
- original_user = rbox.user
118
- user_blocks = routine[timing] || {}
119
- users = user_blocks.keys
120
- # Root stuff is always run first.
121
- users.unshift(users.delete(:root)) if users.member?(:root)
122
- users.each do |user|
123
- proc = user_blocks[user]
124
-
125
- begin
126
- rbox.switch_user user # does nothing if it's the same user
127
- rbox.connect(false) # does nothing if already connected
128
- rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
129
- STDERR.puts "Error connecting: #{ex.message}".color(:red)
130
- STDERR.puts "Skipping user #{user}".color(:red)
131
- next
132
- end
133
-
134
- begin
135
- # We define hooks so we can still print each command and its output
136
- # when running the command blocks. NOTE: We only print this in
137
- # verbosity mode. We intentionally set and unset the hooks
138
- # so the other commands (config file copy) don't get printed.
139
- if @@global.verbose > 0
140
- # This block gets called for every command method call.
141
- rbox.pre_command_hook do |cmd, args, user, host|
142
- puts command_separator(rbox.preview_command(cmd, args), user, host)
143
- end
144
- end
145
- if @@global.verbose > 1
146
- # And this one gets called after each command method call.
147
- rbox.post_command_hook do |ret|
148
- puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
149
- print_response(ret)
150
- end
151
- end
152
-
153
- ### EXECUTE THE COMMANDS BLOCK
154
- rbox.batch(option, argv, &proc)
155
-
156
- rescue Rye::CommandError => ex
157
- print_response(ex)
158
- choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ') || ''
159
- if choice.match(/\AS/i)
160
- return
161
- elsif choice.match(/\AR/i)
162
- retry
163
- else
164
- exit 12
165
- end
166
- rescue Rye::CommandNotFound => ex
167
- STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
168
- STDERR.puts ex.backtrace if Rudy.debug?
169
- choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ') || ''
170
- if choice.match(/\AS/i)
171
- return
172
- elsif choice.match(/\AR/i)
173
- retry
174
- else
175
- exit 12
176
- end
177
- ensure
178
- rbox.pre_command_hook = nil
179
- rbox.post_command_hook = nil
180
- rbox.enable_safe_mode # In case it was disabled
181
- end
182
-
183
- rbox.cd # reset to home dir
184
- end
185
-
186
- # Return the borrowed rbox instance to the user it was provided with
187
- rbox.switch_user original_user
188
-
189
- ##else
190
- ## puts "Nothing to do"
191
- ##end
192
-
193
-
194
- end
195
- end
196
-
197
- end;end