rudy 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/CHANGES.txt +32 -17
  2. data/README.rdoc +74 -40
  3. data/bin/rudy +66 -10
  4. data/bin/rudy-ec2 +3 -1
  5. data/examples/authorize.rb +15 -0
  6. data/examples/gem-test.rb +11 -5
  7. data/examples/solaris.rb +35 -0
  8. data/examples/windows.rb +101 -0
  9. data/lib/rudy.rb +7 -1
  10. data/lib/rudy/aws.rb +2 -2
  11. data/lib/rudy/aws/ec2.rb +29 -22
  12. data/lib/rudy/aws/ec2/group.rb +1 -1
  13. data/lib/rudy/aws/ec2/image.rb +1 -29
  14. data/lib/rudy/aws/ec2/instance.rb +4 -32
  15. data/lib/rudy/aws/ec2/keypair.rb +1 -6
  16. data/lib/rudy/aws/ec2/snapshot.rb +2 -20
  17. data/lib/rudy/aws/ec2/volume.rb +11 -19
  18. data/lib/rudy/aws/ec2/zone.rb +1 -6
  19. data/lib/rudy/aws/sdb.rb +1 -1
  20. data/lib/rudy/cli/aws/ec2/addresses.rb +4 -10
  21. data/lib/rudy/cli/aws/ec2/groups.rb +0 -1
  22. data/lib/rudy/cli/aws/ec2/images.rb +1 -4
  23. data/lib/rudy/cli/aws/ec2/info.rb +63 -0
  24. data/lib/rudy/cli/aws/ec2/instances.rb +3 -5
  25. data/lib/rudy/cli/aws/ec2/keypairs.rb +3 -5
  26. data/lib/rudy/cli/aws/ec2/snapshots.rb +2 -6
  27. data/lib/rudy/cli/aws/ec2/zones.rb +2 -4
  28. data/lib/rudy/cli/backups.rb +20 -9
  29. data/lib/rudy/cli/base.rb +60 -3
  30. data/lib/rudy/cli/candy.rb +1 -1
  31. data/lib/rudy/cli/disks.rb +65 -7
  32. data/lib/rudy/cli/execbase.rb +0 -2
  33. data/lib/rudy/cli/images.rb +97 -0
  34. data/lib/rudy/cli/info.rb +48 -0
  35. data/lib/rudy/cli/keypairs.rb +43 -0
  36. data/lib/rudy/cli/machines.rb +41 -36
  37. data/lib/rudy/cli/networks.rb +68 -0
  38. data/lib/rudy/cli/routines.rb +3 -10
  39. data/lib/rudy/config/objects.rb +0 -1
  40. data/lib/rudy/disks.rb +4 -0
  41. data/lib/rudy/global.rb +1 -1
  42. data/lib/rudy/huxtable.rb +9 -3
  43. data/lib/rudy/machines.rb +1 -1
  44. data/lib/rudy/metadata.rb +4 -1
  45. data/lib/rudy/metadata/backup.rb +2 -2
  46. data/lib/rudy/metadata/disk.rb +7 -4
  47. data/lib/rudy/metadata/machine.rb +66 -2
  48. data/lib/rudy/routines.rb +2 -1
  49. data/lib/rudy/routines/base.rb +4 -157
  50. data/lib/rudy/routines/handlers/base.rb +6 -3
  51. data/lib/rudy/routines/handlers/disks.rb +127 -42
  52. data/lib/rudy/routines/handlers/group.rb +45 -10
  53. data/lib/rudy/routines/handlers/host.rb +16 -10
  54. data/lib/rudy/routines/handlers/keypair.rb +26 -10
  55. data/lib/rudy/routines/handlers/rye.rb +171 -0
  56. data/lib/rudy/routines/handlers/script.rb +2 -1
  57. data/lib/rudy/routines/passthrough.rb +2 -2
  58. data/lib/rudy/routines/reboot.rb +2 -2
  59. data/lib/rudy/routines/shutdown.rb +2 -2
  60. data/lib/rudy/routines/startup.rb +4 -2
  61. data/rudy.gemspec +17 -10
  62. data/tryouts/10_require_time/10_rudy_tryouts.rb +1 -1
  63. data/tryouts/12_config/20_defaults_tryouts.rb +1 -1
  64. data/tryouts/12_config/40_machines_tryouts.rb +1 -1
  65. data/tryouts/15_huxtable/20_user_tryouts.rb +1 -1
  66. data/tryouts/25_ec2/10_keypairs_tryouts.rb +1 -0
  67. data/tryouts/30_metadata/10_include_tryouts.rb +1 -1
  68. data/tryouts/30_metadata/13_object_tryouts.rb +4 -0
  69. data/tryouts/30_metadata/50_disk_tryouts.rb +4 -2
  70. data/tryouts/30_metadata/51_disk_digest_tryouts.rb +1 -1
  71. data/tryouts/30_metadata/53_disk_list_tryouts.rb +2 -1
  72. data/tryouts/30_metadata/56_disk_volume_tryouts.rb +1 -1
  73. data/tryouts/30_metadata/60_backup_tryouts.rb +4 -2
  74. data/tryouts/30_metadata/63_backup_list_tryouts.rb +1 -1
  75. data/tryouts/30_metadata/64_backup_disk_tryouts.rb +3 -1
  76. data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +1 -1
  77. data/tryouts/30_metadata/70_machine_tryouts.rb +5 -2
  78. data/tryouts/30_metadata/73_machine_list_tryouts.rb +1 -1
  79. data/tryouts/30_metadata/76_machine_instance_tryouts.rb +15 -3
  80. data/tryouts/30_metadata/77_machines_tryouts.rb +1 -1
  81. data/tryouts/40_routines/10_keypair_handler_tryouts.rb +6 -5
  82. data/tryouts/40_routines/11_group_handler_tryouts.rb +1 -1
  83. metadata +14 -7
  84. data/lib/rudy/cli/status.rb +0 -60
@@ -6,8 +6,6 @@ module Rudy::CLI
6
6
  class Base
7
7
  extend Drydock
8
8
 
9
- debug :off
10
-
11
9
  before do |obj|
12
10
  # Don't print Rudy header unless requested to
13
11
  obj.global.print_header = false if (obj.global.verbose == 0)
@@ -0,0 +1,97 @@
1
+
2
+ module Rudy
3
+ module CLI
4
+ class Images < Rudy::CLI::CommandBase
5
+
6
+ def bundle_valid?
7
+ raise "No S3 bucket provided. See rudy bundle -h" unless @@global.bucket
8
+ raise "No image name provided. See rudy bundle -h" unless @argv.name
9
+
10
+ @machines = Rudy::Machines.list
11
+ raise "No machines" if @machines.nil?
12
+
13
+ @machines = @machines.select { |m| m.windows? }
14
+ raise "No Windows machines" if @machines.nil?
15
+
16
+ true
17
+ end
18
+
19
+ def bundle
20
+
21
+ @machines.each do |m|
22
+ puts machine_separator(m.name, m.instid)
23
+
24
+ cmd = "ec2-bundle-instance"
25
+ args = [m.instid, "--region", @@global.region.to_s]
26
+ args += ["-b", @@global.bucket, "-p", @argv.name]
27
+ args += ["-o", @@global.accesskey, "-w", @@global.secretkey]
28
+ args += ["-K", @@global.pkey, "-C", @@global.cert]
29
+
30
+ # S3 returned 301 (Moved Permanently) for ACL on bucket [EU-BUCKET]
31
+ args += ["--no-bucket-setup"] if @@global.region.to_s == 'eu-west-1'
32
+
33
+ if @@global.verbose > 0
34
+ puts "Running: " << Rye.prepare_command(cmd, args), $/
35
+ end
36
+
37
+ unless @@global.quiet
38
+ puts "Bundling can take up to 60 minutes."
39
+ puts "Check the status with the following command:"
40
+ puts Rudy::Huxtable.generate_rudy_command('bundle-status').bright
41
+ puts $/, "When complete, register the image with the command:"
42
+ puts Rudy::Huxtable.generate_rudy_command('images', '-R', @argv.name).bright
43
+ end
44
+
45
+ execute_check(:medium)
46
+
47
+ ret = Rye.shell cmd, args
48
+ puts ret.stderr, ret.stdout
49
+ end
50
+ end
51
+
52
+ def bundle_status
53
+ cmd = 'ec2-describe-bundle-tasks'
54
+ args = ["--region", @@global.region.to_s]
55
+ args += ["-K", @@global.pkey, "-C", @@global.cert]
56
+
57
+ if @@global.verbose > 0
58
+ puts "Running: " << Rye.prepare_command(cmd, args), $/
59
+ end
60
+
61
+ ret = Rye.shell cmd, args
62
+ puts ret.stderr, ret.stdout
63
+
64
+ end
65
+
66
+ def register_images_valid?
67
+ raise "No S3 bucket provided. See rudy bundle -h" unless @@global.bucket
68
+ raise "No image name provided. See rudy bundle -h" unless @argv.name
69
+
70
+ true
71
+ end
72
+ def register_images
73
+ name = "#{@@global.bucket}/#{@argv.name}.manifest.xml"
74
+ puts Rudy::AWS::EC2::Images.register(name)
75
+ end
76
+
77
+ def deregister_images_valid?
78
+ unless @argv.first && Rudy::Utils.is_id?(:image, @argv.first)
79
+ raise "Must supply an AMI ID. See rudy images -h"
80
+ end
81
+ true
82
+ end
83
+ def deregister_images
84
+ execute_check(:low)
85
+ puts Rudy::AWS::EC2::Images.deregister(@argv.ami) ? "Done" : "Unknown error"
86
+ end
87
+
88
+ def images
89
+ @option.owner ||= 'self'
90
+ images = Rudy::AWS::EC2::Images.list(@option.owner, @argv) || []
91
+ print_stobjects images
92
+ end
93
+
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,48 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class Info < Rudy::CLI::CommandBase
6
+
7
+ def info
8
+ process_region @@global.region
9
+ oregions = Rudy::AWS::VALID_REGIONS - [@@global.region.to_sym]
10
+ if @option.all
11
+ oregions.each do |region|
12
+ Rudy::AWS::EC2.connect @@global.accesskey, @@global.secretkey, region
13
+ process_region region
14
+ end
15
+ else
16
+ puts $/, "Other regions: " << oregions.join(', ')
17
+ end
18
+ end
19
+
20
+
21
+ private
22
+ def process_region(region)
23
+ puts " Region: %s %30s".att(:reverse) % [region, '']
24
+ puts " Machines".bright
25
+
26
+ (get_machines(:region => region) rescue []).collect do |m|
27
+ m.refresh!
28
+ puts " " << m.to_s.noatt
29
+ end
30
+
31
+ puts " Disks".bright
32
+ (get_disks(:region => region) || []).collect do |d|
33
+ d.refresh!
34
+ puts " " << d.to_s.noatt
35
+ end
36
+
37
+ puts " Backups".bright
38
+ (get_backups(:region => region) || []).collect do |b|
39
+ b.refresh!
40
+ puts " " << b.to_s.noatt
41
+ end
42
+
43
+ puts
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,43 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class Keypairs < Rudy::CLI::CommandBase
6
+
7
+
8
+ def keypairs_add_valid?
9
+ true
10
+ end
11
+
12
+ def keypairs_add
13
+ puts current_group_name
14
+ end
15
+
16
+ def keypairs_valid?
17
+ @pkey = current_user_keypairpath
18
+ unless File.exists? @pkey
19
+ raise "No private key file for #{current_machine_user} in #{current_group_name}"
20
+ end
21
+ true
22
+ end
23
+
24
+ def keypairs
25
+ puts Rudy::AWS::EC2::Keypairs.get(current_user_keypairname)
26
+ end
27
+
28
+ def keypairs_show_valid?
29
+ keypairs_valid?
30
+ end
31
+
32
+ def keypairs_show
33
+ content = File.read(@pkey)
34
+ rkey = Rye::Key.new content
35
+ puts "# #{@pkey}"
36
+ puts content
37
+ puts rkey.public_key
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+
@@ -4,27 +4,32 @@ module Rudy
4
4
  module CLI
5
5
  class Machines < Rudy::CLI::CommandBase
6
6
 
7
-
8
7
  def machines
9
- # Rudy::Machines.list takes two optional args for adding or
10
- # removing metadata attributes to modify the select query.
11
- # When all is specified we want to find machines in every
12
- # environment and role to we remove these attributes from
13
- # the select.
14
- fields, less = {}, []
15
- less = Rudy::Metadata::COMMON_FIELDS if @option.all
16
-
17
- mlist = Rudy::Machines.list(fields, less) || []
18
- if mlist.empty?
19
- raise( NoMachines, @option.all ? nil : current_group_name)
8
+ mlist = get_machines
9
+ print_stobjects mlist
10
+ end
11
+
12
+ def machines_console
13
+ mlist = get_machines
14
+ mlist.each do |machine|
15
+ puts machine_separator(machine.name, machine.instid)
16
+ puts machine.get_console
20
17
  end
21
- mlist.each do |m|
22
- puts @@global.verbose > 0 ? m.to_yaml : "#{m.name}: #{m.dns_public}"
18
+ end
19
+
20
+ def machines_password
21
+ mlist = get_machines
22
+ mlist.each do |machine|
23
+ puts machine_separator(machine.name, machine.instid)
24
+ puts "Password for %s: %s" % [machine.dns_public, machine.get_password]
23
25
  end
26
+ Rudy::Routines::Handlers::Group.authorize rescue nil
24
27
  end
25
28
 
26
29
  def machines_wash
27
- dirt = (Rudy::Machines.list || []).select { |m| !m.instance_running? }
30
+ mlist = get_machines
31
+ dirt = mlist.select { |m| !m.instance_running? }
32
+
28
33
  if dirt.empty?
29
34
  puts "Nothing to wash in #{current_machine_group}"
30
35
  return
@@ -41,7 +46,7 @@ module Rudy
41
46
  end
42
47
 
43
48
  def associate_machines_valid?
44
- @mlist = Rudy::Machines.list || []
49
+ @mlist = get_machines
45
50
  @alist = Rudy::AWS::EC2::Addresses.list || []
46
51
  @alist_used = @alist.select { |a| a.associated? }
47
52
  @alist_unused = @alist.select { |a| !a.associated? }
@@ -118,7 +123,7 @@ module Rudy
118
123
 
119
124
 
120
125
  def disassociate_machines_valid?
121
- @mlist = Rudy::Machines.list || []
126
+ @mlist = get_machines
122
127
  @alist = Rudy::AWS::EC2::Addresses.list || []
123
128
  @alist_used = @alist.select { |a| a.associated? }
124
129
  @alist_instids = @alist_used.collect { |a| a.instid }
@@ -147,19 +152,17 @@ module Rudy
147
152
  end
148
153
 
149
154
  def update_machines
150
- fields, less = {}, []
151
- less = Rudy::Metadata::COMMON_FIELDS if @option.all
152
- mlist = Rudy::Machines.list(fields, less) || []
155
+ mlist = get_machines
153
156
  rset = Rye::Set.new(current_group_name, :parallel => @@global.parallel, :user => 'root')
154
157
  os = current_machine_os
155
158
  mlist.each do |m|
159
+ puts "Updating #{m.name}"
156
160
  m.refresh!
157
161
  rbox = Rye::Box.new(m.dns_public, :user => 'root')
158
162
  rbox.add_key user_keypairpath('root')
159
163
  rbox.nickname = m.name
160
164
  rbox.stash = m
161
165
  rset.add_boxes rbox
162
- puts "Updating metadata"
163
166
  if m.os.to_s != os.to_s
164
167
  puts "os: #{os}"
165
168
  m.os = os
@@ -167,7 +170,7 @@ module Rudy
167
170
  m.save :replace
168
171
  end
169
172
 
170
- unless os.to_s == 'win32'
173
+ unless os.to_s == 'windows'
171
174
  puts "Updating hostnames for #{current_group_name}"
172
175
  Rudy::Routines::Handlers::Host.set_hostname rset
173
176
  puts rset.hostname.flatten
@@ -176,23 +179,29 @@ module Rudy
176
179
  end
177
180
 
178
181
  def available_machines
179
- fields, less = {}, []
180
- less = Rudy::Metadata::COMMON_FIELDS if @option.all
181
- mlist = Rudy::Machines.list(fields, less) || []
182
+ mlist = get_machines
182
183
  mlist.each do |m|
183
184
  print "#{m.name}: "
184
185
  m.refresh!
186
+ port = m.windows? ? 3389 : 22
185
187
  Rudy::Utils.waiter(2, 60, STDOUT, nil, 0) {
186
- Rudy::Utils.service_available?(m.dns_public, 22)
188
+ Rudy::Utils.service_available?(m.dns_public, port)
187
189
  }
188
- available = Rudy::Utils.service_available?(m.dns_public, 22)
190
+ available = Rudy::Utils.service_available?(m.dns_public, port)
189
191
  puts available ? 'up' : 'down'
190
192
  end
191
193
 
192
194
  end
193
195
 
194
196
 
197
+ def ssh_valid?
198
+ #raise "SSH not supported on Windows" if current_machine_os.to_s == 'windows'
199
+ true
200
+ end
201
+
195
202
  def ssh
203
+
204
+
196
205
  # TODO: Give this method a good look over
197
206
  pkey = current_user_keypairpath
198
207
  unless pkey
@@ -201,9 +210,9 @@ module Rudy
201
210
 
202
211
  # Options to be sent to Rye::Box
203
212
  rye_opts = { :user => current_machine_user, :debug => nil }
204
- if pkey
205
- raise "Cannot find file #{pkey}" unless File.exists?(pkey)
206
- if Rudy.sysinfo.os != :win32 && File.stat(pkey).mode != 33152
213
+ if File.exists? pkey
214
+ #raise "Cannot find file #{pkey}" unless File.exists?(pkey)
215
+ if Rudy.sysinfo.os != :windows && File.stat(pkey).mode != 33152
207
216
  raise InsecureKeyPermissions, pkey
208
217
  end
209
218
  rye_opts[:keys] = pkey
@@ -225,12 +234,8 @@ module Rudy
225
234
  end
226
235
 
227
236
  checked = false
228
- lt = Rudy::Machines.list
229
- unless lt
230
- puts "No machines running in #{current_machine_group}"
231
- return
232
- end
233
-
237
+ lt = get_machines
238
+
234
239
  rset = Rye::Set.new(current_machine_group, :parallel => @global.parallel)
235
240
  lt.each do |machine|
236
241
  machine.refresh! # make sure we have the latest DNS info
@@ -13,6 +13,7 @@ module Rudy
13
13
 
14
14
  def update_networks
15
15
  Rudy::Routines::Handlers::Group.authorize rescue nil
16
+ networks
16
17
  end
17
18
 
18
19
  def local_networks
@@ -28,7 +29,74 @@ module Rudy
28
29
  @global.quiet = true # don't print elapsed time
29
30
  end
30
31
 
32
+
33
+ def modify_group_valid?
34
+ if @option.owner == 'self'
35
+ raise "AWS_ACCOUNT_NUMBER not set" unless @@global.accountnum
36
+ @option.owner = @@global.accountnum
37
+ end
38
+
39
+ if (@option.addresses || @option.ports) && (@option.group || @option.owner)
40
+ raise Drydock::OptError.new('', @alias, "Cannot mix group and network authorization")
41
+ end
42
+ if @option.owner && !@option.group
43
+ raise Drydock::OptError.new('', @alias, "Must provide -g with -o")
44
+ end
45
+
46
+ true
47
+ end
48
+
49
+ def revoke_networks_valid?; modify_group_valid?; end
50
+ def revoke_networks; modify_group(:revoke); end
51
+
52
+ def authorize_networks_valid?; modify_group_valid?; end
53
+ def authorize_networks; modify_group(:authorize); end
54
+
55
+ private
56
+
57
+ def modify_group(action)
58
+ group = current_group_name
59
+
60
+ opts = check_options
61
+ if (@option.group || @option.owner)
62
+ g = [opts[:owner], opts[:group]].join(':')
63
+ puts "#{action.to_s.capitalize} access to #{group.bright} from #{g.bright}"
64
+ else
65
+ print "#{action.to_s.capitalize} access to #{group.bright}"
66
+ puts " from #{opts[:addresses].join(', ').bright}"
67
+ print "on #{opts[:protocols].join(', ').bright} "
68
+ puts "ports: #{opts[:ports].map { |p| "#{p.join(' to ').bright}" }.join(', ')}"
69
+ end
70
+ execute_check(:medium)
71
+ execute_action {
72
+ if (@option.group || @option.owner)
73
+ Rudy::AWS::EC2::Groups.send("#{action.to_s}_group", group, opts[:group], opts[:owner])
74
+ else
75
+ Rudy::AWS::EC2::Groups.send(action, group, opts[:addresses], opts[:ports], opts[:protocols])
76
+ end
77
+ }
78
+ networks
79
+ end
80
+
81
+ def check_options
82
+ opts = {}
83
+ [:addresses, :protocols, :owner, :group, :ports].each do |opt|
84
+ opts[opt] = @option.send(opt) if @option.respond_to?(opt)
85
+ end
86
+ unless @option.group || @option.owner
87
+ opts[:ports].collect! { |port| port.split(/[:-]/) } if opts[:ports]
88
+ opts[:ports] ||= [[22,22],[80,80],[443,443]]
89
+ opts[:addresses] ||= [Rudy::Utils::external_ip_address]
90
+ opts[:protocols] ||= [:tcp]
91
+ else
92
+ opts[:owner] ||= @@global.accountnum
93
+ end
94
+ opts
95
+ end
96
+
31
97
  end
32
98
 
99
+
100
+
33
101
  end
34
102
  end
@@ -35,9 +35,7 @@ module Rudy; module CLI;
35
35
  def startup
36
36
  machines = @rr.execute || []
37
37
  puts $/, "The following machines are now available:" unless machines.empty?
38
- machines.each do |machine|
39
- puts machine
40
- end
38
+ print_stobjects machines, :noverbose
41
39
  end
42
40
 
43
41
  def reboot_valid?
@@ -48,9 +46,7 @@ module Rudy; module CLI;
48
46
  def reboot
49
47
  machines = @rr.execute
50
48
  puts $/, "The following machines have been restarted:"
51
- machines.each do |machine|
52
- puts machine
53
- end
49
+ print_stobjects machines, :noverbose
54
50
  end
55
51
 
56
52
  def passthrough_valid?
@@ -77,9 +73,7 @@ module Rudy; module CLI;
77
73
 
78
74
  if @global.verbose > 1 && !machines.empty?
79
75
  puts $/, "The following machines were processed:"
80
- machines.each do |machine|
81
- puts machine
82
- end
76
+ print_stobjects machines, :noverbose
83
77
  end
84
78
 
85
79
  end
@@ -109,7 +103,6 @@ module Rudy; module CLI;
109
103
  puts '%s %s ' % [machine.name.bright, machine.instid]
110
104
  end
111
105
 
112
-
113
106
  end
114
107
 
115
108