rudy 0.8.5 → 0.9.0

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.
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