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.
Files changed (99) hide show
  1. data/CHANGES.txt +8 -9
  2. data/README.rdoc +48 -7
  3. data/Rakefile +102 -7
  4. data/Rudyfile +28 -0
  5. data/bin/ird +162 -0
  6. data/bin/rudy +287 -93
  7. data/lib/annoy.rb +227 -0
  8. data/lib/aws_sdb/service.rb +1 -1
  9. data/lib/console.rb +20 -4
  10. data/lib/escape.rb +305 -0
  11. data/lib/rudy.rb +265 -125
  12. data/lib/rudy/aws.rb +61 -26
  13. data/lib/rudy/aws/ec2.rb +20 -296
  14. data/lib/rudy/aws/ec2/address.rb +121 -0
  15. data/lib/rudy/aws/ec2/group.rb +241 -0
  16. data/lib/rudy/aws/ec2/image.rb +46 -0
  17. data/lib/rudy/aws/ec2/instance.rb +407 -0
  18. data/lib/rudy/aws/ec2/keypair.rb +92 -0
  19. data/lib/rudy/aws/ec2/snapshot.rb +87 -0
  20. data/lib/rudy/aws/ec2/volume.rb +234 -0
  21. data/lib/rudy/aws/simpledb.rb +33 -15
  22. data/lib/rudy/cli.rb +142 -0
  23. data/lib/rudy/cli/addresses.rb +85 -0
  24. data/lib/rudy/cli/backups.rb +175 -0
  25. data/lib/rudy/{command → cli}/config.rb +18 -13
  26. data/lib/rudy/cli/deploy.rb +12 -0
  27. data/lib/rudy/cli/disks.rb +125 -0
  28. data/lib/rudy/cli/domains.rb +17 -0
  29. data/lib/rudy/cli/groups.rb +77 -0
  30. data/lib/rudy/{command → cli}/images.rb +18 -6
  31. data/lib/rudy/cli/instances.rb +142 -0
  32. data/lib/rudy/cli/keypairs.rb +47 -0
  33. data/lib/rudy/cli/manager.rb +51 -0
  34. data/lib/rudy/{command → cli}/release.rb +10 -10
  35. data/lib/rudy/cli/routines.rb +80 -0
  36. data/lib/rudy/cli/volumes.rb +121 -0
  37. data/lib/rudy/command/addresses.rb +62 -39
  38. data/lib/rudy/command/backups.rb +60 -170
  39. data/lib/rudy/command/disks-old.rb +322 -0
  40. data/lib/rudy/command/disks.rb +5 -209
  41. data/lib/rudy/command/domains.rb +34 -0
  42. data/lib/rudy/command/groups.rb +105 -48
  43. data/lib/rudy/command/instances.rb +263 -70
  44. data/lib/rudy/command/keypairs.rb +149 -0
  45. data/lib/rudy/command/manager.rb +65 -0
  46. data/lib/rudy/command/volumes.rb +110 -49
  47. data/lib/rudy/config.rb +90 -70
  48. data/lib/rudy/config/objects.rb +67 -0
  49. data/lib/rudy/huxtable.rb +253 -0
  50. data/lib/rudy/metadata/backup.rb +23 -48
  51. data/lib/rudy/metadata/disk.rb +79 -68
  52. data/lib/rudy/metadata/machine.rb +34 -0
  53. data/lib/rudy/routines.rb +54 -0
  54. data/lib/rudy/routines/disk_handler.rb +190 -0
  55. data/lib/rudy/routines/release.rb +15 -0
  56. data/lib/rudy/routines/script_runner.rb +65 -0
  57. data/lib/rudy/routines/shutdown.rb +42 -0
  58. data/lib/rudy/routines/startup.rb +48 -0
  59. data/lib/rudy/utils.rb +57 -2
  60. data/lib/storable.rb +11 -5
  61. data/lib/sysinfo.rb +274 -0
  62. data/rudy.gemspec +84 -20
  63. data/support/randomize-root-password +45 -0
  64. data/support/rudy-ec2-startup +5 -5
  65. data/support/update-ec2-ami-tools +20 -0
  66. data/test/05_config/00_setup_test.rb +24 -0
  67. data/test/05_config/30_machines_test.rb +69 -0
  68. data/test/20_sdb/00_setup_test.rb +31 -0
  69. data/test/20_sdb/10_domains_test.rb +113 -0
  70. data/test/25_ec2/00_setup_test.rb +34 -0
  71. data/test/25_ec2/10_keypairs_test.rb +33 -0
  72. data/test/25_ec2/20_groups_test.rb +139 -0
  73. data/test/25_ec2/30_addresses_test.rb +35 -0
  74. data/test/25_ec2/40_volumes_test.rb +46 -0
  75. data/test/25_ec2/50_snapshots_test.rb +69 -0
  76. data/test/26_ec2_instances/00_setup_test.rb +33 -0
  77. data/test/26_ec2_instances/10_instances_test.rb +81 -0
  78. data/test/26_ec2_instances/50_images_test.rb +13 -0
  79. data/test/30_sdb_metadata/00_setup_test.rb +28 -0
  80. data/test/30_sdb_metadata/10_disks_test.rb +99 -0
  81. data/test/30_sdb_metadata/20_backups_test.rb +102 -0
  82. data/test/50_commands/00_setup_test.rb +11 -0
  83. data/test/50_commands/10_keypairs_test.rb +79 -0
  84. data/test/50_commands/20_groups_test.rb +77 -0
  85. data/test/50_commands/40_volumes_test.rb +55 -0
  86. data/test/50_commands/50_instances_test.rb +110 -0
  87. data/test/coverage.txt +51 -0
  88. data/test/helper.rb +35 -0
  89. data/tryouts/disks.rb +55 -0
  90. data/tryouts/nested_methods.rb +36 -0
  91. data/tryouts/session_tryout.rb +48 -0
  92. metadata +94 -25
  93. data/bin/rudy-ec2 +0 -108
  94. data/lib/rudy/command/base.rb +0 -839
  95. data/lib/rudy/command/deploy.rb +0 -12
  96. data/lib/rudy/command/environment.rb +0 -74
  97. data/lib/rudy/command/machines.rb +0 -170
  98. data/lib/rudy/command/metadata.rb +0 -41
  99. data/lib/rudy/metadata.rb +0 -26
@@ -0,0 +1,12 @@
1
+
2
+
3
+
4
+
5
+ module Rudy
6
+ module CLI
7
+ class Deploy < Rudy::CLI::Base
8
+
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,125 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class Disks < Rudy::CLI::Base
6
+
7
+ def disk
8
+ puts "Disks".bright
9
+ opts = {}
10
+ [:all, :path, :device, :size].each do |v|
11
+ opts[v] = @option.send(v) if @option.respond_to?(v)
12
+ end
13
+ if @argv.diskname
14
+ key = @argv.diskname =~ /^disk-/ ? :name : :path
15
+ opts[key] = @argv.diskname
16
+ end
17
+
18
+ rdisks = Rudy::Disks.new(:config => @config, :global => @global)
19
+ disks = rdisks.list(opts)
20
+ raise "No disks." unless disks
21
+ #rbacks = Rudy::Backups.new(:config => @config, :global => @global)
22
+ disks.each_pair do |diskid, disk|
23
+ #backups = rbacks.list_by_disk(disk, 2)
24
+ print_disk(disk)
25
+ end
26
+ end
27
+
28
+ def print_disk(disk, backups=[])
29
+ return unless disk
30
+ puts '-'*60
31
+ puts "Disk: #{disk.name.bright}"
32
+ puts disk.to_s
33
+ puts "#{backups.size} most recent backups:", backups.collect { |back| "#{back.nice_time} (#{back.awsid})" }
34
+ puts
35
+ end
36
+
37
+ def create_disk_valid?
38
+ raise "No filesystem path specified" unless @option.path
39
+ raise "No size specified" unless @option.size
40
+ raise "No device specified" unless @option.device
41
+ true
42
+ end
43
+
44
+ def create_disk
45
+ puts "Creating Disk".bright
46
+ exit unless Annoy.are_you_sure?(:low)
47
+ opts = {}
48
+ [:path, :device, :size, :group].each do |v|
49
+ opts[v] = @option.send(v) if @option.respond_to?(v)
50
+ end
51
+ opts[:id] = @option.awsid if @option.awsid
52
+ opts[:id] &&= [opts[:id]].flatten
53
+
54
+ @global.debug = true
55
+ rmachines = Rudy::Instances.new(:config => @config, :global => @global)
56
+ rmachines.list(opts).each_pair do |id,machine|
57
+ rdisks = Rudy::Disks.new(:config => @config, :global => @global)
58
+ disk = rdisks.create(machine, opts)
59
+ print_disk(disk) if disk
60
+ end
61
+ end
62
+
63
+
64
+ def destroy_disk_valid?
65
+ raise "No disk specified" unless @argv.diskname
66
+
67
+ true
68
+ end
69
+
70
+ def destroy_disk
71
+ puts "Destroying Disk".bright
72
+ exit unless Annoy.are_you_sure?(:medium)
73
+ opts = {}
74
+ if @argv.diskname
75
+ key = @argv.diskname =~ /^disk-/ ? :name : :path
76
+ opts[key] = @argv.diskname
77
+ end
78
+
79
+ # TODO: This is fucked! Store the machine info with the disk metadata.
80
+ # Get all disks that match the request and destroy them.
81
+ rmachines = Rudy::Instances.new(:config => @config, :global => @global)
82
+ rmachines.list(opts).each_pair do |id,machine|
83
+ rdisks = Rudy::Disks.new(:config => @config, :global => @global)
84
+ rdisks.destroy(machine, opts)
85
+ end
86
+
87
+ puts "Done."
88
+ end
89
+
90
+ def attach_disk_valid?
91
+ destroy_disk_valid?
92
+ raise "There are no instances running in #{machine_group}" if !@instances || @instances.empty?
93
+ true
94
+ end
95
+
96
+ def attach_disk
97
+ puts "Attaching #{name}"
98
+ switch_user("root")
99
+ exit unless Annoy.are_you_sure?(:medium)
100
+
101
+ machine = @instances.values.first # AK! Assumes single machine
102
+
103
+ execute_attach_disk(@disk, machine)
104
+
105
+ puts
106
+ ssh_command machine[:dns_name], keypairpath, @global.user, "df -h" # Display current mounts
107
+ puts
108
+
109
+ puts "Done!"
110
+ end
111
+
112
+
113
+
114
+
115
+ end
116
+ end
117
+ end
118
+
119
+
120
+ __END__
121
+
122
+
123
+
124
+
125
+
@@ -0,0 +1,17 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class Domains < Rudy::CLI::Base
6
+
7
+
8
+ def domains
9
+ puts "Domains".bright, $/
10
+
11
+ rdom = Rudy::Domains.new(:config => @config, :global => @global)
12
+ puts rdom.list
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,77 @@
1
+
2
+ #
3
+ #
4
+ module Rudy
5
+ module CLI
6
+ class Groups < Rudy::CLI::Base
7
+
8
+ def group
9
+ puts "Machine Groups".bright
10
+ opts = {}
11
+ name = @option.all ? nil : @argv.name
12
+ rudy = Rudy::Groups.new(:config => @config, :global => @global)
13
+ rudy.list(name).each do |grp|
14
+ puts '-'*60
15
+ puts grp.to_s
16
+ end
17
+ end
18
+
19
+ def destroy_group_valid?
20
+ @rgroup = Rudy::Groups.new(:config => @config, :global => @global)
21
+ raise "Group #{@rgroup.name(@argv.name)} does not exist" unless @rgroup.exists?(@argv.name)
22
+ true
23
+ end
24
+
25
+ def destroy_group
26
+ puts "Destroying Machine Group".bright
27
+ opts = {}
28
+ puts "Destroying group: #{@rgroup.name(@argv.name)}"
29
+ exit unless Annoy.are_you_sure?(:medium)
30
+
31
+ @rgroup.destroy(@argv.name)
32
+ puts "Done!"
33
+ end
34
+
35
+ def create_group
36
+ puts "Creating Machine Group".bright
37
+ opts = check_options
38
+ exit unless Annoy.are_you_sure?(:medium)
39
+ rudy = Rudy::Groups.new(:config => @config, :global => @global)
40
+ rudy.create(@argv.name, nil, opts)
41
+ rudy.list(@argv.name)
42
+ end
43
+
44
+ def revoke_group
45
+ puts "Revoke Machine Group Rule".bright
46
+ opts = check_options
47
+ exit unless Annoy.are_you_sure?(:medium)
48
+ rudy = Rudy::Groups.new(:config => @config, :global => @global)
49
+ rudy.revoke(@argv.name, opts)
50
+ rudy.list(@argv.name)
51
+ end
52
+
53
+ def authorize_group
54
+ puts "Authorize Machine Group Rule".bright
55
+ opts = check_options
56
+ exit unless Annoy.are_you_sure?(:medium)
57
+ rudy = Rudy::Groups.new(:config => @config, :global => @global)
58
+ rudy.authorize(opts)
59
+ rudy.list(opts)
60
+ end
61
+
62
+
63
+ private
64
+
65
+ def check_options
66
+ opts = {}
67
+ [:addresses, :protocols, :owner, :group, :ports].each do |opt|
68
+ opts[opt] = @option.send(opt) if @option.respond_to?(opt)
69
+ end
70
+ opts[:ports].collect! { |port| port.split(/:/) } if opts[:ports]
71
+ opts
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+
@@ -1,8 +1,8 @@
1
1
 
2
2
 
3
3
  module Rudy
4
- module Command
5
- class Images < Rudy::Command::Base
4
+ module CLI
5
+ class Images < Rudy::CLI::Base
6
6
 
7
7
 
8
8
  def images
@@ -33,7 +33,7 @@ module Rudy
33
33
 
34
34
  # ~/.rudy, /etc/motd, history -c, /etc/hosts, /var/log/rudy*
35
35
 
36
- are_you_sure?(2)
36
+ exit unless Annoy.are_you_sure?(:medium)
37
37
 
38
38
 
39
39
  machine_list = @ec2.instances.list(machine_group)
@@ -44,7 +44,7 @@ module Rudy
44
44
 
45
45
  puts "The new image will be based on #{machine_group}_01"
46
46
 
47
- @option.account ||= @config.awsinfo.account
47
+ @option.account ||= @config.accounts.aws.accountnum
48
48
 
49
49
  unless @option.account
50
50
  puts "Enter your 12 digit Amazon account number:"
@@ -71,7 +71,7 @@ module Rudy
71
71
  session.exec!("touch /root/firstrun")
72
72
  end
73
73
 
74
- puts "Starting bundling process...".att(:bright)
74
+ puts "Starting bundling process...".bright
75
75
  puts ssh_command(machine[:dns_name], keypairpath, @global.user, "ec2-bundle-vol -r i386 -p #{@option.image_name} -k /mnt/pk-*pem -c /mnt/cert*pem -u #{@option.account}", @option.print)
76
76
  puts ssh_command(machine[:dns_name], keypairpath, @global.user, "ec2-upload-bundle -b #{@option.bucket_name} -m /tmp/#{@option.image_name}.manifest.xml -a #{@global.accesskey} -s #{@global.secretkey}", @option.print)
77
77
 
@@ -83,7 +83,7 @@ module Rudy
83
83
  raise "You must supply an AMI ID (ami-XXXXXXX)" unless ami
84
84
  puts "Deregistering AMI: #{ami}"
85
85
 
86
- are_you_sure?
86
+ exit unless Annoy.are_you_sure?
87
87
 
88
88
  if @ec2.images.deregister(ami)
89
89
  puts "Done!"
@@ -93,6 +93,18 @@ module Rudy
93
93
 
94
94
  end
95
95
 
96
+
97
+ def print_image(img)
98
+ puts '-'*60
99
+ puts "Image: #{img[:aws_id].bright}"
100
+ img.each_pair do |key, value|
101
+ printf(" %22s: %s#{$/}", key, value) if value
102
+ end
103
+ puts
104
+ end
105
+
106
+
107
+
96
108
  end
97
109
  end
98
110
  end
@@ -0,0 +1,142 @@
1
+
2
+
3
+ module Rudy::CLI
4
+ class Instances < Rudy::CLI::Base
5
+
6
+ def connect
7
+ puts "Rudy Connect".bright
8
+
9
+ if @argv.cmd
10
+ @argv.cmd = [@argv.cmd].flatten.join(' ')
11
+ if @global.user.to_s == "root"
12
+ exit unless Annoy.are_you_sure?(:medium)
13
+ end
14
+ end
15
+
16
+ rudy = Rudy::Instances.new(:config => @config, :global => @global)
17
+ rudy.connect(@option.group, @argv.cmd, @option.awsid, @option.print)
18
+ end
19
+
20
+ def copy_valid?
21
+ raise "You must supply a source and a target. See rudy #{@alias} -h" unless @argv.size >= 2
22
+ raise "You cannot download and upload at the same time" if @option.download && @alias == 'upload'
23
+ true
24
+ end
25
+ def copy
26
+ puts "Rudy Copy".bright
27
+ opts = {}
28
+ opts[:group] = @option.group if @option.group
29
+ opts[:id] = @option.awsid if @option.awsid
30
+ opts[:id] &&= [opts[:id]].flatten
31
+
32
+ # Is this more clear?
33
+ @option.recursive && opts[:recursive] = true
34
+ @option.preserve && opts[:preserve] = true
35
+ @option.print && opts[:print] = true
36
+
37
+
38
+ opts[:paths] = @argv
39
+ opts[:dest] = opts[:paths].pop
40
+
41
+ opts[:task] = :download if @alias == 'download' || @option.download
42
+ opts[:task] = :upload if @alias == 'upload'
43
+ opts[:task] ||= :upload
44
+
45
+ #exit unless @option.print || Annoy.are_you_sure?(:low)
46
+
47
+ rudy = Rudy::Instances.new(:config => @config, :global => @global)
48
+ rudy.copy(opts[:group], opts[:id], opts)
49
+ end
50
+
51
+
52
+ def status
53
+ puts "Instance Status".bright
54
+ opts = {}
55
+ opts[:group] = @option.group if @option.group
56
+ opts[:state] = @option.state if @option.state
57
+
58
+ # A nil value forces the @ec2.instances.list to return all instances
59
+ if @option.all
60
+ opts[:state] = :any
61
+ opts[:group] = :any
62
+ end
63
+
64
+ opts[:id] = @argv.awsid if @argv.awsid
65
+ opts[:id] &&= [opts[:id]].flatten
66
+ rudy = Rudy::Instances.new(:config => @config, :global => @global)
67
+
68
+ lt = rudy.list(opts[:state], opts[:group], opts[:id]) do |inst|
69
+ puts '-'*60
70
+ puts "Instance: #{inst.awsid.bright} (AMI: #{inst.ami})"
71
+ puts inst.to_s
72
+ end
73
+ puts "No instances running" if !lt || lt.empty?
74
+ end
75
+ alias :instance :status
76
+
77
+ def console_valid?
78
+
79
+ @rmach = Rudy::Instances.new(:config => @config, :global => @global)
80
+ end
81
+
82
+ def console
83
+ puts "Instance Console".bright
84
+ opts = {}
85
+ opts[:group] = @option.group if @option.group
86
+ opts[:id] = @argv.awsid if @argv.awsid
87
+ opts[:id] &&= [opts[:id]].flatten
88
+
89
+ unless @rmach.any?
90
+ puts "No instances running"
91
+ return
92
+ end
93
+
94
+ console = @rmach.console(opts[:group], opts[:id])
95
+
96
+ if console
97
+ puts console
98
+ else
99
+ puts "Console output is not available"
100
+ end
101
+
102
+ end
103
+
104
+
105
+ def instance_create
106
+ puts "Create Instance".bright
107
+ opts = {}
108
+ [:group, :ami, :address, :itype, :keypair].each do |n|
109
+ opts[n] = @option.send(n) if @option.send(n)
110
+ end
111
+
112
+ rmach = Rudy::Instances.new(:config => @config, :global => @global)
113
+ # TODO: Print number of instances running. If more than 0, use Annoy.are_you_sure?
114
+ rmach.create(opts) do |inst| # Rudy::AWS::EC2::Instance objects
115
+ puts '-'*60
116
+ puts "Instance: #{inst.awsid.bright} (AMI: #{inst.ami})"
117
+ puts inst.to_s
118
+ end
119
+
120
+ end
121
+
122
+
123
+ def instance_destroy
124
+ puts "Destroy Instances".bright
125
+ opts = {}
126
+ opts[:group] = @option.group if @option.group
127
+ opts[:id] = @argv.awsid if @argv.awsid
128
+ opts[:id] &&= [opts[:id]].flatten
129
+
130
+ rmach = Rudy::Instances.new(:config => @config, :global => @global)
131
+ instances = rmach.list(:running, opts[:group], opts[:id])
132
+ raise "No instances running" if instances.nil? || instances.empty?
133
+ puts "Destroying #{instances.size} instances in #{instances.first.groups.first}"
134
+ exit unless Annoy.are_you_sure?(:low)
135
+ rmach.destroy(opts[:group], opts[:id])
136
+ puts "Done!"
137
+ end
138
+
139
+ end
140
+ end
141
+
142
+
@@ -0,0 +1,47 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class KeyPairs < Rudy::CLI::Base
6
+
7
+ def create_keypair
8
+ puts "Create KeyPairs".bright
9
+ rkey = Rudy::KeyPairs.new(:config => @config, :global => @global)
10
+ name = @argv.kpname
11
+
12
+ rkey.create(@argv.kpname, :force => false)
13
+ rkey.list.each do |kp|
14
+ puts kp.to_s
15
+ end
16
+ end
17
+
18
+
19
+ def destroy_keypair
20
+ puts "Destroy KeyPairs".bright
21
+ rkey = Rudy::KeyPairs.new(:config => @config, :global => @global)
22
+ raise "KeyPair #{rkey.name(@argv.kpname)} does not exist" unless rkey.exists?(@argv.kpname)
23
+ kp = rkey.get(@argv.kpname)
24
+ puts "Destroying keypair: #{kp.name}"
25
+ puts "NOTE: the private key file will also be deleted and you will not be able to".color(:blue)
26
+ puts "connect to instances started with this keypair.".color(:blue)
27
+ exit unless Annoy.are_you_sure?(:low)
28
+ ret = rkey.destroy(@argv.kpname)
29
+ puts ret ? "Success" : "Failed"
30
+ end
31
+
32
+ def keypair
33
+ puts "KeyPairs".bright
34
+ rkey = Rudy::KeyPairs.new(:config => @config, :global => @global)
35
+
36
+ rkey.list.each do |kp|
37
+ puts kp.to_s
38
+ end
39
+
40
+ puts "No keypairs" unless rkey.any?
41
+
42
+ end
43
+
44
+
45
+ end
46
+ end
47
+ end