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