solutious-rudy 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +8 -9
- data/README.rdoc +48 -7
- data/Rakefile +102 -7
- data/Rudyfile +28 -0
- data/bin/ird +162 -0
- data/bin/rudy +287 -93
- data/lib/annoy.rb +227 -0
- data/lib/aws_sdb/service.rb +1 -1
- data/lib/console.rb +20 -4
- data/lib/escape.rb +305 -0
- data/lib/rudy.rb +265 -125
- data/lib/rudy/aws.rb +61 -26
- data/lib/rudy/aws/ec2.rb +20 -296
- data/lib/rudy/aws/ec2/address.rb +121 -0
- data/lib/rudy/aws/ec2/group.rb +241 -0
- data/lib/rudy/aws/ec2/image.rb +46 -0
- data/lib/rudy/aws/ec2/instance.rb +407 -0
- data/lib/rudy/aws/ec2/keypair.rb +92 -0
- data/lib/rudy/aws/ec2/snapshot.rb +87 -0
- data/lib/rudy/aws/ec2/volume.rb +234 -0
- data/lib/rudy/aws/simpledb.rb +33 -15
- data/lib/rudy/cli.rb +142 -0
- data/lib/rudy/cli/addresses.rb +85 -0
- data/lib/rudy/cli/backups.rb +175 -0
- data/lib/rudy/{command → cli}/config.rb +18 -13
- data/lib/rudy/cli/deploy.rb +12 -0
- data/lib/rudy/cli/disks.rb +125 -0
- data/lib/rudy/cli/domains.rb +17 -0
- data/lib/rudy/cli/groups.rb +77 -0
- data/lib/rudy/{command → cli}/images.rb +18 -6
- data/lib/rudy/cli/instances.rb +142 -0
- data/lib/rudy/cli/keypairs.rb +47 -0
- data/lib/rudy/cli/manager.rb +51 -0
- data/lib/rudy/{command → cli}/release.rb +10 -10
- data/lib/rudy/cli/routines.rb +80 -0
- data/lib/rudy/cli/volumes.rb +121 -0
- data/lib/rudy/command/addresses.rb +62 -39
- data/lib/rudy/command/backups.rb +60 -170
- data/lib/rudy/command/disks-old.rb +322 -0
- data/lib/rudy/command/disks.rb +5 -209
- data/lib/rudy/command/domains.rb +34 -0
- data/lib/rudy/command/groups.rb +105 -48
- data/lib/rudy/command/instances.rb +263 -70
- data/lib/rudy/command/keypairs.rb +149 -0
- data/lib/rudy/command/manager.rb +65 -0
- data/lib/rudy/command/volumes.rb +110 -49
- data/lib/rudy/config.rb +90 -70
- data/lib/rudy/config/objects.rb +67 -0
- data/lib/rudy/huxtable.rb +253 -0
- data/lib/rudy/metadata/backup.rb +23 -48
- data/lib/rudy/metadata/disk.rb +79 -68
- data/lib/rudy/metadata/machine.rb +34 -0
- data/lib/rudy/routines.rb +54 -0
- data/lib/rudy/routines/disk_handler.rb +190 -0
- data/lib/rudy/routines/release.rb +15 -0
- data/lib/rudy/routines/script_runner.rb +65 -0
- data/lib/rudy/routines/shutdown.rb +42 -0
- data/lib/rudy/routines/startup.rb +48 -0
- data/lib/rudy/utils.rb +57 -2
- data/lib/storable.rb +11 -5
- data/lib/sysinfo.rb +274 -0
- data/rudy.gemspec +84 -20
- data/support/randomize-root-password +45 -0
- data/support/rudy-ec2-startup +5 -5
- data/support/update-ec2-ami-tools +20 -0
- data/test/05_config/00_setup_test.rb +24 -0
- data/test/05_config/30_machines_test.rb +69 -0
- data/test/20_sdb/00_setup_test.rb +31 -0
- data/test/20_sdb/10_domains_test.rb +113 -0
- data/test/25_ec2/00_setup_test.rb +34 -0
- data/test/25_ec2/10_keypairs_test.rb +33 -0
- data/test/25_ec2/20_groups_test.rb +139 -0
- data/test/25_ec2/30_addresses_test.rb +35 -0
- data/test/25_ec2/40_volumes_test.rb +46 -0
- data/test/25_ec2/50_snapshots_test.rb +69 -0
- data/test/26_ec2_instances/00_setup_test.rb +33 -0
- data/test/26_ec2_instances/10_instances_test.rb +81 -0
- data/test/26_ec2_instances/50_images_test.rb +13 -0
- data/test/30_sdb_metadata/00_setup_test.rb +28 -0
- data/test/30_sdb_metadata/10_disks_test.rb +99 -0
- data/test/30_sdb_metadata/20_backups_test.rb +102 -0
- data/test/50_commands/00_setup_test.rb +11 -0
- data/test/50_commands/10_keypairs_test.rb +79 -0
- data/test/50_commands/20_groups_test.rb +77 -0
- data/test/50_commands/40_volumes_test.rb +55 -0
- data/test/50_commands/50_instances_test.rb +110 -0
- data/test/coverage.txt +51 -0
- data/test/helper.rb +35 -0
- data/tryouts/disks.rb +55 -0
- data/tryouts/nested_methods.rb +36 -0
- data/tryouts/session_tryout.rb +48 -0
- metadata +94 -25
- data/bin/rudy-ec2 +0 -108
- data/lib/rudy/command/base.rb +0 -839
- data/lib/rudy/command/deploy.rb +0 -12
- data/lib/rudy/command/environment.rb +0 -74
- data/lib/rudy/command/machines.rb +0 -170
- data/lib/rudy/command/metadata.rb +0 -41
- data/lib/rudy/metadata.rb +0 -26
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Helper
|
4
|
+
|
5
|
+
def test1
|
6
|
+
puts "test1"
|
7
|
+
|
8
|
+
def test2
|
9
|
+
def test3
|
10
|
+
puts "AWESOME"
|
11
|
+
end
|
12
|
+
|
13
|
+
puts "test2"
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
|
17
|
+
def test3
|
18
|
+
puts "test3"
|
19
|
+
end
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
include Helper
|
26
|
+
|
27
|
+
test1 do
|
28
|
+
puts "1"
|
29
|
+
test3 # => test3
|
30
|
+
test2 do
|
31
|
+
test3 # => AWESOME
|
32
|
+
puts "2"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# test2 # => throws error
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'session'
|
8
|
+
require 'net/ssh'
|
9
|
+
require 'rye'
|
10
|
+
require 'yaml'
|
11
|
+
require 'stringio'
|
12
|
+
|
13
|
+
#p Rye.command('ssh', '-i', '', '')
|
14
|
+
|
15
|
+
module Rye::Box::Commands
|
16
|
+
def rudy(*args); command("/proj/git/rudy/bin/rudy", args); end
|
17
|
+
end
|
18
|
+
|
19
|
+
logger = StringIO.new
|
20
|
+
rbox = Rye::Box.new('localhost', 'delano', :stderr => logger).connect
|
21
|
+
#rbox2 = Rye::Box.new('ec2-174-129-173-3.compute-1.amazonaws.com', 'root')
|
22
|
+
#rbox.add_keys('/Users/delano/Projects/git/rudy/.rudy/key-test-app')
|
23
|
+
#rbox.connect
|
24
|
+
#puts rbox.date
|
25
|
+
#puts rbox.pwd
|
26
|
+
puts rbox['/usr/bin'].pwd
|
27
|
+
puts rbox.uptime
|
28
|
+
puts rbox.can
|
29
|
+
puts rbox.echo '$HOME'
|
30
|
+
puts rbox.rudy('myaddress')
|
31
|
+
rbox.disconnect
|
32
|
+
#puts logger.read
|
33
|
+
#>>
|
34
|
+
|
35
|
+
__END__
|
36
|
+
|
37
|
+
|
38
|
+
rgroup = Rye::Group.new('root', 'keydir/file')
|
39
|
+
rgroup.add_hosts('ec2-174-129-173-3.compute-1.amazonaws.com')
|
40
|
+
rgroup.command('hostname')
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
#shell = Session::Shell.new
|
45
|
+
|
46
|
+
#p shell.execute('ssh -T -t -i /Users/delano/Projects/git/rudy/.rudy/key-test-app.private root@ec2-174-129-82-193.compute-1.amazonaws.com')
|
47
|
+
|
48
|
+
#Net::SSH.configuration_for(localhost, ssh_options.fetch(:config, true)).merge(ssh_options)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solutious-rudy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-08 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: echoe
|
17
17
|
type: :runtime
|
18
18
|
version_requirement:
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
26
|
+
name: amazon-ec2
|
27
27
|
type: :runtime
|
28
28
|
version_requirement:
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: "0"
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: aws-sdb
|
37
37
|
type: :runtime
|
38
38
|
version_requirement:
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: "0"
|
44
44
|
version:
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
|
-
name:
|
46
|
+
name: net-ssh
|
47
47
|
type: :runtime
|
48
48
|
version_requirement:
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
version: "0"
|
54
54
|
version:
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: net-
|
56
|
+
name: net-scp
|
57
57
|
type: :runtime
|
58
58
|
version_requirement:
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: "0"
|
64
64
|
version:
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
|
-
name: net-
|
66
|
+
name: net-ssh-gateway
|
67
67
|
type: :runtime
|
68
68
|
version_requirement:
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
version: "0"
|
74
74
|
version:
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name: net-ssh-
|
76
|
+
name: net-ssh-multi
|
77
77
|
type: :runtime
|
78
78
|
version_requirement:
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -83,7 +83,17 @@ dependencies:
|
|
83
83
|
version: "0"
|
84
84
|
version:
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
|
-
name:
|
86
|
+
name: drydock
|
87
|
+
type: :runtime
|
88
|
+
version_requirement:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: caesars
|
87
97
|
type: :runtime
|
88
98
|
version_requirement:
|
89
99
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -93,7 +103,7 @@ dependencies:
|
|
93
103
|
version: "0"
|
94
104
|
version:
|
95
105
|
- !ruby/object:Gem::Dependency
|
96
|
-
name:
|
106
|
+
name: rye
|
97
107
|
type: :runtime
|
98
108
|
version_requirement:
|
99
109
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -102,65 +112,124 @@ dependencies:
|
|
102
112
|
- !ruby/object:Gem::Version
|
103
113
|
version: "0"
|
104
114
|
version:
|
105
|
-
description:
|
115
|
+
description: Not your grandparent's deployment tool.
|
106
116
|
email: delano@solutious.com
|
107
117
|
executables:
|
108
118
|
- rudy
|
109
|
-
-
|
119
|
+
- ird
|
110
120
|
extensions: []
|
111
121
|
|
112
122
|
extra_rdoc_files:
|
113
123
|
- README.rdoc
|
114
124
|
- LICENSE.txt
|
125
|
+
- CHANGES.txt
|
115
126
|
files:
|
116
127
|
- CHANGES.txt
|
117
128
|
- LICENSE.txt
|
118
129
|
- README.rdoc
|
119
130
|
- Rakefile
|
131
|
+
- Rudyfile
|
132
|
+
- bin/ird
|
120
133
|
- bin/rudy
|
121
|
-
-
|
134
|
+
- lib/annoy.rb
|
122
135
|
- lib/aws_sdb.rb
|
123
136
|
- lib/aws_sdb/error.rb
|
124
137
|
- lib/aws_sdb/service.rb
|
125
138
|
- lib/console.rb
|
139
|
+
- lib/escape.rb
|
126
140
|
- lib/rudy.rb
|
127
141
|
- lib/rudy/aws.rb
|
128
142
|
- lib/rudy/aws/ec2.rb
|
143
|
+
- lib/rudy/aws/ec2/address.rb
|
144
|
+
- lib/rudy/aws/ec2/group.rb
|
145
|
+
- lib/rudy/aws/ec2/image.rb
|
146
|
+
- lib/rudy/aws/ec2/instance.rb
|
147
|
+
- lib/rudy/aws/ec2/keypair.rb
|
148
|
+
- lib/rudy/aws/ec2/snapshot.rb
|
149
|
+
- lib/rudy/aws/ec2/volume.rb
|
129
150
|
- lib/rudy/aws/s3.rb
|
130
151
|
- lib/rudy/aws/simpledb.rb
|
152
|
+
- lib/rudy/cli.rb
|
153
|
+
- lib/rudy/cli/addresses.rb
|
154
|
+
- lib/rudy/cli/backups.rb
|
155
|
+
- lib/rudy/cli/config.rb
|
156
|
+
- lib/rudy/cli/deploy.rb
|
157
|
+
- lib/rudy/cli/disks.rb
|
158
|
+
- lib/rudy/cli/domains.rb
|
159
|
+
- lib/rudy/cli/groups.rb
|
160
|
+
- lib/rudy/cli/images.rb
|
161
|
+
- lib/rudy/cli/instances.rb
|
162
|
+
- lib/rudy/cli/keypairs.rb
|
163
|
+
- lib/rudy/cli/manager.rb
|
164
|
+
- lib/rudy/cli/release.rb
|
165
|
+
- lib/rudy/cli/routines.rb
|
166
|
+
- lib/rudy/cli/volumes.rb
|
131
167
|
- lib/rudy/command/addresses.rb
|
132
168
|
- lib/rudy/command/backups.rb
|
133
|
-
- lib/rudy/command/
|
134
|
-
- lib/rudy/command/config.rb
|
135
|
-
- lib/rudy/command/deploy.rb
|
169
|
+
- lib/rudy/command/disks-old.rb
|
136
170
|
- lib/rudy/command/disks.rb
|
137
|
-
- lib/rudy/command/
|
171
|
+
- lib/rudy/command/domains.rb
|
138
172
|
- lib/rudy/command/groups.rb
|
139
|
-
- lib/rudy/command/images.rb
|
140
173
|
- lib/rudy/command/instances.rb
|
141
|
-
- lib/rudy/command/
|
142
|
-
- lib/rudy/command/
|
143
|
-
- lib/rudy/command/release.rb
|
174
|
+
- lib/rudy/command/keypairs.rb
|
175
|
+
- lib/rudy/command/manager.rb
|
144
176
|
- lib/rudy/command/volumes.rb
|
145
177
|
- lib/rudy/config.rb
|
146
|
-
- lib/rudy/
|
178
|
+
- lib/rudy/config/objects.rb
|
179
|
+
- lib/rudy/huxtable.rb
|
147
180
|
- lib/rudy/metadata/backup.rb
|
148
181
|
- lib/rudy/metadata/disk.rb
|
182
|
+
- lib/rudy/metadata/machine.rb
|
183
|
+
- lib/rudy/routines.rb
|
184
|
+
- lib/rudy/routines/disk_handler.rb
|
185
|
+
- lib/rudy/routines/release.rb
|
186
|
+
- lib/rudy/routines/script_runner.rb
|
187
|
+
- lib/rudy/routines/shutdown.rb
|
188
|
+
- lib/rudy/routines/startup.rb
|
149
189
|
- lib/rudy/scm/svn.rb
|
150
190
|
- lib/rudy/utils.rb
|
151
191
|
- lib/storable.rb
|
192
|
+
- lib/sysinfo.rb
|
152
193
|
- lib/tryouts.rb
|
153
194
|
- rudy.gemspec
|
154
195
|
- support/mailtest
|
196
|
+
- support/randomize-root-password
|
155
197
|
- support/rudy-ec2-startup
|
198
|
+
- support/update-ec2-ami-tools
|
199
|
+
- test/05_config/00_setup_test.rb
|
200
|
+
- test/05_config/30_machines_test.rb
|
201
|
+
- test/20_sdb/00_setup_test.rb
|
202
|
+
- test/20_sdb/10_domains_test.rb
|
203
|
+
- test/25_ec2/00_setup_test.rb
|
204
|
+
- test/25_ec2/10_keypairs_test.rb
|
205
|
+
- test/25_ec2/20_groups_test.rb
|
206
|
+
- test/25_ec2/30_addresses_test.rb
|
207
|
+
- test/25_ec2/40_volumes_test.rb
|
208
|
+
- test/25_ec2/50_snapshots_test.rb
|
209
|
+
- test/26_ec2_instances/00_setup_test.rb
|
210
|
+
- test/26_ec2_instances/10_instances_test.rb
|
211
|
+
- test/26_ec2_instances/50_images_test.rb
|
212
|
+
- test/30_sdb_metadata/00_setup_test.rb
|
213
|
+
- test/30_sdb_metadata/10_disks_test.rb
|
214
|
+
- test/30_sdb_metadata/20_backups_test.rb
|
215
|
+
- test/50_commands/00_setup_test.rb
|
216
|
+
- test/50_commands/10_keypairs_test.rb
|
217
|
+
- test/50_commands/20_groups_test.rb
|
218
|
+
- test/50_commands/40_volumes_test.rb
|
219
|
+
- test/50_commands/50_instances_test.rb
|
220
|
+
- test/coverage.txt
|
221
|
+
- test/helper.rb
|
156
222
|
- tryouts/console_tryout.rb
|
223
|
+
- tryouts/disks.rb
|
224
|
+
- tryouts/nested_methods.rb
|
225
|
+
- tryouts/session_tryout.rb
|
157
226
|
has_rdoc: true
|
158
227
|
homepage: http://github.com/solutious/rudy
|
159
228
|
post_install_message:
|
160
229
|
rdoc_options:
|
161
230
|
- --line-numbers
|
162
231
|
- --title
|
163
|
-
- "Rudy:
|
232
|
+
- "Rudy: Not your grandparent's deployment tool."
|
164
233
|
- --main
|
165
234
|
- README.rdoc
|
166
235
|
require_paths:
|
@@ -183,6 +252,6 @@ rubyforge_project: rudy
|
|
183
252
|
rubygems_version: 1.2.0
|
184
253
|
signing_key:
|
185
254
|
specification_version: 2
|
186
|
-
summary:
|
255
|
+
summary: Not your grandparent's deployment tool.
|
187
256
|
test_files: []
|
188
257
|
|
data/bin/rudy-ec2
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
3
|
-
# Rudy -- Your friend in staging and deploying to EC2
|
4
|
-
#
|
5
|
-
# See rudy -h for usage
|
6
|
-
#
|
7
|
-
|
8
|
-
#
|
9
|
-
# No Ruby 1.9.1 support. Only 1.8.x for now :[
|
10
|
-
unless RUBY_VERSION < "1.9"
|
11
|
-
puts "Sorry! We're using the right_aws gem and it doesn't support Ruby 1.9 (md5 error)."
|
12
|
-
exit 1
|
13
|
-
else
|
14
|
-
require 'rubygems'
|
15
|
-
end
|
16
|
-
|
17
|
-
RUDY_HOME = File.join(File.dirname(__FILE__), '..')
|
18
|
-
RUDY_LIB = File.join(RUDY_HOME, 'lib')
|
19
|
-
$:.unshift RUDY_LIB # Put our local lib in first place
|
20
|
-
|
21
|
-
require 'drydock'
|
22
|
-
extend Drydock
|
23
|
-
|
24
|
-
project "Rudy" # This also runs require 'ruby'
|
25
|
-
|
26
|
-
debug :on
|
27
|
-
|
28
|
-
capture :stderr
|
29
|
-
|
30
|
-
global :A, :accesskey, String, "AWS Access Key"
|
31
|
-
global :S, :secretkey, String, "AWS Secret Access Key"
|
32
|
-
global :R, :region, String, "Connect to a specific EC2 region (default: #{Rudy::DEFAULT_REGION})"
|
33
|
-
global :z, :zone, String, "Connect to a specific EC2 zone (default: #{Rudy::DEFAULT_ZONE})"
|
34
|
-
global :q, :quiet, "Run with less output"
|
35
|
-
global :v, :verbose, "Increase verbosity of output (i.e. -v or -vv or -vvv)" do
|
36
|
-
@verbose ||= 0
|
37
|
-
@verbose += 1
|
38
|
-
end
|
39
|
-
global :V, :version, "Display version number" do
|
40
|
-
puts "Rudy version: #{Rudy::VERSION}"
|
41
|
-
exit 0
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
# ----------------------------------- AMAZON EC2 COMMANDS --------
|
49
|
-
# ------------------------------------------------------------------
|
50
|
-
|
51
|
-
usage "rudy [global options] addresses [-A address instance ID]"
|
52
|
-
desc "Manage Amazon Elastic IP addresses"
|
53
|
-
argv :address, :instanceid
|
54
|
-
action :A, :associate, "Associate an address to a running instance"
|
55
|
-
command :addresses => Rudy::Command::Addresses
|
56
|
-
command_alias :addresses, :address
|
57
|
-
|
58
|
-
|
59
|
-
usage "rudy images [-C -i name [-b bucket -a account]] [-D AMI-ID]"
|
60
|
-
desc "Manage EC2 Machine Images (AMIs)"
|
61
|
-
option :a, :account, String, "Your Amazon Account Number"
|
62
|
-
option :i, :image_name, String, "The name of the image"
|
63
|
-
option :p, :print, "Print-only (don't execute commands)"
|
64
|
-
option :b, :bucket_name, String, "The name of the bucket that will store the image"
|
65
|
-
action :C, :create, "Create an image"
|
66
|
-
#action :P, :prepare, "Prepare a running instance to be used as an image"
|
67
|
-
action :D, :destroy, "Deregister an image (currently _does not_ remove images files from S3)"
|
68
|
-
argv :ami
|
69
|
-
command :images => Rudy::Command::Images
|
70
|
-
command_alias :images, :image
|
71
|
-
|
72
|
-
|
73
|
-
desc "Manage EC2 Volumes"
|
74
|
-
action :D, :destroy, "Destroy a volume"
|
75
|
-
argv :vol
|
76
|
-
command :volumes => Rudy::Command::Volumes
|
77
|
-
command_alias :volumes, :volume
|
78
|
-
|
79
|
-
|
80
|
-
usage "rudy [global options] instances [-D] [-S -i image ID] [instance ID OR group name]"
|
81
|
-
desc "Manage EC2 Instances"
|
82
|
-
option :all, "Display all instances"
|
83
|
-
option :a, :address, String, "Amazon elastic IP"
|
84
|
-
option :i, :image, String, "Amazon machine image ID (ami)"
|
85
|
-
#option :v, :volume, String, "Amazon volume ID"
|
86
|
-
action :D, :destroy, "Destroy the given instance IDs. All data will be lost!"
|
87
|
-
#action :S, :start, "Start an instance"
|
88
|
-
#action :R, :restart, "Restart an instance"
|
89
|
-
argv :filter
|
90
|
-
command :instances => Rudy::Command::Instances
|
91
|
-
command_alias :instances, :instance
|
92
|
-
|
93
|
-
|
94
|
-
usage "rudy [global options] groups [-C] [-a IP addresses] [-p ports] [group name]"
|
95
|
-
desc "Manage EC2 Security Groups"
|
96
|
-
option :all, "Display all security groups"
|
97
|
-
option :r, :protocols, Array, "Comma-separated list of protocols. One of: tcp (default), udp, icmp"
|
98
|
-
option :p, :ports, Array, "List of comma-separated ports to authorize (default: 22,80,443)"
|
99
|
-
option :a, :addresses, Array, "List of comma-separated IP addresses to authorize (default: your external IP)"
|
100
|
-
action :C, :create, "Create a security group"
|
101
|
-
action :D, :destroy, "Destroy a security group"
|
102
|
-
action :M, :modify, "Modify a security group"
|
103
|
-
argv :group
|
104
|
-
command :groups => Rudy::Command::Groups
|
105
|
-
command_alias :groups, :group
|
106
|
-
|
107
|
-
|
108
|
-
|
data/lib/rudy/command/base.rb
DELETED
@@ -1,839 +0,0 @@
|
|
1
|
-
|
2
|
-
module Rudy
|
3
|
-
class UnknownInstance < RuntimeError; end
|
4
|
-
end
|
5
|
-
|
6
|
-
module Rudy
|
7
|
-
module Command
|
8
|
-
class NoCred < RuntimeError; end;
|
9
|
-
|
10
|
-
class Base < Drydock::Command
|
11
|
-
|
12
|
-
attr_reader :scm
|
13
|
-
|
14
|
-
attr_reader :rscripts
|
15
|
-
attr_reader :domains
|
16
|
-
attr_reader :machine_images
|
17
|
-
|
18
|
-
attr_reader :config
|
19
|
-
|
20
|
-
|
21
|
-
def init
|
22
|
-
|
23
|
-
|
24
|
-
raise "PRODUCTION ACCESS IS DISABLED IN DEBUG MODE" if @global.environment == "prod" && Drydock.debug?
|
25
|
-
|
26
|
-
@global.config ||= RUDY_CONFIG_FILE
|
27
|
-
|
28
|
-
unless File.exists?(@global.config)
|
29
|
-
init_config_dir
|
30
|
-
end
|
31
|
-
|
32
|
-
@config = Rudy::Config.new(@global.config, {:verbose => (@global.verbose > 0)} )
|
33
|
-
@config.look_and_load
|
34
|
-
|
35
|
-
raise "There is no machine group configured" if @config.machines.nil?
|
36
|
-
raise "There is no AWS info configured" if @config.awsinfo.nil?
|
37
|
-
|
38
|
-
|
39
|
-
@global.accesskey ||= @config.awsinfo.accesskey || ENV['AWS_ACCESS_KEY']
|
40
|
-
@global.secretkey ||= @config.awsinfo.secretkey || ENV['AWS_SECRET_KEY'] || ENV['AWS_SECRET_ACCESS_KEY']
|
41
|
-
@global.account ||= @config.awsinfo.account || ENV['AWS_ACCOUNT_NUMBER']
|
42
|
-
|
43
|
-
@global.cert ||= @config.awsinfo.cert || ENV['EC2_CERT']
|
44
|
-
@global.privatekey ||= @config.awsinfo.privatekey || ENV['EC2_PRIVATE_KEY']
|
45
|
-
|
46
|
-
@global.cert = File.expand_path(@global.cert || '')
|
47
|
-
@global.privatekey = File.expand_path(@global.privatekey || '')
|
48
|
-
|
49
|
-
@global.region ||= @config.defaults.region || DEFAULT_REGION
|
50
|
-
@global.zone ||= @config.defaults.zone || DEFAULT_ZONE
|
51
|
-
@global.environment ||= @config.defaults.environment || DEFAULT_ENVIRONMENT
|
52
|
-
@global.role ||= @config.defaults.role || DEFAULT_ROLE
|
53
|
-
@global.position ||= @config.defaults.position || DEFAULT_POSITION
|
54
|
-
@global.user ||= @config.defaults.user || DEFAULT_USER
|
55
|
-
|
56
|
-
@global.local_user = ENV['USER'] || :user
|
57
|
-
@global.local_hostname = Socket.gethostname || :host
|
58
|
-
|
59
|
-
|
60
|
-
if @global.verbose > 1
|
61
|
-
puts "GLOBALS:"
|
62
|
-
@global.marshal_dump.each_pair do |n,v|
|
63
|
-
puts "#{n}: #{v}"
|
64
|
-
end
|
65
|
-
["machines", "routines"].each do |type|
|
66
|
-
puts "#{$/*2}#{type.upcase}:"
|
67
|
-
val = @config.send(type).find_deferred(@global.environment, @global.role)
|
68
|
-
puts val.to_hash.to_yaml
|
69
|
-
end
|
70
|
-
puts
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
# TODO: enforce home directory permissions
|
76
|
-
#if File.exists?(RUDY_CONFIG_DIR)
|
77
|
-
# puts "Checking #{check_environment} permissions..."
|
78
|
-
#end
|
79
|
-
|
80
|
-
if has_keys?
|
81
|
-
@ec2 = Rudy::AWS::EC2.new(@global.accesskey, @global.secretkey)
|
82
|
-
@sdb = Rudy::AWS::SimpleDB.new(@global.accesskey, @global.secretkey)
|
83
|
-
#@s3 = Rudy::AWS::SimpleDB.new(@global.accesskey, @global.secretkey)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
protected :init
|
87
|
-
|
88
|
-
def machine_data
|
89
|
-
machine_data = {
|
90
|
-
# Give the machine an identity
|
91
|
-
:zone => @global.zone,
|
92
|
-
:environment => @global.environment,
|
93
|
-
:role => @global.role,
|
94
|
-
:position => @global.position,
|
95
|
-
|
96
|
-
# Add hosts to the /etc/hosts file
|
97
|
-
:hosts => {
|
98
|
-
:dbmaster => "127.0.0.1",
|
99
|
-
}
|
100
|
-
}
|
101
|
-
|
102
|
-
machine_data.to_hash
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
# Raises exceptions if the requested user does
|
107
|
-
# not have a valid keypair configured. (See: EC2_KEYPAIR_*)
|
108
|
-
def check_keys
|
109
|
-
raise "No SSH key provided for #{@global.user}! (check #{RUDY_CONFIG_FILE})" unless has_keypair?
|
110
|
-
raise "SSH key provided but cannot be found! (check #{RUDY_CONFIG_FILE})" unless File.exists?(keypairpath)
|
111
|
-
end
|
112
|
-
|
113
|
-
def has_pem_keys?
|
114
|
-
(@global.cert && File.exists?(@global.cert) &&
|
115
|
-
@global.privatekey && File.exists?(@global.privatekey))
|
116
|
-
end
|
117
|
-
|
118
|
-
def has_keys?
|
119
|
-
(@global.accesskey && !@global.accesskey.empty? && @global.secretkey && !@global.secretkey.empty?)
|
120
|
-
end
|
121
|
-
|
122
|
-
def keypairpath(name=nil)
|
123
|
-
name ||= @global.user
|
124
|
-
raise "No default user configured" unless name
|
125
|
-
kp = @config.machines.find(@global.environment, @global.role, :users, name, :keypair2)
|
126
|
-
kp ||= @config.machines.find(@global.environment, :users, name, :keypair)
|
127
|
-
kp ||= @config.machines.find(:users, name, :keypair)
|
128
|
-
kp &&= File.expand_path(kp)
|
129
|
-
kp
|
130
|
-
end
|
131
|
-
def has_keypair?(name=nil)
|
132
|
-
kp = keypairpath(name)
|
133
|
-
(!kp.nil? && File.exists?(kp))
|
134
|
-
end
|
135
|
-
|
136
|
-
# Opens an SSH session.
|
137
|
-
# <li>+host+ the hostname to connect to. Defaults to the machine specified
|
138
|
-
# by @global.environment, @global.role, @global.position.</li>
|
139
|
-
# <li>+b+ a block to execute on the host. Receives |session|</li>
|
140
|
-
#
|
141
|
-
# ssh do |session|
|
142
|
-
# session.exec(cmd)
|
143
|
-
# end
|
144
|
-
#
|
145
|
-
# See Net::SSH
|
146
|
-
#
|
147
|
-
def ssh(host=nil, &b)
|
148
|
-
host ||= machine_hostname
|
149
|
-
raise "No host provided for SSH" unless host
|
150
|
-
raise "No block provided for SSH" unless b
|
151
|
-
|
152
|
-
Net::SSH.start(host, @global.user, :keys => [keypairpath]) do |session|
|
153
|
-
b.call(session)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# Secure copy.
|
158
|
-
#
|
159
|
-
# scp do |scp|
|
160
|
-
# # upload a file to a remote server
|
161
|
-
# scp.upload! "/local/path", "/remote/path"
|
162
|
-
#
|
163
|
-
# # upload from an in-memory buffer
|
164
|
-
# scp.upload! StringIO.new("some data to upload"), "/remote/path"
|
165
|
-
#
|
166
|
-
# # run multiple downloads in parallel
|
167
|
-
# d1 = scp.download("/remote/path", "/local/path")
|
168
|
-
# d2 = scp.download("/remote/path2", "/local/path2")
|
169
|
-
# [d1, d2].each { |d| d.wait }
|
170
|
-
# end
|
171
|
-
#
|
172
|
-
def scp(host=nil, &b)
|
173
|
-
host ||= machine_hostname
|
174
|
-
raise "No host provided for scp" unless host
|
175
|
-
raise "No block provided for scp" unless b
|
176
|
-
|
177
|
-
Net::SCP.start(host, @global.user, :keys => [keypairpath]) do |scp|
|
178
|
-
b.call(scp)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
# +name+ the name of the remote user to use for the remainder of the command
|
183
|
-
# (or until switched again). If no name is provided, the user will be revert
|
184
|
-
# to whatever it was before the previous switch.
|
185
|
-
def switch_user(name=nil)
|
186
|
-
if name == nil && @switch_user_previous
|
187
|
-
@global.user = @switch_user_previous
|
188
|
-
elsif @global.user != name
|
189
|
-
puts "Remote commands will be run as #{name} user"
|
190
|
-
@switch_user_previous = @global.user
|
191
|
-
@global.user = name
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# Returns a hash of info for the requested machine. If the requested machine
|
196
|
-
# is not running, it will raise an exception.
|
197
|
-
def find_current_machine
|
198
|
-
find_machine(machine_group)
|
199
|
-
end
|
200
|
-
|
201
|
-
def find_machine(group)
|
202
|
-
machine_list = @ec2.instances.list(group)
|
203
|
-
machine = machine_list.values.first # NOTE: Only one machine per group, for now...
|
204
|
-
raise "There's no machine running in #{group}" unless machine
|
205
|
-
raise "The primary machine in #{group} is not in a running state" unless machine[:aws_state] == 'running'
|
206
|
-
machine
|
207
|
-
end
|
208
|
-
|
209
|
-
def machine_hostname(group=nil)
|
210
|
-
group ||= machine_group
|
211
|
-
find_machine(group)[:dns_name]
|
212
|
-
end
|
213
|
-
|
214
|
-
def machine_group
|
215
|
-
[@global.environment, @global.role].join(RUDY_DELIM)
|
216
|
-
end
|
217
|
-
|
218
|
-
def machine_image
|
219
|
-
ami = @config.machines.find_deferred(@global.environment, @global.role, :ami)
|
220
|
-
raise "There is no AMI configured for #{machine_group}" unless ami
|
221
|
-
ami
|
222
|
-
end
|
223
|
-
|
224
|
-
def machine_address
|
225
|
-
@config.machines.find_deferred(@global.environment, @global.role, :address)
|
226
|
-
end
|
227
|
-
|
228
|
-
# TODO: fix machine_group to include zone
|
229
|
-
def machine_name
|
230
|
-
[@global.zone, machine_group, @global.position].join(RUDY_DELIM)
|
231
|
-
end
|
232
|
-
|
233
|
-
def instance_id?(id=nil)
|
234
|
-
(id && id[0,2] == "i-")
|
235
|
-
end
|
236
|
-
|
237
|
-
def image_id?(id=nil)
|
238
|
-
(id && id[0,4] == "ami-")
|
239
|
-
end
|
240
|
-
|
241
|
-
def volume_id?(id=nil)
|
242
|
-
(id && id[0,4] == "vol-")
|
243
|
-
end
|
244
|
-
|
245
|
-
def snapshot_id?(id=nil)
|
246
|
-
(id && id[0,5] == "snap-")
|
247
|
-
end
|
248
|
-
|
249
|
-
|
250
|
-
def wait_for_machine(id)
|
251
|
-
|
252
|
-
print "Waiting for #{id} to become available"
|
253
|
-
STDOUT.flush
|
254
|
-
|
255
|
-
while @ec2.instances.pending?(id)
|
256
|
-
sleep 2
|
257
|
-
print '.'
|
258
|
-
STDOUT.flush
|
259
|
-
end
|
260
|
-
|
261
|
-
machine = @ec2.instances.get(id)
|
262
|
-
|
263
|
-
puts " It's up!\a\a" # with bells
|
264
|
-
print "Waiting for SSH daemon at #{machine[:dns_name]}"
|
265
|
-
STDOUT.flush
|
266
|
-
|
267
|
-
while !Rudy::Utils.service_available?(machine[:dns_name], 22)
|
268
|
-
print '.'
|
269
|
-
STDOUT.flush
|
270
|
-
end
|
271
|
-
puts " It's up!\a\a\a"
|
272
|
-
|
273
|
-
end
|
274
|
-
|
275
|
-
|
276
|
-
def device_to_path(machine, device)
|
277
|
-
# /dev/sdr 10321208 154232 9642688 2% /rilli/app
|
278
|
-
dfoutput = ssh_command(machine[:dns_name], keypairpath, @global.user, "df #{device} | tail -1").chomp
|
279
|
-
dfvals = dfoutput.scan(/(#{device}).+\s(.+?)$/).flatten # ["/dev/sdr", "/rilli/app"]
|
280
|
-
dfvals.last
|
281
|
-
end
|
282
|
-
|
283
|
-
# +action+ is one of: :shutdown, :start, :deploy
|
284
|
-
# +machine+ is a right_aws machine instance hash
|
285
|
-
def execute_disk_routines(machines, action)
|
286
|
-
machines = [machines] unless machines.is_a?( Array)
|
287
|
-
|
288
|
-
puts "Running #{action.to_s.capitalize} DISK routines".att(:bright)
|
289
|
-
|
290
|
-
disks = @config.machines.find_deferred(@global.environment, @global.role, :disks)
|
291
|
-
routines = @config.routines.find(@global.environment, @global.role, action, :disks)
|
292
|
-
|
293
|
-
unless routines
|
294
|
-
puts "No #{action} disk routines."
|
295
|
-
return
|
296
|
-
end
|
297
|
-
|
298
|
-
switch_user("root")
|
299
|
-
|
300
|
-
machines.each do |machine|
|
301
|
-
|
302
|
-
unless machine[:aws_instance_id]
|
303
|
-
puts "Machine given has no instance ID. Skipping disks."
|
304
|
-
return
|
305
|
-
end
|
306
|
-
|
307
|
-
unless machine[:dns_name]
|
308
|
-
puts "Machine given has no DNS name. Skipping disks."
|
309
|
-
return
|
310
|
-
end
|
311
|
-
|
312
|
-
if routines.destroy
|
313
|
-
disk_paths = routines.destroy.keys
|
314
|
-
vols = @ec2.instances.volumes(machine[:aws_instance_id]) || []
|
315
|
-
puts "No volumes to destroy for (#{machine[:aws_instance_id]})" if vols.empty?
|
316
|
-
vols.each do |vol|
|
317
|
-
disk = Rudy::MetaData::Disk.find_from_volume(@sdb, vol[:aws_id])
|
318
|
-
if disk
|
319
|
-
this_path = disk.path
|
320
|
-
else
|
321
|
-
puts "No disk metadata for volume #{vol[:aws_id]}. Going old school..."
|
322
|
-
this_path = device_to_path(machine, vol[:aws_device])
|
323
|
-
end
|
324
|
-
|
325
|
-
dconf = disks[this_path]
|
326
|
-
|
327
|
-
unless dconf
|
328
|
-
puts "#{this_path} is not defined for this machine. Check your machines config."
|
329
|
-
next
|
330
|
-
end
|
331
|
-
|
332
|
-
if disk_paths.member?(this_path)
|
333
|
-
|
334
|
-
unless disks.has_key?(this_path)
|
335
|
-
puts "#{this_path} is not defined as a machine disk. Skipping..."
|
336
|
-
next
|
337
|
-
end
|
338
|
-
|
339
|
-
begin
|
340
|
-
puts "Unmounting #{this_path}..."
|
341
|
-
ssh_command machine[:dns_name], keypairpath, @global.user, "umount #{this_path}"
|
342
|
-
sleep 3
|
343
|
-
rescue => ex
|
344
|
-
puts "Error while unmounting #{this_path}: #{ex.message}"
|
345
|
-
puts ex.backtrace if Drydock.debug?
|
346
|
-
puts "We'll keep going..."
|
347
|
-
end
|
348
|
-
|
349
|
-
begin
|
350
|
-
|
351
|
-
if @ec2.volumes.attached?(disk.awsid)
|
352
|
-
puts "Detaching #{vol[:aws_id]}"
|
353
|
-
@ec2.volumes.detach(vol[:aws_id])
|
354
|
-
sleep 3 # TODO: replace with something like wait_for_machine
|
355
|
-
end
|
356
|
-
|
357
|
-
puts "Destroying #{this_path} (#{vol[:aws_id]})"
|
358
|
-
if @ec2.volumes.available?(disk.awsid)
|
359
|
-
@ec2.volumes.destroy(vol[:aws_id])
|
360
|
-
else
|
361
|
-
puts "Volume is still attached (maybe a web server of database is running?)"
|
362
|
-
end
|
363
|
-
|
364
|
-
if disk
|
365
|
-
puts "Deleteing metadata for #{disk.name}"
|
366
|
-
Rudy::MetaData::Disk.destroy(@sdb, disk)
|
367
|
-
end
|
368
|
-
|
369
|
-
rescue => ex
|
370
|
-
puts "Error while detaching volume #{vol[:aws_id]}: #{ex.message}"
|
371
|
-
puts ex.backtrace if Drydock.debug?
|
372
|
-
puts "Continuing..."
|
373
|
-
end
|
374
|
-
|
375
|
-
end
|
376
|
-
puts
|
377
|
-
|
378
|
-
end
|
379
|
-
|
380
|
-
end
|
381
|
-
|
382
|
-
|
383
|
-
if routines.mount
|
384
|
-
disk_paths = routines.mount.keys
|
385
|
-
vols = @ec2.instances.volumes(machine[:aws_instance_id]) || []
|
386
|
-
puts "No volumes to mount for (#{machine[:aws_instance_id]})" if vols.empty?
|
387
|
-
vols.each do |vol|
|
388
|
-
disk = Rudy::MetaData::Disk.find_from_volume(@sdb, vol[:aws_id])
|
389
|
-
if disk
|
390
|
-
this_path = disk.path
|
391
|
-
else
|
392
|
-
puts "No disk metadata for volume #{vol[:aws_id]}. Going old school..."
|
393
|
-
this_path = device_to_path(machine, vol[:aws_device])
|
394
|
-
end
|
395
|
-
|
396
|
-
next unless disk_paths.member?(this_path)
|
397
|
-
|
398
|
-
dconf = disks[this_path]
|
399
|
-
|
400
|
-
unless dconf
|
401
|
-
puts "#{this_path} is not defined for this machine. Check your machines config."
|
402
|
-
next
|
403
|
-
end
|
404
|
-
|
405
|
-
|
406
|
-
begin
|
407
|
-
unless @ec2.instances.attached_volume?(machine[:aws_instance_id], vol[:aws_device])
|
408
|
-
puts "Attaching #{vol[:aws_id]} to #{machine[:aws_instance_id]}".att(:bright)
|
409
|
-
@ec2.volumes.attach(machine[:aws_instance_id], vol[:aws_id],vol[:aws_device])
|
410
|
-
sleep 3
|
411
|
-
end
|
412
|
-
|
413
|
-
puts "Mounting #{this_path} to #{vol[:aws_device]}".att(:bright)
|
414
|
-
ssh_command machine[:dns_name], keypairpath, @global.user, "mkdir -p #{this_path} && mount -t ext3 #{vol[:aws_device]} #{this_path}"
|
415
|
-
|
416
|
-
sleep 1
|
417
|
-
rescue => ex
|
418
|
-
puts "There was an error mounting #{this_path}: #{ex.message}"
|
419
|
-
puts ex.backtrace if Drydock.debug?
|
420
|
-
end
|
421
|
-
puts
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
if routines.restore
|
428
|
-
|
429
|
-
routines.restore.each_pair do |path,props|
|
430
|
-
from = props[:from] || "unknown"
|
431
|
-
unless from.to_s == "backup"
|
432
|
-
puts "Sorry! You can currently only restore from backup. Check your routines config."
|
433
|
-
next
|
434
|
-
end
|
435
|
-
|
436
|
-
begin
|
437
|
-
puts "Restoring disk for #{path}"
|
438
|
-
|
439
|
-
dconf = disks[path]
|
440
|
-
|
441
|
-
unless dconf
|
442
|
-
puts "#{path} is not defined for this machine. Check your machines config."
|
443
|
-
next
|
444
|
-
end
|
445
|
-
|
446
|
-
zon = props[:zone] || @global.zone
|
447
|
-
env = props[:environment] || @global.environment
|
448
|
-
rol = props[:role] || @global.role
|
449
|
-
pos = props[:position] || @global.position
|
450
|
-
puts "Looking for backup from #{zon}-#{env}-#{rol}-#{pos}"
|
451
|
-
backup = find_most_recent_backup(zon, env, rol, pos, path)
|
452
|
-
|
453
|
-
unless backup
|
454
|
-
puts "No backups found"
|
455
|
-
next
|
456
|
-
end
|
457
|
-
|
458
|
-
puts "Found: #{backup.name}".att(:bright)
|
459
|
-
|
460
|
-
disk = Rudy::MetaData::Disk.new
|
461
|
-
disk.path = path
|
462
|
-
[:region, :zone, :environment, :role, :position].each do |n|
|
463
|
-
disk.send("#{n}=", @global.send(n)) if @global.send(n)
|
464
|
-
end
|
465
|
-
|
466
|
-
disk.device = dconf[:device]
|
467
|
-
size = (backup.size.to_i > dconf[:size].to_i) ? backup.size : dconf[:size]
|
468
|
-
disk.size = size.to_i
|
469
|
-
|
470
|
-
|
471
|
-
if Rudy::MetaData::Disk.is_defined?(@sdb, disk)
|
472
|
-
puts "The disk #{disk.name} already exists."
|
473
|
-
puts "You probably need to define when to destroy the disk."
|
474
|
-
puts "Skipping..."
|
475
|
-
next
|
476
|
-
end
|
477
|
-
|
478
|
-
if @ec2.instances.attached_volume?(machine[:aws_instance_id], disk.device)
|
479
|
-
puts "Skipping disk for #{disk.path} (device #{disk.device} is in use)"
|
480
|
-
next
|
481
|
-
end
|
482
|
-
|
483
|
-
# NOTE: It's important to use Caesars' hash syntax b/c the disk property
|
484
|
-
# "size" conflicts with Hash#size which is what we'll get if there's no
|
485
|
-
# size defined.
|
486
|
-
unless disk.size.kind_of?(Integer)
|
487
|
-
puts "Skipping disk for #{disk.path} (size not defined)"
|
488
|
-
next
|
489
|
-
end
|
490
|
-
|
491
|
-
if disk.path.nil?
|
492
|
-
puts "Skipping disk for #{disk.path} (no path defined)"
|
493
|
-
next
|
494
|
-
end
|
495
|
-
|
496
|
-
unless disk.valid?
|
497
|
-
puts "Skipping #{disk.name} (not enough info)"
|
498
|
-
next
|
499
|
-
end
|
500
|
-
|
501
|
-
puts "Creating volume... (from #{backup.awsid})".att(:bright)
|
502
|
-
volume = @ec2.volumes.create(@global.zone, disk.size, backup.awsid)
|
503
|
-
|
504
|
-
puts "Attaching #{volume[:aws_id]} to #{machine[:aws_instance_id]}".att(:bright)
|
505
|
-
@ec2.volumes.attach(machine[:aws_instance_id], volume[:aws_id], disk.device)
|
506
|
-
sleep 3
|
507
|
-
|
508
|
-
puts "Mounting #{disk.device} to #{disk.path}".att(:bright)
|
509
|
-
ssh_command machine[:dns_name], keypairpath, @global.user, "mkdir -p #{disk.path} && mount -t ext3 #{disk.device} #{disk.path}"
|
510
|
-
|
511
|
-
puts "Creating disk metadata for #{disk.name}"
|
512
|
-
disk.awsid = volume[:aws_id]
|
513
|
-
Rudy::MetaData::Disk.save(@sdb, disk)
|
514
|
-
|
515
|
-
sleep 1
|
516
|
-
rescue => ex
|
517
|
-
puts "There was an error creating #{path}: #{ex.message}"
|
518
|
-
puts ex.backtrace if Drydock.debug?
|
519
|
-
if disk
|
520
|
-
puts "Removing metadata for #{disk.name}"
|
521
|
-
Rudy::MetaData::Disk.destroy(@sdb, disk)
|
522
|
-
end
|
523
|
-
end
|
524
|
-
puts
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
if routines.create
|
531
|
-
routines.create.each_pair do |path,props|
|
532
|
-
|
533
|
-
begin
|
534
|
-
puts "Creating disk for #{path}"
|
535
|
-
|
536
|
-
dconf = disks[path]
|
537
|
-
|
538
|
-
unless dconf
|
539
|
-
puts "#{path} is not defined for this machine. Check your machines config."
|
540
|
-
next
|
541
|
-
end
|
542
|
-
|
543
|
-
disk = Rudy::MetaData::Disk.new
|
544
|
-
disk.path = path
|
545
|
-
[:region, :zone, :environment, :role, :position].each do |n|
|
546
|
-
disk.send("#{n}=", @global.send(n)) if @global.send(n)
|
547
|
-
end
|
548
|
-
[:device, :size].each do |n|
|
549
|
-
disk.send("#{n}=", dconf[n]) if dconf.has_key?(n)
|
550
|
-
end
|
551
|
-
|
552
|
-
if Rudy::MetaData::Disk.is_defined?(@sdb, disk)
|
553
|
-
puts "The disk #{disk.name} already exists."
|
554
|
-
puts "You probably need to define when to destroy the disk."
|
555
|
-
puts "Skipping..."
|
556
|
-
next
|
557
|
-
end
|
558
|
-
|
559
|
-
if @ec2.instances.attached_volume?(machine[:aws_instance_id], disk.device)
|
560
|
-
puts "Skipping disk for #{disk.path} (device #{disk.device} is in use)"
|
561
|
-
next
|
562
|
-
end
|
563
|
-
|
564
|
-
# NOTE: It's important to use Caesars' hash syntax b/c the disk property
|
565
|
-
# "size" conflicts with Hash#size which is what we'll get if there's no
|
566
|
-
# size defined.
|
567
|
-
unless disk.size.kind_of?(Integer)
|
568
|
-
puts "Skipping disk for #{disk.path} (size not defined)"
|
569
|
-
next
|
570
|
-
end
|
571
|
-
|
572
|
-
if disk.path.nil?
|
573
|
-
puts "Skipping disk for #{disk.path} (no path defined)"
|
574
|
-
next
|
575
|
-
end
|
576
|
-
|
577
|
-
unless disk.valid?
|
578
|
-
puts "Skipping #{disk.name} (not enough info)"
|
579
|
-
next
|
580
|
-
end
|
581
|
-
|
582
|
-
puts "Creating volume... (#{disk.size}GB in #{@global.zone})".att(:bright)
|
583
|
-
volume = @ec2.volumes.create(@global.zone, disk.size)
|
584
|
-
|
585
|
-
puts "Attaching #{volume[:aws_id]} to #{machine[:aws_instance_id]}".att(:bright)
|
586
|
-
@ec2.volumes.attach(machine[:aws_instance_id], volume[:aws_id], disk.device)
|
587
|
-
sleep 6
|
588
|
-
|
589
|
-
puts "Creating the filesystem (mkfs.ext3 -F #{disk.device})".att(:bright)
|
590
|
-
ssh_command machine[:dns_name], keypairpath, @global.user, "mkfs.ext3 -F #{disk.device}"
|
591
|
-
sleep 3
|
592
|
-
|
593
|
-
puts "Mounting #{disk.device} to #{disk.path}".att(:bright)
|
594
|
-
ssh_command machine[:dns_name], keypairpath, @global.user, "mkdir -p #{disk.path} && mount -t ext3 #{disk.device} #{disk.path}"
|
595
|
-
|
596
|
-
puts "Creating disk metadata for #{disk.name}"
|
597
|
-
disk.awsid = volume[:aws_id]
|
598
|
-
Rudy::MetaData::Disk.save(@sdb, disk)
|
599
|
-
|
600
|
-
sleep 1
|
601
|
-
rescue => ex
|
602
|
-
puts "There was an error creating #{path}: #{ex.message}"
|
603
|
-
if disk
|
604
|
-
puts "Removing metadata for #{disk.name}"
|
605
|
-
Rudy::MetaData::Disk.destroy(@sdb, disk)
|
606
|
-
end
|
607
|
-
end
|
608
|
-
puts
|
609
|
-
end
|
610
|
-
end
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
def find_most_recent_backup(zon, env, rol, pos, path)
|
615
|
-
criteria = [zon, env, rol, pos, path]
|
616
|
-
(Rudy::MetaData::Backup.list(@sdb, *criteria) || []).first
|
617
|
-
end
|
618
|
-
|
619
|
-
def execute_routines(machines, action, before_or_after)
|
620
|
-
machines = [machines] unless machines.is_a?( Array)
|
621
|
-
config = @config.routines.find_deferred(@global.environment, @global.role, :config) || {}
|
622
|
-
config[:global] = @global.marshal_dump
|
623
|
-
config[:global].reject! { |n,v| n == :cert || n == :privatekey }
|
624
|
-
|
625
|
-
# The config file contains settings from ~/.rudy/config
|
626
|
-
#
|
627
|
-
# routines do
|
628
|
-
# config do
|
629
|
-
# end
|
630
|
-
# end
|
631
|
-
#
|
632
|
-
config_file = "#{action}-config.yaml"
|
633
|
-
tf = Tempfile.new(config_file)
|
634
|
-
write_to_file(tf.path, config.to_hash.to_yaml, 'w')
|
635
|
-
puts "Running #{action.to_s.capitalize} #{before_or_after.to_s.upcase} routines".att(:bright)
|
636
|
-
machines.each do |machine|
|
637
|
-
|
638
|
-
rscripts = @config.routines.find_deferred(@global.environment, @global.role, action, before_or_after) || []
|
639
|
-
rscripts = [rscripts] unless rscripts.is_a?(Array)
|
640
|
-
|
641
|
-
puts "No scripts defined." if !rscripts || rscripts.empty?
|
642
|
-
|
643
|
-
rscripts.each do |rscript|
|
644
|
-
user, script = rscript.shift
|
645
|
-
|
646
|
-
switch_user(user) # scp and ssh will run as this user
|
647
|
-
|
648
|
-
puts "Transfering #{config_file}..."
|
649
|
-
scp do |scp|
|
650
|
-
scp.upload!(tf.path, "~/#{config_file}") do |ch, name, sent, total|
|
651
|
-
"#{name}: #{sent}/#{total}"
|
652
|
-
end
|
653
|
-
end
|
654
|
-
ssh do |session|
|
655
|
-
puts "Running #{script}...".att(:bright)
|
656
|
-
session.exec!("chmod 700 ~/#{config_file}")
|
657
|
-
session.exec!("chmod 700 #{script}")
|
658
|
-
puts session.exec!("#{script}")
|
659
|
-
|
660
|
-
puts "Removing remote copy of #{config_file}..."
|
661
|
-
session.exec!("rm ~/#{config_file}")
|
662
|
-
end
|
663
|
-
puts $/
|
664
|
-
end
|
665
|
-
end
|
666
|
-
|
667
|
-
tf.delete # remove local copy of config_file
|
668
|
-
#switch_user # return to the requested user
|
669
|
-
end
|
670
|
-
|
671
|
-
# Print a default header to the screen for every command.
|
672
|
-
# +cmd+ is the name of the command current running.
|
673
|
-
def print_header(cmd=nil)
|
674
|
-
title = "RUDY v#{Rudy::VERSION}" unless @global.quiet
|
675
|
-
now_utc = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")
|
676
|
-
criteria = []
|
677
|
-
[:zone, :environment, :role, :position].each do |n|
|
678
|
-
val = @global.send(n)
|
679
|
-
next unless val
|
680
|
-
criteria << "#{n.to_s.slice(0,1).att :normal}:#{val.att :bright}"
|
681
|
-
end
|
682
|
-
puts '%s -- %s UTC' % [title, now_utc] unless @global.quiet
|
683
|
-
puts '[%s]' % criteria.join(" ") unless @global.quiet
|
684
|
-
|
685
|
-
puts unless @global.quiet
|
686
|
-
|
687
|
-
if (@global.environment == "prod")
|
688
|
-
msg = without_indent %q(
|
689
|
-
=======================================================
|
690
|
-
=======================================================
|
691
|
-
!!!!!!!!! YOU ARE PLAYING WITH PRODUCTION !!!!!!!!!
|
692
|
-
=======================================================
|
693
|
-
=======================================================)
|
694
|
-
puts msg.colour(:red).bgcolour(:white).att(:bright), $/ unless @global.quiet
|
695
|
-
|
696
|
-
end
|
697
|
-
|
698
|
-
if Rudy.in_situ?
|
699
|
-
msg = %q(============ THIS IS EC2 ============)
|
700
|
-
puts msg.colour(:blue).bgcolour(:white).att(:bright), $/ unless @global.quiet
|
701
|
-
end
|
702
|
-
|
703
|
-
end
|
704
|
-
|
705
|
-
def print_footer
|
706
|
-
|
707
|
-
end
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
def group_metadata(env=@global.environment, role=@global.role)
|
713
|
-
query = "['environment' = '#{env}'] intersection ['role' = '#{role}']"
|
714
|
-
@sdb.query_with_attributes(RUDY_DOMAIN, query)
|
715
|
-
end
|
716
|
-
|
717
|
-
private
|
718
|
-
# Print info about a running instance
|
719
|
-
# +inst+ is a hash
|
720
|
-
def print_instance(inst)
|
721
|
-
puts '-'*60
|
722
|
-
puts "Instance: #{inst[:aws_instance_id].att(:bright)} (AMI: #{inst[:aws_image_id]})"
|
723
|
-
[:aws_state, :dns_name, :private_dns_name, :aws_availability_zone, :aws_launch_time, :ssh_key_name].each do |key|
|
724
|
-
printf(" %22s: %s#{$/}", key, inst[key]) if inst[key]
|
725
|
-
end
|
726
|
-
printf(" %22s: %s#{$/}", 'aws_groups', inst[:aws_groups].join(', '))
|
727
|
-
puts
|
728
|
-
end
|
729
|
-
|
730
|
-
def print_image(img)
|
731
|
-
puts '-'*60
|
732
|
-
puts "Image: #{img[:aws_id].att(:bright)}"
|
733
|
-
img.each_pair do |key, value|
|
734
|
-
printf(" %22s: %s#{$/}", key, value) if value
|
735
|
-
end
|
736
|
-
puts
|
737
|
-
end
|
738
|
-
|
739
|
-
def print_disk(disk, backups=[])
|
740
|
-
puts '-'*60
|
741
|
-
puts "Disk: #{disk.name.att(:bright)}"
|
742
|
-
puts disk.to_s
|
743
|
-
puts "#{backups.size} most recent backups:", backups.collect { |back| "#{back.nice_time} (#{back.awsid})" }
|
744
|
-
puts
|
745
|
-
end
|
746
|
-
|
747
|
-
|
748
|
-
def print_volume(vol, disk)
|
749
|
-
puts '-'*60
|
750
|
-
puts "Volume: #{vol[:aws_id].att(:bright)} (disk: #{disk.name if disk})"
|
751
|
-
vol.each_pair do |key, value|
|
752
|
-
printf(" %22s: %s#{$/}", key, value) if value
|
753
|
-
end
|
754
|
-
puts
|
755
|
-
end
|
756
|
-
|
757
|
-
# Print info about a a security group
|
758
|
-
# +group+ is an OpenStruct
|
759
|
-
def print_group(group)
|
760
|
-
puts '-'*60
|
761
|
-
puts "%12s: %s" % ['GROUP', group[:aws_group_name].att(:bright)]
|
762
|
-
puts
|
763
|
-
|
764
|
-
group_ip = {}
|
765
|
-
group[:aws_perms].each do |perm|
|
766
|
-
(group_ip[ perm[:cidr_ips] ] ||= []) << "#{perm[:protocol]}/#{perm[:from_port]}-#{perm[:to_port]}"
|
767
|
-
end
|
768
|
-
|
769
|
-
puts "%22s %s" % ["source address/mask", "protocol/ports (from, to)"]
|
770
|
-
|
771
|
-
|
772
|
-
group_ip.each_pair do |ip, perms|
|
773
|
-
puts "%22s %s" % [ip, perms.shift]
|
774
|
-
perms.each do |perm|
|
775
|
-
puts "%22s %s" % ['', perm]
|
776
|
-
end
|
777
|
-
puts
|
778
|
-
end
|
779
|
-
end
|
780
|
-
|
781
|
-
def init_config_dir
|
782
|
-
unless File.exists?(RUDY_CONFIG_DIR)
|
783
|
-
puts "Creating #{RUDY_CONFIG_DIR}"
|
784
|
-
Dir.mkdir(RUDY_CONFIG_DIR, 0700)
|
785
|
-
end
|
786
|
-
|
787
|
-
unless File.exists?(RUDY_CONFIG_FILE)
|
788
|
-
puts "Creating #{RUDY_CONFIG_FILE}"
|
789
|
-
rudy_config = without_indent %Q{
|
790
|
-
# Amazon Web Services
|
791
|
-
# Account access indentifiers.
|
792
|
-
awsinfo do
|
793
|
-
account ""
|
794
|
-
accesskey ""
|
795
|
-
secretkey ""
|
796
|
-
privatekey "~/path/2/pk-xxxx.pem"
|
797
|
-
cert "~/path/2/cert-xxxx.pem"
|
798
|
-
end
|
799
|
-
|
800
|
-
# Machine Configuration
|
801
|
-
# Specify your private keys here. These can be defined globally
|
802
|
-
# or by environment and role like in machines.rb.
|
803
|
-
machines do
|
804
|
-
ami "ami-0734d36e" # gentoo-m1.small-v5
|
805
|
-
users do
|
806
|
-
root :keypair => "path/2/root-private-key"
|
807
|
-
end
|
808
|
-
end
|
809
|
-
|
810
|
-
# Routine Configuration
|
811
|
-
# Define stuff here that you don't want to be stored in version control.
|
812
|
-
routines do
|
813
|
-
config do
|
814
|
-
# ...
|
815
|
-
end
|
816
|
-
end
|
817
|
-
|
818
|
-
# Global Defaults
|
819
|
-
# Define the values to use unless otherwise specified on the command-line.
|
820
|
-
defaults do
|
821
|
-
region "us-east-1"
|
822
|
-
zone "us-east-1b"
|
823
|
-
environment "stage"
|
824
|
-
role "app"
|
825
|
-
position "01"
|
826
|
-
user ENV['USER']
|
827
|
-
end
|
828
|
-
}
|
829
|
-
write_to_file(RUDY_CONFIG_FILE, rudy_config, 'w')
|
830
|
-
end
|
831
|
-
|
832
|
-
#puts "Creating SimpleDB domain called #{RUDY_DOMAIN}"
|
833
|
-
#@sdb.domains.create(RUDY_DOMAIN)
|
834
|
-
end
|
835
|
-
end
|
836
|
-
end
|
837
|
-
end
|
838
|
-
|
839
|
-
|