solutious-rudy 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/CHANGES.txt +40 -16
  2. data/README.rdoc +6 -6
  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 +48 -38
  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 +173 -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 +15 -8
  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 +13 -6
  84. data/lib/rudy/cli/status.rb +0 -60
@@ -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
@@ -200,15 +209,20 @@ module Rudy
200
209
  end
201
210
 
202
211
  # Options to be sent to Rye::Box
203
- 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
212
+ rye_opts = { :user => current_machine_user, :keys => [], :debug => nil }
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
- rye_opts[:keys] = pkey
218
+ rye_opts[:keys] << pkey
210
219
  end
211
220
 
221
+ local_keys = Rye.keys
222
+ rye_opts[:keys] += local_keys if local_keys.is_a?(Array)
223
+
224
+ puts "# SSH OPTS", rye_opts.to_yaml if @@global.verbose > 3
225
+
212
226
  # The user specified a command to run. We won't create an interactive
213
227
  # session so we need to prepare the command and its arguments
214
228
  if @argv.first
@@ -225,12 +239,8 @@ module Rudy
225
239
  end
226
240
 
227
241
  checked = false
228
- lt = Rudy::Machines.list
229
- unless lt
230
- puts "No machines running in #{current_machine_group}"
231
- return
232
- end
233
-
242
+ lt = get_machines
243
+
234
244
  rset = Rye::Set.new(current_machine_group, :parallel => @global.parallel)
235
245
  lt.each do |machine|
236
246
  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
 
@@ -177,7 +177,6 @@ class Rudy::Config
177
177
  chill :xremote
178
178
 
179
179
  forced_hash :network
180
- chill :network
181
180
 
182
181
  # Startup, Shutdown, Reboot routines
183
182
  forced_hash :before_local
data/lib/rudy/disks.rb CHANGED
@@ -21,5 +21,9 @@ module Rudy
21
21
  Rudy::Disk.from_hash h
22
22
  end
23
23
 
24
+ def exists?(path)
25
+ !get(path).nil?
26
+ end
27
+
24
28
  end
25
29
  end
data/lib/rudy/global.rb CHANGED
@@ -70,7 +70,7 @@ module Rudy
70
70
  # value from the defaults config.
71
71
  # WARNING: Don't add bucket either or any machines configuration param
72
72
  # TODO: investigate removing this apply_config method
73
- %w[region zone environment role position
73
+ %w[region zone environment role position bucket
74
74
  localhost nocolor quiet auto force parallel].each do |name|
75
75
  curval, defval = self.send(name), config.defaults.send(name)
76
76
  if curval.nil? && !defval.nil?
data/lib/rudy/huxtable.rb CHANGED
@@ -177,8 +177,8 @@ module Rudy
177
177
  end
178
178
 
179
179
  def current_machine_address(position='01')
180
- raise NoConfig unless @@config
181
- raise NoMachinesConfig unless @@config.machines
180
+ #raise NoConfig unless @@config
181
+ #raise NoMachinesConfig unless @@config.machines
182
182
  raise "Position cannot be nil" if position.nil?
183
183
  addresses = [fetch_machine_param(:addresses)].flatten.compact
184
184
  addresses[position.to_i-1]
@@ -275,7 +275,7 @@ module Rudy
275
275
  end
276
276
  disks.each_pair do |path, props|
277
277
  unless disk_defs.has_key?(path)
278
- li "#{path} is not defined. Check your #{action} machines config.".color(:red)
278
+ li "#{path} is not defined. Check your machines config.".color(:red)
279
279
  routine.disks[raction].delete(path)
280
280
  next
281
281
  end
@@ -288,6 +288,12 @@ module Rudy
288
288
  routine
289
289
  end
290
290
 
291
+ def self.generate_rudy_command(name, *args)
292
+ cmd = "rudy "
293
+ cmd << "-C " << @@global.config.join(' -C ') if @@global.config
294
+ "#{cmd} #{name} " << args.join(' ')
295
+ end
296
+
291
297
  # Is +action+ a valid routine for the current machine group?
292
298
  def valid_routine?(action)
293
299
  !fetch_routine_config(action).nil?
data/lib/rudy/machines.rb CHANGED
@@ -55,7 +55,7 @@ module Rudy
55
55
 
56
56
  def restart
57
57
  group = list
58
- raise MachineGroupNotRunning, current_group_name if group.nil?
58
+ raise MachineGroupNotRunning, current_machine_group if group.nil?
59
59
  group.each do |inst|
60
60
  inst.restart
61
61
  end
data/lib/rudy/metadata.rb CHANGED
@@ -106,11 +106,14 @@ module Rudy
106
106
  criteria
107
107
  end
108
108
 
109
+
110
+ # These methods are common to all plural metadata classes:
111
+ # Rudy::Machines, Rudy::Disks, Rudy::Backups, etc...
112
+ #
109
113
  module ClassMethods
110
114
  extend self
111
115
  extend Rudy::Huxtable
112
116
 
113
- # TODO: MOVE TO Rudy:Disks etc...
114
117
  def list(fields={}, less=[], &block)
115
118
  fields = Rudy::Metadata.build_criteria self::RTYPE, fields, less
116
119
  records_raw, records = Rudy::Metadata.select(fields), []
@@ -67,8 +67,8 @@ module Rudy
67
67
  @second = @created.sec.to_s.rjust(2, '0')
68
68
  end
69
69
 
70
- def to_s(with_titles=true)
71
- "%s; %s" % [self.name, self.to_hash.inspect]
70
+ def to_s(*args)
71
+ [self.name.bright, self.snapid, self.volid, self.size, self.fstype].join '; '
72
72
  end
73
73
 
74
74
  def name
@@ -16,6 +16,9 @@ module Rudy
16
16
  field :size
17
17
  field :fstype
18
18
 
19
+ field :name # Windows, used for label
20
+ field :index # Windows, used for diskpart
21
+
19
22
  #field :backups => Array
20
23
 
21
24
  # Is the associated volume formatted? One of: true, false
@@ -45,7 +48,7 @@ module Rudy
45
48
 
46
49
  opts = {
47
50
  :size => 1,
48
- :device => '/dev/sdh'
51
+ :device => current_machine_os.to_s == 'windows' ? DEFAULT_WINDOWS_DEVICE : DEFAULT_LINUX_DEVICE
49
52
  }.merge opts
50
53
 
51
54
  super Rudy::Disks::RTYPE, opts # Rudy::Metadata#initialize
@@ -68,8 +71,8 @@ module Rudy
68
71
  @mounted = (@mounted == "true") unless @mounted.is_a?(TrueClass)
69
72
  end
70
73
 
71
- def to_s(with_titles=true)
72
- self.name
74
+ def to_s(*args)
75
+ [self.name.bright, self.volid, self.size, self.fstype].join '; '
73
76
  end
74
77
 
75
78
  def name
@@ -83,7 +86,7 @@ module Rudy
83
86
  end
84
87
 
85
88
  def create(size=nil, zone=nil, snapshot=nil)
86
- raise DuplicateRecord, self.name if exists?
89
+ raise DuplicateRecord, self.name if exists? && !@@global.force
87
90
  vol = Rudy::AWS::EC2::Volumes.create(size || @size, zone || @zone, snapshot)
88
91
  #vol = Rudy::AWS::EC2::Volumes.list(:available).first # debugging
89
92
  @volid, @raw = vol.awsid, true