rudy 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -1,9 +1,60 @@
1
1
  RUDY, CHANGES
2
2
 
3
+ TODO: Look into RubyGems error
4
+ /Library/Ruby/Gems/1.8/gems/rake-0.8.3/lib/rake/gempackagetask.rb:13:Warning: Gem::manage_gems is deprecated and will be removed on or after March 2009.
5
+ rake aborted!
6
+ RubyGem version error: rdoc(2.4.0 not ~> 2.3.0)
7
+
8
+ TODO: Remove aws_swb
9
+
10
+
11
+ #### 0.4.1 (2009-03-??) ###############################
12
+
13
+ * CHANGE: Recommend keypair config to be in ~/.rudy/config
14
+ * FIX: Rudy now checks for user keys specified by env-role, env, and global
15
+ * FIX: gemspec dependency net-ssh-multi
16
+ * NEW: rerelease command
17
+
18
+ #### 0.4 (2009-03-12) ###############################
19
+
20
+ NOTE: This is a significant re-write from 0.3
21
+
22
+ * CHANGE: Mostly re-written bin/ruby, moving validation to Command classes
23
+ * CHANGE: upgrade to Drydock 0.5
24
+ * CHANGE: Moved generic EC2 commands to bin/rudy-ec2
25
+ * CHANGE: Removed ambiguity of pluralized command names.
26
+ * OLD: backups, disks, configs
27
+ * NEW: backup, disk, config
28
+ * NEW: ssh and scp commands for connecting to and copying files to/from machines
29
+ * NEW: New dependencies (trying out net-ssh)
30
+ * NEW: Domain specific language for configuration
31
+ * NEW: "Routines" for handling common actions. Starting, stopping, releasing, deploying.
32
+ * NEW: "rudy release" will create a release from the current working copy, start an instance,
33
+ checkout the release, run routines. It needs some work still, but this already functions as
34
+ a single command release process.
35
+ * NEW: "rudy start|destroy|restart|update|status". Routines allow us to have generic commands
36
+ that can be used for any machine group. These commands relate to starting new instances.
37
+ * NEW: Extra caution when running destructive commands
38
+ * NEW: Default ~/.rudy/config created if it doesn't exist.
39
+
40
+
41
+ #### 0.3 (2009-02-26) ###############################
42
+
43
+ NOTE: This is a significant re-write from 0.2
44
+
45
+ * CHANGE: Re-written support/rudy-ec2-startup
46
+ * CHANGE: upgrade to Drydock 0.4
47
+ * NEW: More functionality for disks and backups
48
+ * NEW: config commands
49
+ * NEW: Per machine configuration (via ~/.rudy)
50
+
51
+
3
52
  #### 0.2 (2009-02-23) ###############################
4
53
 
5
54
  NOTE: This is a complete re-write from 0.1
6
55
 
56
+ * CHANGE: Added Environment variables
57
+ * CHANGE: upgrade to drydock 0.3.3
7
58
  * NEW: All time references are converted to UTC
8
59
  * NEW: Safer "Are you sure?". Number of characters to enter is
9
60
  commiserate with amount of danger.
@@ -16,10 +67,9 @@ NOTE: This is a complete re-write from 0.1
16
67
  * NEW: Partial support for regions and zones
17
68
  * NEW: Manage system based on security groups.
18
69
  * NEW: "rudy groups" overhaul. Display, creates, destroys groups.
19
- * CHANGE: Added Environment variables
20
- * UPGRADE: drydock 0.3.3
70
+
21
71
 
22
72
 
23
73
  #### 0.1 (2009-02-06) ###############################
24
74
 
25
- * Initial release
75
+ * Initial public release
data/README.rdoc CHANGED
@@ -1,12 +1,13 @@
1
- = Rudy - v0.3 BETA!
1
+ = Rudy - v0.4 ALPHA!
2
2
 
3
3
  Rudy is a handy staging and deployment tool for EC2.
4
4
 
5
- NOTE: Rudy is not ready for general consumption. Come back in Q2 2009!
5
+ NOTE: Rudy will be ready for general consumption in Q2 2009.
6
6
 
7
7
  == Installation
8
8
 
9
- # Soon!
9
+ * Soon!
10
+ * ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION' (See net/ssh docs)
10
11
 
11
12
  == More Info
12
13
 
@@ -23,8 +24,11 @@ NOTE: Rudy is not ready for general consumption. Come back in Q2 2009!
23
24
 
24
25
  == Thanks
25
26
 
26
- * The Rilli[http://rilli.com/] team, for the initial use case and support.
27
- * Alicia Eyre Vasconcelos, for the name ("H-e-l-l-o R.U.D.Y")
27
+ * The Rilli.com team -- for the initial use case, the ongoing feedback and support, and the good times!
28
+ * Adam Bognar
29
+ * Andrew Simpson
30
+ * Caleb Buxton
31
+ * Colin Brumelle
28
32
 
29
33
 
30
34
  == License
data/bin/rudy CHANGED
@@ -4,348 +4,171 @@
4
4
  #
5
5
  # See rudy -h for usage
6
6
  #
7
- # AWS commands need the access identifiers. If you don't want
8
- # to include them as arguments, you can set the following variables
9
- # in your environment (replace **** with the literal value):
10
- #
11
-
12
- #
13
- # No Ruby 1.9.1 support. Only 1.8.x for now :[
14
- unless RUBY_VERSION < "1.9"
15
- puts "Sorry! We're using the right_aws gem and it doesn't support Ruby 1.9 yet."
16
- exit 1
17
- end
18
7
 
19
- RUDY_HOME = File.join(File.dirname(__FILE__))
20
- RUDY_LIB = File.join(RUDY_HOME, '..', 'lib')
8
+ RUDY_HOME = File.join(File.dirname(__FILE__), '..')
9
+ RUDY_LIB = File.join(RUDY_HOME, 'lib')
21
10
  $:.unshift RUDY_LIB # Put our local lib in first place
22
11
 
23
- require 'rubygems'
24
- require 'openssl'
25
-
12
+ require 'rubygems' if RUBY_VERSION < "1.9"
13
+ require 'date'
26
14
  require 'drydock'
27
- require 'rudy'
28
15
  extend Drydock
29
16
 
30
-
31
-
32
- default :commands
33
-
34
-
35
- global_usage "rudy [global options] COMMAND [command options]"
36
- global_option :A, :access_key, "AWS Access Key", String
37
- global_option :S, :secret_key, "AWS Secret Access Key", String
38
- global_option :R, :region, String, "Connect to a specific EC2 region (default: #{Rudy::DEFAULT_REGION})"
39
-
40
- #global_option :z, :zone, String, "Connect to a specific EC2 zone (default: #{Rudy::DEFAULT_ZONE})"
41
- global_option :e, :environment, String, "Connect to the specified environment (default: #{Rudy::DEFAULT_ENVIRONMENT})"
42
- global_option :r, :role, String, "Connect to a machine with the specified role (defalt: #{Rudy::DEFAULT_ROLE})"
43
- global_option :p, :position, String, "Position in the machine in its group (default: #{Rudy::DEFAULT_POSITION})"
44
-
45
- global_option :u, :user, String, "Provide a username (default: #{Rudy::DEFAULT_USER})"
46
-
47
- #global_option :c, :config, String, "Specify the config file to read (default: #{Rudy::RUDY_CONFIG})"
48
-
49
-
50
- global_option :V, :version, "Display version number" do
51
- puts "Rudy version: #{Rudy::VERSION}"
52
- exit 0
53
- end
54
- global_option :v, :verbose, "Increase verbosity of output (i.e. -v or -vv or -vvv)" do
17
+ project "Rudy" # This also runs require 'ruby'
18
+
19
+ global :A, :accesskey, String, "AWS Access Key"
20
+ global :S, :secretkey, String, "AWS Secret Access Key"
21
+ #global :R, :region, String, "Connect to a specific EC2 region (ie: #{Rudy::DEFAULT_REGION})"
22
+ global :f, :config, String, "Specify another configuration file to read (ie: #{Rudy::RUDY_CONFIG_FILE})"
23
+ global :z, :zone, String, "Connect to a specific EC2 zone (ie: #{Rudy::DEFAULT_ZONE})"
24
+ global :e, :environment, String, "Connect to the specified environment (ie: #{Rudy::DEFAULT_ENVIRONMENT})"
25
+ global :r, :role, String, "Connect to a machine with the specified role (ie: #{Rudy::DEFAULT_ROLE})"
26
+ global :p, :position, String, "Position in the machine in its group (ie: #{Rudy::DEFAULT_POSITION})"
27
+ global :u, :user, String, "Provide a username (ie: #{Rudy::DEFAULT_USER})"
28
+ global :q, :quiet, "Run with less output"
29
+ global :v, :verbose, "Increase verbosity of output (i.e. -v or -vv or -vvv)" do
55
30
  @verbose ||= 0
56
31
  @verbose += 1
57
32
  end
58
- global_option :q, :quiet, "Run with less output"
59
-
60
- command :commands => Rudy::Command::Metadata do |obj|
61
- obj.print_header
62
-
63
- puts "Rudy can do all of these things:", ""
64
- command_names.sort.each do |cmd|
65
- puts " %16s" % cmd
66
- end
67
- puts
68
- puts "Try: rudy -h OR rudy COMMAND -h"
69
- puts
33
+ global :V, :version, "Display version number" do
34
+ puts "Rudy version: #{Rudy::VERSION}"
35
+ exit 0
70
36
  end
71
37
 
72
- debug :off
38
+ #desc "Run this the first time you use Rudy (it's immutable so running it again does no harm)."
39
+ #command :setup => Rudy::Command::Metadata
73
40
 
74
- usage "rudy init"
75
- command :init => Rudy::Command::Metadata do |obj|
76
- obj.setup
77
- end
78
41
 
79
- usage "rudy info"
80
- command :info => Rudy::Command::Metadata do |obj|
81
- obj.info
82
- end
42
+ # ------------------------------------ RUDY INFO COMMANDS --------
43
+ # ------------------------------------------------------------------
83
44
 
84
- option :a, :all, "Display config settings for all machines"
85
- option :d, :defaults, "Display the default value for the supplied parameter"
86
- usage "rudy [-f config-file] config [param-name]"
87
- command :config => Rudy::Command::Environment do |obj, argv|
88
- obj.config(argv.first)
89
- end
45
+ #usage "rudy info"
46
+ #desc "Displays info about the current Rudy configuration"
47
+ #command :info => Rudy::Command::Metadata
90
48
 
49
+ usage "rudy [-f config-file] config [param-name]"
50
+ desc "Check Rudy configuration."
51
+ option :l, :all, "Display config settings for all machines"
52
+ option :d, :defaults, "Display the default value for the supplied parameter"
53
+ argv :name
54
+ command :config => Rudy::Command::Config
91
55
 
56
+ usage "rudy myaddress [-i] [-e]"
57
+ desc "Displays you current internal and external IP addresses"
92
58
  option :e, :external, "Display only external IP address"
93
59
  option :i, :internal, "Display only internal IP address"
94
- usage "rudy myaddress [-i] [-e]"
95
60
  command :myaddress do |obj|
96
- ea = Rudy::Utils::external_ip_address
97
- ia = Rudy::Utils::internal_ip_address
98
- puts "%10s: %s" % ['Internal', ia] unless obj.external && !obj.internal
99
- puts "%10s: %s" % ['External', ea] unless obj.internal && !obj.external
100
- end
101
-
102
-
103
- option :D, :destroy, "Destroy all metadata stored in SimpleDB"
104
- option :u, :update, "Update the role or environment metadata for the given instance-IDs"
105
- usage "rudy [global options] metadata instance-ID"
106
- command :metadata => Rudy::Command::Metadata do |obj, argv|
107
- obj.print_header
108
-
109
- if obj.update
110
- raise "No instance ID!" if argv.empty?
111
- raise "Nothing to change (see global options -r or -e)" unless obj.role || obj.environment
112
- obj.update_metadata(argv.first)
113
- elsif obj.destroy
114
- exit unless are_you_sure?
115
- obj.destroy_metadata
116
- else
117
- obj.print_metadata(argv.first)
118
- end
119
- end
120
-
121
-
122
- option :i, :instance, String, "Instance ID to associate the id"
123
- option :A, :associate, "Associate an address to a running instance"
124
- usage "rudy [global options] addresses [-A -i instance ID] [address]"
125
- command :addresses => Rudy::Command::Addresses do |obj, argv|
126
- obj.print_header
127
-
128
- if obj.associate
129
- obj.associate_address(argv.first)
61
+ ea = Rudy::Utils::external_ip_address || ''
62
+ ia = Rudy::Utils::internal_ip_address || ''
63
+ if obj.global.quiet
64
+ puts ia unless obj.option.external && !obj.option.internal
65
+ puts ea unless obj.option.internal && !obj.option.external
130
66
  else
131
- obj.print_addresses
132
- end
133
- end
134
-
135
-
136
-
137
- option :p, :print, "Only print the SSH command, don't connect"
138
- usage "rudy [-e env] [-u user] connect [-p]"
139
- command :connect => Rudy::Command::Environment do |obj|
140
- capture(:stderr) do
141
- obj.print_header
142
- obj.connect
67
+ puts "%10s: %s" % ['Internal', ia] unless obj.option.external && !obj.option.internal
68
+ puts "%10s: %s" % ['External', ea] unless obj.option.internal && !obj.option.external
143
69
  end
144
70
  end
145
71
 
146
72
 
147
- option :r, :remote, "Copy FROM the remote machine to the local machine"
148
- option :p, :print, "Only print the SSH command, don't connect"
149
- usage "rudy [-e env] [-u user] copy [-p] -r [from path] [to path]"
150
- command :copy => Rudy::Command::Environment do |obj, argv|
151
- capture(:stderr) do
152
- obj.print_header
153
- raise "No path specified (rudy copy FROM-PATH [FROM-PATH ...] TO-PATH)" unless argv.size >= 2
154
- obj.copy(argv)
155
- end
156
- end
157
73
 
74
+ # ----------------------------- RUDY MAINTENANCE COMMANDS --------
75
+ # ------------------------------------------------------------------
158
76
 
159
- option :all, "Display all disk definitions"
77
+ usage "#{$/} [global options] disks [-C -p path -d device -s size] [-A] [-D] [disk name]"
78
+ desc "Manage Disks"
79
+ option :l, :all, "Display all disk definitions"
160
80
  option :p, :path, String, "The filesystem path to use as the mount point"
161
81
  option :d, :device, String, "The device id (default: /dev/sdh)"
162
82
  option :s, :size, Integer, "The size of disk (in GB)"
163
- option :C, :create, "Create a disk definition"
164
- option :D, :destroy, "Destroy a disk definition"
165
- option :A, :attach, "Attach a disk"
166
- option :N, :unattach, "Unattach a disk"
167
- usage "rudy [global options] disks [-C -p path -d device -s size] [-A] [-D] [disk name]"
168
- command :disks => Rudy::Command::Disks do |obj, argv|
169
- capture(:stderr) do
170
- obj.print_header
171
- if obj.create
172
- raise "No filesystem path specified" unless obj.path
173
- raise "No size specified" unless obj.size
174
- obj.create_disk
175
- elsif obj.destroy
176
- raise "No disk specified" if argv.empty?
177
- exit unless are_you_sure?(5)
178
- obj.destroy_disk(argv.first)
179
- elsif obj.unattach
180
- raise "No disk specified" if argv.empty?
181
- exit unless are_you_sure?(4)
182
- obj.unattach_disk(argv.first)
183
- elsif obj.attach
184
- raise "No disk specified" if argv.empty?
185
- obj.attach_disk(argv.first)
186
- else
187
- obj.print_disks
188
- end
189
- obj.print_footer
190
- end
191
- end
83
+ action :C, :create, "Create a disk definition"
84
+ action :D, :destroy, "Destroy a disk definition"
85
+ action :A, :attach, "Attach a disk"
86
+ action :N, :unattach, "Unattach a disk"
87
+ argv :diskname
88
+ command :disk => Rudy::Command::Disks
192
89
 
193
- option :s, :snapshot, String, "Create a backup entry from an existing snapshot"
194
- option :Z, :synchronize, "Check for and delete backup metadata with no snapshot. DOES NOT delete snapshots."
195
- #option :T, :tidy, "Tidy existing backups"
196
- option :D, :destroy, "Destroy a backup"
197
- option :C, :create, "Create a backup"
198
- usage "rudy [global options] backups [-C] [disk name]"
199
- command :backups => Rudy::Command::Disks do |obj, argv|
200
- capture(:stderr) do
201
- obj.print_header
202
- if obj.create
203
- obj.create_backup(argv.first)
204
- elsif obj.synchronize
205
- unless argv.empty?
206
- puts "The disk you specified will be ignored."
207
- argv.clear
208
- end
209
- obj.sync_backups
210
- elsif obj.destroy
211
- raise "No backup specified" if argv.empty?
212
- #exit unless are_you_sure?
213
- obj.destroy_backup(argv.first)
214
- else
215
- obj.print_backups
216
- end
217
- end
218
- end
219
90
 
91
+ usage "rudy [global options] backups [-C] [disk name]"
92
+ desc "Manage Backups"
93
+ option :s, :snapshot, String, "Create a backup entry from an existing snapshot"
94
+ action :Z, :sync, "Check for and delete backup metadata with no snapshot. DOES NOT delete snapshots."
95
+ #action :T, :tidy, "Tidy existing backups"
96
+ action :D, :destroy, "Destroy a backup and DELETE its snapshots."
97
+ action :C, :create, "Create a backup"
98
+ argv :disk
99
+ command :'backup' => Rudy::Command::Backups
100
+ command_alias :backup, :bu
220
101
 
221
- option :D, :destroy, "Destroy a volume"
222
- command :volumes => Rudy::Command::Volumes do |obj, argv|
223
- capture(:stderr) do
224
- obj.print_header
225
-
226
- if obj.destroy
227
- exit unless are_you_sure? 4
228
- obj.destroy_volume(argv.first)
229
- else
230
- obj.print_volumes
231
- end
232
- end
233
- end
234
102
 
235
- option :all, "Display all instances"
236
- option :a, :address, String, "Amazon elastic IP"
237
- option :i, :image, String, "Amazon machine image ID (ami)"
238
- option :v, :volume, String, "Amazon volume ID"
239
- option :D, :destroy, "Destroy the given instance IDs. All data will be lost!"
240
- option :S, :start, "Start an instance"
241
- usage "rudy [global options] instances [-D] [-S -i image ID] [instance ID OR group name]"
242
- command :instances => Rudy::Command::Instances do |obj, argv|
243
- capture(:stderr) do
244
- obj.print_header
245
- if obj.destroy
246
- exit unless are_you_sure?
247
- obj.destroy_instances(argv.first)
248
- elsif obj.start
249
- exit unless are_you_sure?
250
- obj.start_instance
251
- else
252
- obj.print_instances(argv.first)
253
- end
254
- obj.print_footer
255
- end
256
- end
103
+ usage "rudy [global options] metadata instance-ID"
104
+ desc "Display Rudy metadata."
105
+ command :metadata => Rudy::Command::Metadata
106
+ command_alias :metadata, :md
257
107
 
258
108
 
259
- option :a, :account, String, "Your Amazon Account Number"
260
- option :i, :image_name, String, "The name of the image"
261
- option :b, :bucket_name, String, "The name of the bucket that will store the image"
262
- option :C, :create, "Create an image"
263
- option :D, :destroy, "Deregister an image (currently _does not_ remove images files from S3)"
264
- usage "rudy images [-C -i name -b bucket -a account] [-D AMI-ID]"
265
- command :images => Rudy::Command::Images do |obj, argv|
266
- capture(:stderr) do
267
- obj.print_header
268
-
269
- if obj.create
270
- puts "Make sure the machine is clean. I don't want archive no crud!"
271
- exit unless are_you_sure?
272
- obj.create_image
273
-
274
- elsif obj.destroy
275
- obj.deregister(argv.first)
276
-
277
- else
278
- obj.print_images
279
- end
280
-
281
- end
282
- end
109
+ desc "Machine Group Status"
110
+ command :status => Rudy::Command::Machines
283
111
 
284
112
 
113
+ #desc "Update a Machine Group with the current version of Rudy"
114
+ #command :update => Rudy::Command::Machines
285
115
 
286
- command :stage => Rudy::Command::Stage do |obj|
287
- capture(:stderr) do
288
- obj.print_header
289
-
290
- raise "No SCM defined. Set RUDY_SVN_BASE or RUDY_GIT_BASE." unless obj.scm
291
-
292
- exit unless are_you_sure?
293
- obj.push_to_stage
294
- end
295
- end
296
116
 
117
+ usage "rudy [-e env] [-u user] connect [-p] [cmd]"
118
+ desc "Open an SSH connection"
119
+ option :p, :print, "Only print the SSH command, don't connect"
120
+ argv :cmd
121
+ command :connect => Rudy::Command::Environment
122
+ command_alias :connect, :ssh
297
123
 
124
+ usage "rudy [-e env] [-u user] copy [-p] -r [from path] [to path]"
125
+ desc "Copy files to or from machines. NOTE: You must use quotes when using a tilda for your remote dir ('~/')."
126
+ option :r, :remote, "Copy FROM the remote machine to the local machine"
127
+ option :p, :print, "Only print the SSH command, don't connect"
128
+ argv :from, :to
129
+ command :copy => Rudy::Command::Environment
130
+ command_alias :copy, :scp
131
+ command_alias :copy, :upload
132
+ command_alias :copy, :download
298
133
 
299
134
 
300
- option :all, "Display all security groups"
301
- option :r, :protocols, Array, "Comma-separated list of protocols. One of: tcp (default), udp, icmp"
302
- option :p, :ports, Array, "List of comma-separated ports to authorize (default: 22,80,443)"
303
- option :a, :addresses, Array, "List of comma-separated IP addresses to authorize (default: your external IP)"
304
- option :C, :create, "Create a security group"
305
- option :D, :destroy, "Destroy a security group"
306
- option :M, :modify, "Modify a security group"
307
- usage "rudy [global options] groups [-C] [-a IP addresses] [-p ports] [group name]"
308
- command :groups => Rudy::Command::Groups do |obj, argv|
309
- capture(:stderr) do
310
- obj.print_header
311
-
312
- if obj.create
313
- obj.create_group(argv.first)
314
-
315
- elsif obj.modify
316
- obj.modify_group(argv.first)
317
-
318
- elsif obj.destroy
319
- exit unless are_you_sure?
320
- obj.destroy_group(argv.first)
321
-
322
- else
323
- obj.print_groups(argv.first)
324
- end
325
- end
326
- end
135
+ # -------------------------------- RUDY ROUTINES COMMANDS --------
136
+ # ------------------------------------------------------------------
327
137
 
138
+ desc "Shutdown a Machine Group"
139
+ command :shutdown => Rudy::Command::Machines
328
140
 
329
- __END__
141
+ desc "Start a Machine Group"
142
+ command :startup => Rudy::Command::Machines
143
+ command_alias :startup, :start
330
144
 
331
- # Create the SimpleDB domain for storing metadata. Check environment variables.
332
- rudy init
333
- rudy create-group -a address -i ami-1111111 -v vol-2222222
145
+ desc "Restart a Machine Group"
146
+ command :restart => Rudy::Command::Machines
334
147
 
335
- # Connect to stage-app-01 as root
336
- rudy --user root connect
148
+ desc "Release to a machine group"
149
+ option :s, :switch, "Switch to the release branch/tag"
150
+ option :m, :msg, String, "A short release note"
151
+ command :release => Rudy::Command::Release
337
152
 
338
- # Zone, environment, role and position are implied.
339
- rudy disks -C -p /rilli/app -d /dev/sdh -s 100
340
- rudy disks -D disk-us-east-1b-stage-app-01-rilli-db222
153
+ desc "Update the release currently running in a machine group"
154
+ command :rerelease => Rudy::Command::Release
155
+ command_alias :rerelease, :rere
341
156
 
342
- # Create an image from an existing instance
343
- rudy -e prod images -C -b rilli-ami-us -i rilli-app-32-r3
157
+ #desc "Deploy disk snapshots from one machine to another"
158
+ #command :deploy => Rudy::Command::Deploy
344
159
 
345
- # Create an instance
346
- rudy -e prod instances -S -i ami-11111
347
160
 
348
161
 
349
- rudy release
350
162
 
163
+ # ------------------------------------------- UGLY STUFFS --------
164
+ # ------------------------------------------------------------------
165
+ debug :on
166
+ capture :stderr
167
+ before do
168
+ @start = Time.now
169
+ end
170
+ after do
171
+ @elapsed = Time.now - @start
172
+ puts $/, "Elapsed: %.2f seconds" % @elapsed.to_f if @elapsed > 0.1
173
+ end
351
174