rudy 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +110 -18
- data/README.rdoc +40 -44
- data/Rudyfile +35 -50
- data/bin/rudy +88 -57
- data/bin/rudy-ec2 +2 -16
- data/bin/rudy-s3 +0 -10
- data/bin/rudy-sdb +11 -12
- data/lib/rudy.rb +59 -91
- data/lib/rudy/aws.rb +4 -45
- data/lib/rudy/aws/ec2.rb +57 -20
- data/lib/rudy/aws/ec2/address.rb +10 -11
- data/lib/rudy/aws/ec2/group.rb +10 -9
- data/lib/rudy/aws/ec2/image.rb +8 -8
- data/lib/rudy/aws/ec2/instance.rb +18 -19
- data/lib/rudy/aws/ec2/keypair.rb +14 -19
- data/lib/rudy/aws/ec2/snapshot.rb +16 -9
- data/lib/rudy/aws/ec2/volume.rb +39 -26
- data/lib/rudy/aws/ec2/zone.rb +5 -4
- data/lib/rudy/aws/s3.rb +2 -1
- data/lib/rudy/aws/sdb.rb +35 -86
- data/lib/rudy/backups.rb +24 -0
- data/lib/rudy/cli.rb +5 -131
- data/lib/rudy/cli/aws/ec2/addresses.rb +19 -27
- data/lib/rudy/cli/aws/ec2/candy.rb +45 -20
- data/lib/rudy/cli/aws/ec2/groups.rb +9 -13
- data/lib/rudy/cli/aws/ec2/images.rb +5 -133
- data/lib/rudy/cli/aws/ec2/instances.rb +25 -25
- data/lib/rudy/cli/aws/ec2/keypairs.rb +7 -11
- data/lib/rudy/cli/aws/ec2/snapshots.rb +5 -9
- data/lib/rudy/cli/aws/ec2/volumes.rb +22 -23
- data/lib/rudy/cli/aws/ec2/zones.rb +2 -3
- data/lib/rudy/cli/aws/sdb/domains.rb +5 -6
- data/lib/rudy/cli/aws/sdb/objects.rb +33 -0
- data/lib/rudy/cli/aws/sdb/select.rb +23 -0
- data/lib/rudy/cli/backups.rb +38 -0
- data/lib/rudy/cli/base.rb +104 -0
- data/lib/rudy/cli/candy.rb +1 -2
- data/lib/rudy/cli/config.rb +20 -7
- data/lib/rudy/cli/disks.rb +7 -9
- data/lib/rudy/cli/execbase.rb +56 -0
- data/lib/rudy/cli/machines.rb +242 -45
- data/lib/rudy/cli/metadata.rb +24 -10
- data/lib/rudy/cli/networks.rb +34 -0
- data/lib/rudy/cli/routines.rb +32 -6
- data/lib/rudy/cli/status.rb +60 -0
- data/lib/rudy/config.rb +55 -32
- data/lib/rudy/config/objects.rb +44 -30
- data/lib/rudy/disks.rb +25 -0
- data/lib/rudy/exceptions.rb +99 -0
- data/lib/rudy/global.rb +67 -28
- data/lib/rudy/guidelines.rb +3 -2
- data/lib/rudy/huxtable.rb +67 -58
- data/lib/rudy/machines.rb +41 -263
- data/lib/rudy/metadata.rb +212 -38
- data/lib/rudy/metadata/backup.rb +123 -78
- data/lib/rudy/metadata/disk.rb +153 -170
- data/lib/rudy/metadata/machine.rb +179 -0
- data/lib/rudy/mixins.rb +2 -1
- data/lib/rudy/mixins/hash.rb +3 -1
- data/lib/rudy/mixins/symbol.rb +8 -0
- data/lib/rudy/routines.rb +127 -344
- data/lib/rudy/routines/base.rb +229 -0
- data/lib/rudy/routines/handlers/base.rb +48 -0
- data/lib/rudy/routines/handlers/depends.rb +49 -0
- data/lib/rudy/routines/handlers/disks.rb +249 -0
- data/lib/rudy/routines/handlers/group.rb +44 -0
- data/lib/rudy/routines/handlers/host.rb +70 -0
- data/lib/rudy/routines/handlers/keypair.rb +70 -0
- data/lib/rudy/routines/handlers/machines.rb +15 -0
- data/lib/rudy/routines/handlers/script.rb +85 -0
- data/lib/rudy/routines/handlers/user.rb +45 -0
- data/lib/rudy/routines/passthrough.rb +19 -23
- data/lib/rudy/routines/reboot.rb +98 -50
- data/lib/rudy/routines/shutdown.rb +65 -14
- data/lib/rudy/routines/startup.rb +112 -17
- data/lib/rudy/utils.rb +35 -68
- data/rudy.gemspec +82 -25
- data/tryouts/01_mixins/01_hash_tryouts.rb +20 -0
- data/tryouts/10_require_time/10_rudy_tryouts.rb +33 -0
- data/tryouts/10_require_time/15_global_tryouts.rb +58 -0
- data/tryouts/12_config/10_load_config_tryouts.rb +43 -0
- data/tryouts/12_config/20_defaults_tryouts.rb +16 -0
- data/tryouts/12_config/30_accounts_tryouts.rb +17 -0
- data/tryouts/12_config/40_machines_tryouts.rb +53 -0
- data/tryouts/12_config/50_commands_tryouts.rb +17 -0
- data/tryouts/12_config/60_routines_tryouts.rb +16 -0
- data/tryouts/15_huxtable/10_huxtable_tryouts.rb +47 -0
- data/tryouts/15_huxtable/20_user_tryouts.rb +47 -0
- data/tryouts/20_simpledb/10_domains_tryouts.rb +36 -0
- data/tryouts/20_simpledb/20_objects_tryouts.rb +56 -0
- data/tryouts/25_ec2/10_keypairs_tryouts.rb +54 -0
- data/tryouts/25_ec2/20_groups_tryouts.rb +56 -0
- data/tryouts/25_ec2/21_groups_authorize_address_tryouts.rb +53 -0
- data/tryouts/25_ec2/22_groups_authorize_account_tryouts.rb +54 -0
- data/tryouts/25_ec2/30_addresses_tryouts.rb +42 -0
- data/tryouts/25_ec2/40_volumes_tryouts.rb +53 -0
- data/tryouts/25_ec2/50_snapshots_tryouts.rb +75 -0
- data/tryouts/26_ec2_instances/10_instance_tryouts.rb +107 -0
- data/tryouts/26_ec2_instances/50_images_tryouts.rb +7 -0
- data/tryouts/30_metadata/10_include_tryouts.rb +45 -0
- data/tryouts/30_metadata/13_object_tryouts.rb +19 -0
- data/tryouts/30_metadata/50_disk_tryouts.rb +115 -0
- data/tryouts/30_metadata/51_disk_digest_tryouts.rb +24 -0
- data/tryouts/30_metadata/53_disk_list_tryouts.rb +35 -0
- data/tryouts/30_metadata/56_disk_volume_tryouts.rb +68 -0
- data/tryouts/30_metadata/60_backup_tryouts.rb +101 -0
- data/tryouts/30_metadata/63_backup_list_tryouts.rb +38 -0
- data/tryouts/30_metadata/64_backup_disk_tryouts.rb +65 -0
- data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +76 -0
- data/tryouts/30_metadata/70_machine_tryouts.rb +85 -0
- data/tryouts/30_metadata/73_machine_list_tryouts.rb +58 -0
- data/tryouts/30_metadata/76_machine_instance_tryouts.rb +64 -0
- data/tryouts/30_metadata/77_machines_tryouts.rb +45 -0
- data/tryouts/40_routines/10_keypair_handler_tryouts.rb +52 -0
- data/tryouts/40_routines/11_group_handler_tryouts.rb +36 -0
- data/tryouts/80_cli/10_rudyec2_tryouts.rb +8 -0
- data/tryouts/80_cli/60_rudy_tryouts.rb +41 -0
- data/tryouts/exploration/console.rb +91 -0
- data/tryouts/exploration/machine.rb +23 -0
- data/tryouts/failer +6 -0
- metadata +116 -32
- data/bin/ird +0 -153
- data/lib/rudy/metadata/backups.rb +0 -67
- data/lib/rudy/metadata/debug.rb +0 -38
- data/lib/rudy/metadata/disks.rb +0 -67
- data/lib/rudy/metadata/objectbase.rb +0 -108
- data/lib/rudy/routines/helper.rb +0 -76
- data/lib/rudy/routines/helpers/dependshelper.rb +0 -34
- data/lib/rudy/routines/helpers/diskhelper.rb +0 -403
- data/lib/rudy/routines/helpers/scripthelper.rb +0 -197
- data/lib/rudy/routines/helpers/userhelper.rb +0 -37
- data/support/rudy-ec2-startup +0 -200
@@ -0,0 +1,179 @@
|
|
1
|
+
##--
|
2
|
+
## CONSIDER: http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide-20090713.pdf
|
3
|
+
##++
|
4
|
+
|
5
|
+
module Rudy
|
6
|
+
class Machine < Storable
|
7
|
+
include Rudy::Metadata
|
8
|
+
include Gibbler::Complex
|
9
|
+
|
10
|
+
field :rtype
|
11
|
+
field :instid
|
12
|
+
|
13
|
+
field :region
|
14
|
+
field :zone
|
15
|
+
field :environment
|
16
|
+
field :role
|
17
|
+
field :position
|
18
|
+
|
19
|
+
field :size
|
20
|
+
field :ami
|
21
|
+
field :group
|
22
|
+
field :keypair
|
23
|
+
field :address
|
24
|
+
|
25
|
+
field :created => Time
|
26
|
+
field :started => Time
|
27
|
+
|
28
|
+
field :dns_public
|
29
|
+
field :dns_private
|
30
|
+
field :state
|
31
|
+
|
32
|
+
field :os
|
33
|
+
field :impl
|
34
|
+
|
35
|
+
attr_reader :instance
|
36
|
+
|
37
|
+
# An ephemeral value which is set after checking whether
|
38
|
+
# the SSH daemon is running. By default this will be set
|
39
|
+
# to false but can be set to true to avoid checking again.
|
40
|
+
# See available?
|
41
|
+
attr_writer :available
|
42
|
+
|
43
|
+
# * +position+
|
44
|
+
# * +opts+ is a hash of machine options.
|
45
|
+
#
|
46
|
+
# Valid options are:
|
47
|
+
# * +:position+ (overridden by +position+ arg)
|
48
|
+
# * +:size+
|
49
|
+
# * +:os+
|
50
|
+
# * +:ami+
|
51
|
+
# * +:group+
|
52
|
+
# * +:keypair+
|
53
|
+
# * +:address+
|
54
|
+
#
|
55
|
+
def initialize(position='01', opts={})
|
56
|
+
|
57
|
+
opts = {
|
58
|
+
:size => current_machine_size,
|
59
|
+
:os => current_machine_os,
|
60
|
+
:ami => current_machine_image,
|
61
|
+
:group => current_group_name,
|
62
|
+
:keypair => root_keypairname
|
63
|
+
}.merge opts
|
64
|
+
|
65
|
+
opts[:address] = current_machine_address opts[:position] || position
|
66
|
+
|
67
|
+
super Rudy::Machines::RTYPE, opts # Rudy::Metadata#initialize
|
68
|
+
|
69
|
+
@position = position
|
70
|
+
|
71
|
+
# Defaults:
|
72
|
+
@created = Time.now.utc
|
73
|
+
@available = false
|
74
|
+
postprocess
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
def postprocess
|
79
|
+
@position &&= @position.to_s.rjust(2, '0')
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_s(*args)
|
83
|
+
self.name
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_instance
|
87
|
+
Rudy::AWS::EC2::Instances.get @instid
|
88
|
+
end
|
89
|
+
|
90
|
+
def create
|
91
|
+
raise "#{name} is already running" if instance_running?
|
92
|
+
|
93
|
+
# Options for Rudy::AWS::EC2::Instances#create
|
94
|
+
opts = {
|
95
|
+
:min => 1,
|
96
|
+
:size => @size,
|
97
|
+
:ami => @ami,
|
98
|
+
:group => @group,
|
99
|
+
:keypair => @keypair,
|
100
|
+
:zone => @zone,
|
101
|
+
:machine_data => self.generate_machine_data.to_yaml
|
102
|
+
}
|
103
|
+
|
104
|
+
Rudy::Huxtable.ld "OPTS: #{opts.inspect}"
|
105
|
+
|
106
|
+
Rudy::AWS::EC2::Instances.create(opts) do |inst|
|
107
|
+
@instid = inst.awsid
|
108
|
+
@created = @started = Time.now
|
109
|
+
@state = inst.state
|
110
|
+
# We need to be safe when creating machines because if an exception is
|
111
|
+
# raised, instances will have been created but the calling class won't know.
|
112
|
+
begin
|
113
|
+
# Assign IP address only if we have one for that position
|
114
|
+
if @address
|
115
|
+
# Make sure the address is associated to the current account
|
116
|
+
if Rudy::AWS::EC2::Addresses.exists?(@address)
|
117
|
+
puts "Associating #{@address} to #{@instid}"
|
118
|
+
Rudy::AWS::EC2::Addresses.associate(@address, @instid)
|
119
|
+
else
|
120
|
+
STDERR.puts "Unknown address: #{@address}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
rescue => ex
|
124
|
+
STDERR.puts "Error: #{ex.message}"
|
125
|
+
STDERR.puts ex.backtrace if Rudy.debug?
|
126
|
+
end
|
127
|
+
end
|
128
|
+
self.save
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
def destroy
|
133
|
+
Rudy::AWS::EC2::Instances.destroy(@instid) if instance_running?
|
134
|
+
super
|
135
|
+
end
|
136
|
+
|
137
|
+
def restart
|
138
|
+
Rudy::AWS::EC2::Instances.restart(@instid) if instance_running?
|
139
|
+
end
|
140
|
+
|
141
|
+
def refresh!(metadata=true)
|
142
|
+
## Updating the metadata isn't necessary
|
143
|
+
##super if metadata # update metadata
|
144
|
+
@instance = get_instance
|
145
|
+
if @instance.is_a?(Rudy::AWS::EC2::Instance)
|
146
|
+
@dns_public, @dns_private = @instance.dns_public, @instance.dns_private
|
147
|
+
@state = @instance.state
|
148
|
+
save :replace
|
149
|
+
elsif @instance.nil?
|
150
|
+
@awsid = @dns_public = @dns_private = nil
|
151
|
+
@state = 'rogue'
|
152
|
+
# Don't save it b/c it's possible the EC2 server is just down.
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def generate_machine_data
|
157
|
+
d = {}
|
158
|
+
[:region, :zone, :environment, :role, :position].each do |k|
|
159
|
+
d[k] = self.send k
|
160
|
+
end
|
161
|
+
d
|
162
|
+
end
|
163
|
+
|
164
|
+
def dns_public?; !@dns_public.nil? && !@dns_public.empty?; end
|
165
|
+
def dns_private?; !@dns_private.nil? && !@dns_private.empty?; end
|
166
|
+
|
167
|
+
# See +available+ attribute
|
168
|
+
def available?; @available; end
|
169
|
+
|
170
|
+
# Create instance_*? methods
|
171
|
+
%w[exists? running? pending? terminated? shutting_down? unavailable?].each do |state|
|
172
|
+
define_method("instance_#{state}") do
|
173
|
+
return false if @instid.nil? || @instid.empty?
|
174
|
+
Rudy::AWS::EC2::Instances.send(state, @instid) rescue false # exists?, running?, etc...
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
data/lib/rudy/mixins.rb
CHANGED
data/lib/rudy/mixins/hash.rb
CHANGED
data/lib/rudy/routines.rb
CHANGED
@@ -1,363 +1,146 @@
|
|
1
1
|
|
2
|
-
|
3
2
|
module Rudy
|
3
|
+
|
4
|
+
# = Rudy::Routines
|
5
|
+
#
|
6
|
+
# Every Rudy routine is associated to a handler. There are four standard
|
7
|
+
# handler types: Startup, Shutdown, Reboot, and Passthrough. The first
|
8
|
+
# three are associated to routines of the same same. All other routines
|
9
|
+
# are handled by Rudy::Routines::Passthrough.
|
10
|
+
#
|
11
|
+
# An individual routine is made up of various actions. Each action is
|
12
|
+
# associated to one of the following handlers: depends, disk, script,
|
13
|
+
# user. See each handler for the list of actions it is responsible for.
|
4
14
|
module Routines
|
15
|
+
|
16
|
+
require 'rudy/routines/base'
|
17
|
+
require 'rudy/routines/handlers/base'
|
18
|
+
|
19
|
+
# A Hash of routine names pointing to a specific handler.
|
20
|
+
# See Rudy::Routines.add_routine
|
21
|
+
@@routine = {}
|
22
|
+
|
23
|
+
# A Hash of routine keywords pointing to a specifc handler.
|
24
|
+
# See Rudy::Routines.add_routine
|
25
|
+
@@handler = {}
|
26
|
+
|
5
27
|
class NoRoutine < Rudy::Error
|
6
|
-
def message; "
|
28
|
+
def message; "Unknown routine '#{@obj}'"; end
|
7
29
|
end
|
8
30
|
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def init; raise "Must override init"; end
|
29
|
-
|
30
|
-
def execute
|
31
|
-
raise "Override execute method"
|
32
|
-
end
|
33
|
-
|
34
|
-
def raise_early_exceptions
|
35
|
-
raise "Must override raise_early_exceptions"
|
31
|
+
class NoHandler < Rudy::Error
|
32
|
+
def message; "Unknown routine action '#{@obj}'"; end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EmptyDepends < Rudy::Error
|
36
|
+
def message; "Empty depends block in routine."; end
|
37
|
+
end
|
38
|
+
|
39
|
+
class GroupNotRunning < Rudy::Error
|
40
|
+
def message; "Some machines are not running:#{$/}#{@obj.inspect}"; end
|
41
|
+
end
|
42
|
+
|
43
|
+
class GroupNotAvailable < Rudy::Error
|
44
|
+
def message; "Some machines are not available:#{$/}#{@obj.inspect}"; end
|
45
|
+
end
|
46
|
+
|
47
|
+
class UnsupportedActions < Rudy::Error
|
48
|
+
def initialize(klass, actions)
|
49
|
+
@klass, @actions = klass, [actions].flatten
|
36
50
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
execute_dependency(before_dependencies, skip_check, skip_header)
|
80
|
-
}
|
81
|
-
|
82
|
-
|
83
|
-
lbox = Rye::Box.new('localhost', :info => (@@global.verbose > 3), :debug => false)
|
84
|
-
sconf = fetch_script_config
|
85
|
-
|
86
|
-
enjoy_every_sandwich {
|
87
|
-
if Rudy::Routines::ScriptHelper.before_local?(routine) # before_local
|
88
|
-
# Runs "before_local" scripts of routines config.
|
89
|
-
task_separator("LOCAL SHELL")
|
90
|
-
lbox.cd Dir.pwd # Run local command block from current working directory
|
91
|
-
Rudy::Routines::ScriptHelper.before_local(routine, sconf, lbox, @option, @argv)
|
92
|
-
end
|
93
|
-
}
|
94
|
-
|
95
|
-
enjoy_every_sandwich {
|
96
|
-
if Rudy::Routines::ScriptHelper.script_local?(routine) # script_local
|
97
|
-
# Runs "script_local" scripts of routines config.
|
98
|
-
# NOTE: This is synonymous with before_local
|
99
|
-
task_separator("LOCAL SHELL")
|
100
|
-
lbox.cd Dir.pwd # Run local command block from current working directory
|
101
|
-
Rudy::Routines::ScriptHelper.script_local(routine, sconf, lbox, @option, @argv)
|
102
|
-
end
|
103
|
-
}
|
104
|
-
|
105
|
-
# Execute the action (create, list, destroy, restart)
|
106
|
-
machines = enjoy_every_sandwich([]) { rmach.send(machine_action) } || []
|
107
|
-
|
108
|
-
machines.each do |machine|
|
109
|
-
puts machine_separator(machine.name, machine.awsid) unless skip_header
|
110
|
-
|
111
|
-
unless skip_check
|
112
|
-
msg = preliminary_separator("Checking if instance is running...")
|
113
|
-
Rudy::Utils.waiter(3, 120, STDOUT, msg, 0) {
|
114
|
-
inst = machine.get_instance
|
115
|
-
inst && inst.running?
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
# Add instance info to machine and save it. This is really important
|
120
|
-
# for the initial startup so the metadata is updated right away. But
|
121
|
-
# it's also important to call here because if a routine was executed
|
122
|
-
# and an unexpected exception occurs before this update is executed
|
123
|
-
# the machine metadata won't contain the DNS information. Calling it
|
124
|
-
# here ensure that the metadata is always up-to-date.
|
125
|
-
machine.update
|
126
|
-
|
127
|
-
# This is a short-circuit for Windows instances. We don't support
|
128
|
-
# disks for windows yet and there's no SSH so routines are out of
|
129
|
-
# the picture too. Here we simply run the per machine block which
|
130
|
-
# is crucial for shutdown and possibly others as well.
|
131
|
-
if (machine.os || '').to_s == 'win32'
|
132
|
-
enjoy_every_sandwich {
|
133
|
-
# Startup, shutdown, release, deploy, etc...
|
134
|
-
routine_action.call(machine, nil) if routine_action
|
135
|
-
}
|
136
|
-
|
137
|
-
next # The short circuit
|
138
|
-
end
|
139
|
-
|
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, 30, STDOUT, msg, 0) {
|
144
|
-
Rudy::Utils.service_available?(machine.dns_public, 22)
|
145
|
-
}
|
146
|
-
is_available = ret
|
147
|
-
}
|
148
|
-
end
|
149
|
-
|
150
|
-
if is_available
|
151
|
-
# TODO: trap rbox errors. We could get an authentication error.
|
152
|
-
opts = { :keys => root_keypairpath, :user => remote_user,
|
153
|
-
:info => @@global.verbose > 3, :debug => false }
|
154
|
-
begin
|
155
|
-
rbox = Rye::Box.new(machine.dns_public, opts)
|
156
|
-
Rudy::Utils.waiter(2, 10, STDOUT, nil, 0) { rbox.connect }
|
157
|
-
rescue Rye::NoHost => ex
|
158
|
-
STDERR.puts "No host: #{ex.message}"
|
159
|
-
exit 65
|
160
|
-
end
|
161
|
-
|
162
|
-
unless skip_check
|
163
|
-
# Set the hostname if specified in the machines config.
|
164
|
-
# :rudy -> change to Rudy's machine name
|
165
|
-
# :default -> leave the hostname as it is
|
166
|
-
# Anything else other than nil -> change to that value
|
167
|
-
# NOTE: This will set hostname every time a routine is
|
168
|
-
# run so we may want to make this an explicit action.
|
169
|
-
enjoy_every_sandwich {
|
170
|
-
hn = current_machine_hostname || :rudy
|
171
|
-
if hn != :default
|
172
|
-
hn = machine.name if hn == :rudy
|
173
|
-
print preliminary_separator("Setting hostname to #{hn}... ")
|
174
|
-
rbox.hostname(hn)
|
175
|
-
puts "done"
|
176
|
-
end
|
177
|
-
}
|
178
|
-
end
|
179
|
-
|
180
|
-
|
181
|
-
## NOTE: This prevents shutdown from doing its thing and prob
|
182
|
-
## isn't necessary.
|
183
|
-
##unless has_remote_task?(routine)
|
184
|
-
## puts "[no remote tasks]"
|
185
|
-
## next
|
186
|
-
##end
|
187
|
-
|
188
|
-
enjoy_every_sandwich {
|
189
|
-
if Rudy::Routines::UserHelper.adduser?(routine) # adduser
|
190
|
-
task_separator("ADD USER")
|
191
|
-
Rudy::Routines::UserHelper.adduser(routine, machine, rbox)
|
192
|
-
end
|
193
|
-
}
|
194
|
-
|
195
|
-
enjoy_every_sandwich {
|
196
|
-
if Rudy::Routines::UserHelper.authorize?(routine) # authorize
|
197
|
-
task_separator("AUTHORIZE USER")
|
198
|
-
Rudy::Routines::UserHelper.authorize(routine, machine, rbox)
|
199
|
-
end
|
200
|
-
}
|
201
|
-
|
202
|
-
enjoy_every_sandwich {
|
203
|
-
if Rudy::Routines::ScriptHelper.before?(routine) # before
|
204
|
-
task_separator("REMOTE SHELL")
|
205
|
-
Rudy::Routines::ScriptHelper.before(routine, sconf, machine, rbox, @option, @argv)
|
206
|
-
end
|
207
|
-
}
|
208
|
-
|
209
|
-
enjoy_every_sandwich {
|
210
|
-
if Rudy::Routines::DiskHelper.disks?(routine) # disk
|
211
|
-
task_separator("DISKS")
|
212
|
-
##if rbox.ostype == "sunos"
|
213
|
-
## puts "Sorry, Solaris disks are not supported yet!"
|
214
|
-
##else
|
215
|
-
Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
|
216
|
-
##end
|
217
|
-
end
|
218
|
-
}
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
enjoy_every_sandwich {
|
223
|
-
# Startup, shutdown, release, deploy, etc...
|
224
|
-
routine_action.call(machine, rbox) if routine_action
|
225
|
-
}
|
226
|
-
|
227
|
-
|
228
|
-
if is_available
|
229
|
-
# The "after" blocks are synonymous with "script" blocks.
|
230
|
-
# For some routines, like startup, it makes sense to an
|
231
|
-
# "after" block b/c "script" is ambiguous. In generic
|
232
|
-
# routines, there is no concept of before or after. The
|
233
|
-
# definition is the entire routine so we use "script".
|
234
|
-
# NOTE: If both after and script are supplied they will
|
235
|
-
# both be executed.
|
236
|
-
enjoy_every_sandwich {
|
237
|
-
if Rudy::Routines::ScriptHelper.script?(routine) # script
|
238
|
-
task_separator("REMOTE SHELL")
|
239
|
-
# Runs "after" scripts of routines config
|
240
|
-
Rudy::Routines::ScriptHelper.script(routine, sconf, machine, rbox, @option, @argv)
|
241
|
-
end
|
242
|
-
}
|
243
|
-
|
244
|
-
enjoy_every_sandwich {
|
245
|
-
if Rudy::Routines::ScriptHelper.after?(routine) # after
|
246
|
-
task_separator("REMOTE SHELL")
|
247
|
-
# Runs "after" scripts of routines config
|
248
|
-
Rudy::Routines::ScriptHelper.after(routine, sconf, machine, rbox, @option, @argv)
|
249
|
-
end
|
250
|
-
}
|
251
|
-
|
252
|
-
rbox.disconnect
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
enjoy_every_sandwich {
|
257
|
-
if Rudy::Routines::ScriptHelper.after_local?(routine) # after_local
|
258
|
-
task_separator("LOCAL SHELL")
|
259
|
-
lbox.cd Dir.pwd # Run local command block from current working directory
|
260
|
-
# Runs "after_local" scripts of routines config
|
261
|
-
Rudy::Routines::ScriptHelper.after_local(routine, sconf, lbox, @option, @argv)
|
262
|
-
end
|
263
|
-
}
|
264
|
-
|
265
|
-
# This calls generic_machine_runner for every dependent after routine
|
266
|
-
enjoy_every_sandwich {
|
267
|
-
execute_dependency(after_dependencies, skip_check, skip_header)
|
51
|
+
def message; "#{@klass} does not support: #{@actions.join(', ')}"; end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add a routine handler to @@routine.
|
55
|
+
#
|
56
|
+
# * +routine_name+ Literally the name of the routine that will
|
57
|
+
# have a special handler, like startup, shutdown, and reboot.
|
58
|
+
# * +handler+ The class that will handle this routine. It must
|
59
|
+
# inherit Rudy::Routine::Base
|
60
|
+
#
|
61
|
+
# Returns the value of +handler+.
|
62
|
+
def self.add_routine(name, klass)
|
63
|
+
add_some_class @@routine, Rudy::Routines::Base, name, klass
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the value in the @@routine associated to the key +routine_name+
|
67
|
+
# if it exists, otherwise it returns Rudy::Routines::Passthrough
|
68
|
+
def self.get_routine(name)
|
69
|
+
get_some_class(@@routine, name) || Rudy::Routines::Passthrough
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add a routine handler to @@handler.
|
73
|
+
def self.add_handler(name, klass)
|
74
|
+
add_some_class @@handler, Rudy::Routines::Handlers::Base, name, klass
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the value in the @@handler associated to the key +name+
|
78
|
+
# if it exists, otherwise it returns nil
|
79
|
+
def self.get_handler(name)
|
80
|
+
get_some_class(@@handler, name) || nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.has_routine?(name); @@routine.has_key?(name); end
|
84
|
+
def self.has_handler?(name); @@handler.has_key?(name); end
|
85
|
+
|
86
|
+
# Executes a routine block
|
87
|
+
def self.runner(routine, rset, lbox, argv=nil)
|
88
|
+
routine.each_pair do |name,definition|
|
89
|
+
handler = Rudy::Routines.get_handler name
|
90
|
+
Rudy::Huxtable.ld " executing handler: #{name}"
|
91
|
+
self.rescue {
|
92
|
+
handler.execute(name, definition, rset, lbox, argv)
|
268
93
|
}
|
269
|
-
|
270
|
-
machines
|
271
94
|
end
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
#
|
284
|
-
|
285
|
-
|
286
|
-
# (startup, shutdown, reboot)
|
287
|
-
generic_machine_runner(:list, routine_dependency, skip_check, skip_header)
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.rescue(ret=nil, &bloc_party)
|
98
|
+
begin
|
99
|
+
ret = bloc_party.call
|
100
|
+
rescue NameError, ArgumentError, RuntimeError => ex
|
101
|
+
STDERR.puts " #{ex.class}: #{ex.message}".color(:red)
|
102
|
+
STDERR.puts ex.backtrace if Rudy.debug?
|
103
|
+
unless Rudy::Huxtable.global.parallel
|
104
|
+
choice = Annoy.get_user_input('(S)kip (A)bort: ', nil, 3600) || ''
|
105
|
+
if choice.match(/\AS/i)
|
106
|
+
# do nothing
|
107
|
+
else
|
108
|
+
exit 12
|
288
109
|
end
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
# Does the given +routine+ define any remote tasks?
|
294
|
-
def has_remote_task?(routine)
|
295
|
-
any = [Rudy::Routines::DiskHelper.disks?(routine),
|
296
|
-
Rudy::Routines::ScriptHelper.before?(routine),
|
297
|
-
Rudy::Routines::ScriptHelper.after?(routine),
|
298
|
-
Rudy::Routines::ScriptHelper.script?(routine),
|
299
|
-
Rudy::Routines::UserHelper.authorize?(routine),
|
300
|
-
Rudy::Routines::UserHelper.adduser?(routine),
|
301
|
-
!@after_dependencies.nil?,
|
302
|
-
!@before_dependencies.nil?]
|
303
|
-
# Throw away all false answers (and nil answers)
|
304
|
-
any = any.compact.select { |success| success }
|
305
|
-
!any.empty? # Returns true if any element contains true
|
306
|
-
end
|
307
|
-
|
308
|
-
def preliminary_separator(msg)
|
309
|
-
# TODO: Count number messages printed 1/3. ie:
|
310
|
-
# m-us-east-1b-stage-app-01
|
311
|
-
# (1/3) Checking if instance is running... done
|
312
|
-
# (2/3) Waiting for SSH daemon... done
|
313
|
-
# (3/3) Setting hostame to m-us-east-1b-stage-app-01... done
|
314
|
-
(" -> #{msg}")
|
110
|
+
end
|
111
|
+
rescue Interrupt
|
112
|
+
puts "Aborting..."
|
113
|
+
exit 12
|
315
114
|
end
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
name = name.to_s
|
330
|
-
dashes = 59 - name.size #
|
331
|
-
dashes = 0 if dashes < 1
|
332
|
-
#puts '%-40s' % [name.bright]
|
115
|
+
ret
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.machine_separator(name, awsid)
|
119
|
+
('%s %-50s awsid: %s ' % [$/, name, awsid]).att(:reverse)
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# See Rudy::Routines.add_routine
|
125
|
+
def self.add_some_class(store, super_klass, name, klass)
|
126
|
+
if store.has_key? name
|
127
|
+
Rudy::Huxtable.li "Redefining class for #{name}"
|
333
128
|
end
|
334
|
-
|
335
|
-
|
336
|
-
begin
|
337
|
-
ret = bloc_party.call
|
338
|
-
rescue => ex
|
339
|
-
STDERR.puts " Error: #{ex.message}".color(:red)
|
340
|
-
STDERR.puts ex.backtrace if Rudy.debug?
|
341
|
-
choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ') || ''
|
342
|
-
if choice.match(/\AS/i)
|
343
|
-
return
|
344
|
-
elsif choice.match(/\AR/i)
|
345
|
-
retry
|
346
|
-
else
|
347
|
-
exit 12
|
348
|
-
end
|
349
|
-
rescue Interrupt
|
350
|
-
puts "Aborting..."
|
351
|
-
exit 12
|
352
|
-
end
|
353
|
-
ret
|
129
|
+
unless klass.ancestors.member? super_klass
|
130
|
+
raise "#{klass} does not inherit #{super_klass}"
|
354
131
|
end
|
355
|
-
|
132
|
+
store[name] = klass
|
356
133
|
end
|
134
|
+
|
135
|
+
# See Rudy::Routines.get_routine
|
136
|
+
def self.get_some_class(store, routine_name)
|
137
|
+
routine_name &&= routine_name.to_sym
|
138
|
+
store[routine_name]
|
139
|
+
end
|
140
|
+
|
357
141
|
end
|
358
142
|
end
|
359
143
|
|
360
144
|
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'routines', '*.rb')
|
361
|
-
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'routines', '
|
362
|
-
|
145
|
+
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'routines', 'handlers', '*.rb')
|
363
146
|
|