solutious-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 +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