rudy 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -1,5 +1,25 @@
1
1
  RUDY, CHANGES
2
2
 
3
+ #### 0.9.0 (TBD) ###############################
4
+
5
+ NOTE: The following changes are planned for the 0.9.0 release.
6
+
7
+ * group identifier will be changed to 'grp' from 'g'
8
+ * machine identifier will be changes to 'mach' from 'm'
9
+ * private keys are stored in ~/.ssh/
10
+ * zone is now a single letter: a, b, c, etc... The long form (us-east-1b) will set the region too.
11
+ * Disk syntax in the routines DSL will change. The DSL no longer accepts arguments, just the action (create, destroy, ...).
12
+ * Disk backups will be removed (temporarily -- probably until on of the early 1.x releases).
13
+
14
+
15
+ #### 0.8.5 (2009-06-??) ###############################
16
+
17
+ * FIXED: Bug in DiskHelper. mount method tried to attach when already attached.
18
+ * CHANGE: rudy config now displays account info (but keeps secret key hidden)
19
+ * CHANGE: defaults configuration has been removed from the default ~/.rudy/config.
20
+ It is now recommended to put it in the same place as machines, routines config.
21
+ * FIXED: Bug in addresses which prevented assigning elastic IP addresses.
22
+
3
23
 
4
24
  #### 0.8.4 (2009-06-04) ###############################
5
25
 
@@ -109,7 +129,6 @@ RUDY, CHANGES
109
129
  * ADDED: Support for arbitrary routines via passthrough
110
130
 
111
131
 
112
-
113
132
  #### 0.6.8 (2009-04-24) ###############################
114
133
 
115
134
  * CHANGE: Renamed rudy config --rudy option to --project. This was important
data/README.rdoc CHANGED
@@ -16,7 +16,13 @@ All configuration is organized into the zones, environments, and roles that you
16
16
 
17
17
  <b>See Getting-Started[http://solutious.com/products/rudy/getting-started.html] for more info.</b>
18
18
 
19
- <em>NOTE: This is a BETA release. That means Rudy's not ready for production use! See Project-Status[http://wiki.github.com/solutious/rudy/project-status].</em>
19
+
20
+ == Project Status
21
+
22
+ <em>This is a BETA release. That means Rudy's not ready for production use! See Project-Status[http://wiki.github.com/solutious/rudy/project-status].</em>
23
+
24
+ I'm currently rebuilding[http://github.com/solutious/rudy/tree/metadata-refactor] the metadata implementation. This is the part of Rudy that stores your machine, disk, and backup infoz in SimpleDB so it's pretty important! The implementation in the 0.8.4 release (and this master branch) are functional but frail so I want to re-emphasize not to use Rudy for production right now.
25
+
20
26
 
21
27
  == Configuration
22
28
 
@@ -150,12 +156,16 @@ I'm very open to contributions!
150
156
 
151
157
  == Related Projects
152
158
 
159
+ * Sprinkle -- http://github.com/crafterm/sprinkle/
160
+ * Wakame -- http://wakame.rubyforge.org/
153
161
  * Pool Party -- http://www.poolpartyrb.com/
154
162
  * Rubber -- http://github.com/wr0ngway/rubber/wikis
155
163
  * Moonshine -- http://github.com/railsmachine/moonshine/tree
156
164
  * Boto -- http://code.google.com/p/boto/
157
165
  * Fabric -- http://www.nongnu.org/fab/
158
166
 
167
+
168
+
159
169
  == License
160
170
 
161
171
  See: LICENSE.txt
data/Rudyfile CHANGED
@@ -17,11 +17,11 @@
17
17
  # it's ADDED or APPENDED depending on context. This means you can split
18
18
  # configuration across many files as you please.
19
19
  #
20
- # There are four sections: accounts, defaults, machines, commands and routines.
20
+ # There are five sections: accounts, defaults, machines, commands and routines.
21
21
  #
22
- # By convention, accounts and defaults go in ~/.rudy/config or ./.rudy/config
23
- # machines, commands and routines configuration go in ./Rudyfile or into
24
- # separate files in ./.rudy or ./config/rudy (machines.rb, commands.rb, ...)
22
+ # By convention, accounts go in ./.rudy/config or ~/.rudy/config
23
+ # machines, commands, routines, and defaults configuration go in ./Rudyfile or
24
+ # into separate files in ./.rudy or ./config/rudy (machines.rb, commands.rb, ...)
25
25
  #
26
26
 
27
27
  # --------------------------------------------------------- MACHINES --------
@@ -62,9 +62,9 @@ machines do
62
62
  end
63
63
 
64
64
  users do # Specify existing private keys per user
65
- #root do
66
- # keypair "/path/2/private-key"
67
- #end
65
+ rudy do
66
+ keypair "/path/2/private-key"
67
+ end
68
68
  end
69
69
 
70
70
  end
@@ -92,7 +92,6 @@ end
92
92
  # allow COMMAND-NAME, '/path/2/COMMAND', 'default argument', 'another arg'
93
93
  #
94
94
  commands do
95
- allow :make
96
95
  allow :gem_install, '/usr/bin/gem', 'install', :V, '--no-rdoc', '--no-ri'
97
96
  allow :apt_get, 'apt-get', :y, :q
98
97
  allow :floo, :time, 1 do
@@ -183,3 +182,18 @@ routines do
183
182
  end
184
183
  end
185
184
 
185
+
186
+ # ----------------------------------------------------------- DEFAULTS --------
187
+ # These values are used as defaults for their respective global settings. All
188
+ # non-boolean values are expected to be Symbols.
189
+ #
190
+ defaults do
191
+ region :"us-east-1"
192
+ zone :"us-east-1b"
193
+ environment :stage
194
+ role :app
195
+ user Rudy.sysinfo.user.to_sym # This will be the user running Rudy
196
+ color false # Terminal colors? true/false
197
+ yes false # Auto-confirm? true/false
198
+ end
199
+
data/bin/rudy CHANGED
@@ -36,7 +36,7 @@ class RudyCLI < Rudy::CLI::Base
36
36
  # ------------------------------------------------------------------
37
37
 
38
38
  about "View Machines"
39
- option :l, :all, "Display all machines"
39
+ option :l, :all, "Display machines for all environments and roles"
40
40
  action :W, :wash, "Wash machine metadata."
41
41
  command :machines => Rudy::CLI::Machines
42
42
  command_alias :machines, :m
@@ -48,6 +48,16 @@ class RudyCLI < Rudy::CLI::Base
48
48
  command :disks => Rudy::CLI::Disks
49
49
  command_alias :disks, :d
50
50
 
51
+ about "View raw metadata"
52
+ usage "rudy metadata"
53
+ usage "rudy metadata -l -o [disk|back|m]"
54
+ usage "rudy metadata -D object-id"
55
+ option :o, :otype, String, "Object type. One of: disk, back, m"
56
+ option :l, :all, "Display metadata for all environments and roles"
57
+ action :D, :delete, "Delete an object"
58
+ argv :oid
59
+ command :metadata => Rudy::CLI::MetaData
60
+
51
61
  about "Log in to a machine"
52
62
  command :ssh => Rudy::CLI::Machines
53
63
 
data/bin/rudy-ec2 CHANGED
@@ -184,7 +184,7 @@ module RudyCLI_EC2
184
184
  about "Amazon EC2 Volumes"
185
185
  usage "rudy-ec2 volumes"
186
186
  usage "rudy-ec2 volumes -C -s size [-d device-path]"
187
- usage "rudy-ec2 volumes -A volume-id instance-id"
187
+ usage "rudy-ec2 volumes -A -i instance-id volume-id"
188
188
  usage "rudy-ec2 volumes -N volume-id"
189
189
  usage "rudy-ec2 volumes -D volume-id"
190
190
  option :i, :instance, String, "Instance ID"
data/lib/rudy.rb CHANGED
@@ -4,8 +4,9 @@ unless defined?(RUDY_HOME)
4
4
  RUDY_LIB = File.join(File.dirname(__FILE__), '..', 'lib')
5
5
  end
6
6
 
7
- local_libs = %w{net-scp amazon-ec2 aws-s3 caesars drydock rye storable sysinfo annoy}
8
- local_libs.each { |dir| $:.unshift File.join(RUDY_HOME, '..', dir, 'lib') }
7
+ local_libs = %w{net-ssh net-scp amazon-ec2 aws-s3 caesars drydock rye storable sysinfo annoy}
8
+ #local_libs.each { |dir| $:.unshift File.join(RUDY_HOME, '..', dir, 'lib') }
9
+ #require 'rubygems'
9
10
 
10
11
  require 'digest/md5'
11
12
  require 'stringio'
@@ -38,28 +39,34 @@ module Rudy
38
39
  unless defined?(MAJOR)
39
40
  MAJOR = 0.freeze
40
41
  MINOR = 8.freeze
41
- TINY = 4.freeze
42
+ TINY = 5.freeze
42
43
  end
43
44
  def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
44
45
  def self.to_f; self.to_s.to_f; end
45
46
  end
46
47
 
47
- unless defined?(Rudy::DOMAIN) # We can assume all constants are defined
48
+ unless defined? Rudy::DOMAIN # We can assume all constants are defined
49
+
50
+ @@quiet = false
51
+ @@yes = false
52
+ @@debug = false
53
+ @@sysinfo = SysInfo.new.freeze
54
+
48
55
  # SimpleDB accepts dashes in the domain name on creation and with the query syntax.
49
56
  # However, with select syntax it says: "The specified query expression syntax is not valid"
50
57
  DOMAIN = "rudy_state".freeze
51
58
  DELIM = '-'.freeze
52
59
 
53
- CONFIG_DIR = File.join(ENV['HOME'] || ENV['USERPROFILE'], '.rudy').freeze
60
+ CONFIG_DIR = File.join(@@sysinfo.home, '.rudy').freeze
54
61
  CONFIG_FILE = File.join(Rudy::CONFIG_DIR, 'config').freeze
55
62
 
56
- DEFAULT_REGION = 'us-east-1'.freeze
57
- DEFAULT_ZONE = 'us-east-1b'.freeze
58
- DEFAULT_ENVIRONMENT = 'stage'.freeze
59
- DEFAULT_ROLE = 'app'.freeze
63
+ DEFAULT_REGION = :'us-east-1'.freeze
64
+ DEFAULT_ZONE = :'us-east-1b'.freeze
65
+ DEFAULT_ENVIRONMENT = :'stage'.freeze
66
+ DEFAULT_ROLE = :'app'.freeze
60
67
  DEFAULT_POSITION = '01'.freeze
61
68
 
62
- DEFAULT_USER = 'rudy'.freeze
69
+ DEFAULT_USER = :'rudy'.freeze
63
70
 
64
71
  DEFAULT_EC2_HOST = "ec2.amazonaws.com"
65
72
  DEFAULT_EC2_PORT = 443
@@ -86,12 +93,7 @@ module Rudy
86
93
  :dns_public => 'ec2',
87
94
  :dns_private => 'domU',
88
95
  }.freeze
89
-
90
- @@quiet = false
91
- @@yes = false
92
- @@debug = false
93
- @@sysinfo = SysInfo.new.freeze
94
-
96
+
95
97
  end
96
98
 
97
99
  def Rudy.debug?; @@debug == true; end
@@ -163,6 +165,3 @@ require 'rudy/aws' # is
163
165
  require 'rudy/metadata' # important
164
166
  require 'rudy/machines'
165
167
  require 'rudy/routines'
166
-
167
-
168
-
@@ -134,7 +134,7 @@ module Rudy::AWS
134
134
  # Returns true if the given address is assigned to the current account
135
135
  def exists?(address)
136
136
  address = address.ipaddress if address.is_a?(Rudy::AWS::EC2::Address)
137
- list do |a|
137
+ list.each do |a|
138
138
  return true if a.ipaddress == address
139
139
  end
140
140
  false
data/lib/rudy/aws/sdb.rb CHANGED
@@ -65,14 +65,15 @@ module Rudy
65
65
 
66
66
  # Takes a zipped Array or Hash of criteria.
67
67
  # Returns a string suitable for a SimpleDB Select
68
- def self.generate_select(*args)
69
- fields, domain, args = *args
70
- q = args.is_a?(Hash) ? args : Hash[*args.flatten]
68
+ def self.generate_select(fields, domain, *args)
69
+ q = args.first.is_a?(Hash)? args.first : Hash[*args.flatten]
71
70
  query = []
72
- q.each do |n,v|
71
+ q.each_pair do |n,v|
73
72
  query << "#{Rudy::AWS.escape n}='#{Rudy::AWS.escape v}'"
74
73
  end
75
- "select * from #{domain} where " << query.join(' and ')
74
+ str = "select * from #{domain} "
75
+ str << " where "<< query.join(' and ') unless query.empty?
76
+ str
76
77
  end
77
78
 
78
79
 
data/lib/rudy/cli.rb CHANGED
@@ -48,9 +48,6 @@ module Rudy
48
48
  exit 81
49
49
  end
50
50
 
51
- # And then update global again b/c some values come from @@config
52
- Rudy::Huxtable.update_global
53
-
54
51
  @@global.nocolor ? String.disable_color : String.enable_color
55
52
  @@global.yes ? Annoy.enable_skip : Annoy.disable_skip
56
53
 
@@ -103,9 +100,7 @@ module Rudy
103
100
  end
104
101
 
105
102
  def machine_separator(name, awsid)
106
- dashes = 80 - name.size #
107
- dashes = 0 if dashes < 1
108
- ('%s %-63s awsid: %s ' % [$/, name, awsid]).att(:reverse)
103
+ ('%s %-50s awsid: %s ' % [$/, name, awsid]).att(:reverse)
109
104
  end
110
105
 
111
106
  end
@@ -54,10 +54,11 @@ module Rudy
54
54
  puts conf.to_hash.send(outform) if conf
55
55
 
56
56
  else
57
- puts "# ACCOUNTS: [not displayed]" if types.delete(:accounts)
57
+ #puts "# ACCOUNTS: [not displayed]" if types.delete(:accounts)
58
58
  types.each do |conftype|
59
59
  puts "# #{conftype.to_s.upcase}"
60
60
  next unless @@config[conftype] # Nothing to output
61
+ @@config[conftype][:aws][:secretkey] = '[hidden]' if conftype == :accounts
61
62
  puts @@config[conftype].to_hash.send(outform)
62
63
  end
63
64
  end
@@ -29,7 +29,7 @@ module Rudy
29
29
  if @option.backups
30
30
  d.list_backups.each_with_index do |b, index|
31
31
  puts ' %s' % b.name
32
- break if @option.all.nil? && index >= 2 # display only 3, unless all
32
+ ##break if @option.all.nil? && index >= 2 # display only 3, unless all
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,37 @@
1
+
2
+
3
+ module Rudy
4
+ module CLI
5
+ class MetaData < Rudy::CLI::CommandBase
6
+
7
+
8
+ def metadata
9
+ more, less = [], []
10
+ less = [:environment, :role, :zone, :region] if @option.all
11
+ more += [:rtype, @option.otype] if @option.otype
12
+
13
+ rdebug = Rudy::MetaData::Debug.new
14
+ objlist = rdebug.list(more, less) || []
15
+ objlist.each do |o|
16
+ p o
17
+ end
18
+ end
19
+
20
+ def metadata_delete_valid?
21
+ raise "Must supply object ID" unless @argv.oid
22
+ true
23
+ end
24
+
25
+ def metadata_delete
26
+ rdebug = Rudy::MetaData::Debug.new
27
+ unless @@global.quiet
28
+ msg = "NOTE: This will delete only the metadata and "
29
+ msg << "not the EC2 object (volume, instance, etc...)"
30
+ puts msg
31
+ end
32
+ p rdebug.get( @argv.oid)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
data/lib/rudy/config.rb CHANGED
@@ -17,11 +17,11 @@ module Rudy
17
17
  def accounts?; self.respond_to?(:accounts) && !self[:accounts].nil?; end #a
18
18
  def defaults?; self.respond_to?(:defaults) && !self[:defaults].nil?; end #u
19
19
  def machines?; self.respond_to?(:machines) && !self[:machines].nil?; end #t
20
- def routines?; self.respond_to?(:routines) && !self[:routines].nil?; end #o
21
- def networks?; self.respond_to?(:networks) && !self[:networks].nil?; end #g
22
- def controls?; self.respond_to?(:controls) && !self[:controls].nil?; end #e
23
- def commands?; self.respond_to?(:commands) && !self[:commands].nil?; end #n
24
- def services?; self.respond_to?(:services) && !self[:services].nil?; end #!
20
+ def commands?; self.respond_to?(:commands) && !self[:commands].nil?; end #o
21
+ def routines?; self.respond_to?(:routines) && !self[:routines].nil?; end #g
22
+ #def networks?; self.respond_to?(:networks) && !self[:networks].nil?; end #e
23
+ #def controls?; self.respond_to?(:controls) && !self[:controls].nil?; end #n
24
+ #def services?; self.respond_to?(:services) && !self[:services].nil?; end #!
25
25
 
26
26
  # This method is called by Caesars::Config.refresh for every DSL
27
27
  # file that is loaded and parsed. If we want to run processing
@@ -44,6 +44,10 @@ module Rudy
44
44
  # the case. Rudy::Config::Commands knows to only raise the
45
45
  # exception one time (using a boolean flag in a class var).
46
46
  @commands.postprocess if @commands
47
+ @defaults.postprocess if @defaults
48
+
49
+ # default will be nil if non was specified. We at least want the object.
50
+ @defaults = Rudy::Config::Defaults.new if @defaults.nil?
47
51
  end
48
52
 
49
53
  def look_and_load(adhoc_path=nil)
@@ -96,16 +100,6 @@ module Rudy
96
100
  cert "~/path/2/cert-xxxx.pem"
97
101
  end
98
102
  end
99
-
100
- defaults do # Global Defaults
101
- region :"us-east-1"
102
- zone :"us-east-1b"
103
- environment :stage
104
- role :app
105
- user Rudy.sysinfo.user.to_sym
106
- color false # Terminal colors? true/false
107
- yes false # Auto-confirm? true/false
108
- end
109
103
  }
110
104
  Rudy::Utils.write_to_file(Rudy::CONFIG_FILE, rudy_config, 'w', 0600)
111
105
  end
@@ -7,11 +7,33 @@ class Rudy::Config
7
7
  end
8
8
  def message; "Error in #{@ctype}: #{@obj}"; end
9
9
  end
10
+
11
+ class Accounts < Caesars
12
+ def valid?
13
+ (!aws.nil? && !aws.accesskey.nil? && !aws.secretkey.nil?) &&
14
+ (!aws.account.empty? && !aws.accesskey.empty? && !aws.secretkey.empty?)
15
+ end
16
+ end
17
+
18
+ # Default configuration. All of the defaults can be overridden
19
+ # on the command line with global options.
20
+ class Defaults < Caesars
21
+ class DoubleDefined < Rudy::Config::Error
22
+ def message; "Check your defaults config. '#{@obj}' has been defined twice"; end
23
+ end
24
+ #
25
+ # All values should scalars
26
+ #
27
+ def postprocess
28
+ self.keys.each do |k|
29
+ next unless self[k].is_a?(Array)
30
+ raise Defaults::DoubleDefined.new(:defaults, k)
31
+ end
32
+ end
33
+ end
34
+
10
35
  class Machines < Caesars; end
11
- class Defaults < Caesars; end
12
- class Networks < Caesars; end
13
- class Controls < Caesars; end
14
- class Services < Caesars; end
36
+
15
37
  # Modify the SSH command available in routines. The default
16
38
  # set of commands is defined by Rye::Cmd (Rudy executes all
17
39
  # SSH commands via Rye).
@@ -79,7 +101,9 @@ class Rudy::Config
79
101
 
80
102
  # We can allow existing commands to be overridden but we
81
103
  # print a message to STDERR so the user knows what's up.
82
- STDERR.puts "Redefining #{cmd}" if Rye::Cmd.can?(cmd)
104
+ if Rye::Cmd.can?(cmd)
105
+ STDERR.puts "Redefining #{cmd}" #if @@global.verbose > 0
106
+ end
83
107
 
84
108
  if args.last.is_a?(Proc)
85
109
  block = args.pop
@@ -112,13 +136,6 @@ class Rudy::Config
112
136
  end
113
137
  end
114
138
 
115
- class Accounts < Caesars
116
- def valid?
117
- (!aws.nil? && !aws.accesskey.nil? && !aws.secretkey.nil?) &&
118
- (!aws.account.empty? && !aws.accesskey.empty? && !aws.secretkey.empty?)
119
- end
120
- end
121
-
122
139
  class Routines < Caesars
123
140
 
124
141
  # Disk routines
@@ -128,6 +145,8 @@ class Rudy::Config
128
145
  forced_hash :umount
129
146
  forced_hash :unmount
130
147
  forced_hash :mount
148
+ forced_hash :attach
149
+ forced_hash :detach
131
150
  forced_hash :snapshot
132
151
  forced_hash :restore
133
152
 
@@ -136,8 +155,8 @@ class Rudy::Config
136
155
  forced_hash :after
137
156
  forced_hash :script_local
138
157
  forced_hash :before_local
139
- forced_hash :after_local # We force hash the script keywords
140
- forced_hash :script # b/c we want them to store the usernames
158
+ forced_hash :after_local # We force hash the script keywords b/c
159
+ forced_hash :script # we want them to store the usernames
141
160
  chill :before # as hash keys.
142
161
  chill :after # We also chill them b/c we want to execute
143
162
  chill :before_local # the command blocks with an instance_eval
@@ -153,4 +172,12 @@ class Rudy::Config
153
172
  end
154
173
 
155
174
  end
175
+
176
+
177
+ class Networks < Caesars #:nodoc:all
178
+ end
179
+ class Controls < Caesars #:nodoc:all
180
+ end
181
+ class Services < Caesars #:nodoc:all
182
+ end
156
183
  end
data/lib/rudy/global.rb CHANGED
@@ -50,7 +50,7 @@ module Rudy
50
50
  @print_header = true if @print_header == nil
51
51
  @yes = false if @yes.nil?
52
52
  end
53
-
53
+
54
54
  def apply_config(config)
55
55
  return unless config.is_a?(Rudy::Config)
56
56
  if config.defaults?
@@ -10,7 +10,7 @@ module Rudy
10
10
  def inspect
11
11
  all = Guidelines.constants
12
12
  g = all.collect { |c| '%s="%s"' % [c, const_get(c)] }
13
- %q{#<Rudy::Guidelines:%s %s>} % [self.object_id, g.join(' ')]
13
+ %q{#<Rudy::Guidelines:0x%s %s>} % [self.object_id, g.join(' ')]
14
14
  end
15
15
  end
16
16
  end
data/lib/rudy/huxtable.rb CHANGED
@@ -1,4 +1,4 @@
1
-
1
+
2
2
 
3
3
 
4
4
  module Rudy
@@ -21,38 +21,28 @@ module Rudy
21
21
  #
22
22
  module Huxtable
23
23
 
24
- # TODO: investigate @@debug bug. When this is true, Caesars.debug? returns true
25
- # too. It's possible this is intentional but probably not.
26
- @@debug = false
27
- @@abort = false
28
-
29
24
  @@config = Rudy::Config.new
30
25
  @@global = Rudy::Global.new
31
26
  @@logger = StringIO.new # BUG: memory-leak for long-running apps
32
27
 
33
- @@sacred_params = [:accesskey, :secretkey, :cert, :privatekey]
34
-
35
- # NOTE: These methods conflict with Drydock::Command classes. It's
36
- # probably a good idea to not expose these anyway since it can be
37
- # done via Rudy::Huxtable.update_global etc...
38
- #def config; @@config; end
39
- #def global; @@global; end
40
- #def logger; @@logger; end
28
+ def self.config; @@config; end
29
+ def self.global; @@global; end
30
+ def self.logger; @@logger; end
41
31
 
42
32
  def self.update_config(path=nil)
43
33
  @@config.verbose = (@@global.verbose > 1)
44
34
  # nil and bad paths sent to look_and_load are ignored
45
35
  @@config.look_and_load(path || @@global.config)
46
36
  @@global.apply_config(@@config)
37
+ # And then update global again b/c some values come from @@config
38
+ update_global ## TODO: Check if this can be removed
47
39
  end
40
+
41
+ def self.update_global(ghash={}); @@global.update(ghash); end
42
+ def self.update_logger(logger); @@logger = logger; end
48
43
 
49
- def self.update_global(ghash={})
50
- @@global.update(ghash)
51
- end
52
-
53
- def self.update_logger(logger)
54
- @@logger = logger
55
- end
44
+ def self.reset_config; @@config = Rudy::Config.new; end
45
+ def self.reset_global; @@global = Rudy::Global.new; end
56
46
 
57
47
  def self.create_domain
58
48
  @sdb = Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
@@ -68,29 +58,6 @@ module Rudy
68
58
  Rudy::DOMAIN
69
59
  end
70
60
 
71
- def self.change_zone(v); @@global.zone = v; end
72
- def self.change_role(v); @@global.role = v; end
73
- def self.change_region(v); @@global.region = v; end
74
- def self.change_environment(v); @@global.environment = v; end
75
- def self.change_position(v); @@global.position = v; end
76
-
77
- def debug?; Rudy::Huxtable.debug?; end
78
- def Huxtable.debug?; @@debug == true; end
79
- def check_keys
80
- raise "No EC2 .pem keys provided" unless has_pem_keys?
81
- raise "No SSH key provided for #{current_user}!" unless has_keypair?
82
- raise "No SSH key provided for root!" unless has_keypair?(:root)
83
- end
84
-
85
- def has_pem_keys?
86
- (@@global.cert && File.exists?(@@global.cert) &&
87
- @@global.privatekey && File.exists?(@@global.privatekey))
88
- end
89
-
90
- def has_keys?
91
- (@@global.accesskey && !@@global.accesskey.empty? && @@global.secretkey && !@@global.secretkey.empty?)
92
- end
93
-
94
61
  def config_dirname
95
62
  raise "No config paths defined" unless @@config.is_a?(Rudy::Config) && @@config.paths.is_a?(Array)
96
63
  base_dir = File.dirname @@config.paths.first
@@ -224,11 +191,6 @@ module Rudy
224
191
  end
225
192
  end
226
193
 
227
- def group_metadata(env=@@global.environment, role=@@global.role)
228
- query = "['environment' = '#{env}'] intersection ['role' = '#{role}']"
229
- @sdb.query_with_attributes(Rudy::DOMAIN, query)
230
- end
231
-
232
194
  def self.keypair_path_to_name(kp)
233
195
  return nil unless kp
234
196
  name = File.basename kp
@@ -338,8 +300,9 @@ module Rudy
338
300
 
339
301
  # Returns true if this is the default machine environment and role
340
302
  def default_machine_group?
341
- @@global.environment == @@config.defaults.environment &&
342
- @@global.role == @@config.defaults.role
303
+ default_env = @@config.defaults.environment || Rudy::DEFAULT_ENVIRONMENT
304
+ default_rol = @@config.defaults.role || Rudy::DEFAULT_ROLE
305
+ @@global.environment == default_env && @@global.role == default_rol
343
306
  end
344
307
 
345
308
  def fetch_machine_config
data/lib/rudy/machines.rb CHANGED
@@ -82,7 +82,7 @@ module Rudy
82
82
  end
83
83
 
84
84
  def get_instance
85
- @ec2inst.get(@awsid)
85
+ @ec2inst.get(@awsid) rescue nil
86
86
  end
87
87
 
88
88
  def update
@@ -176,7 +176,7 @@ module Rudy
176
176
 
177
177
  def running?
178
178
  return false if @awsid.nil? || @awsid.empty?
179
- @ec2inst.running?(@awsid)
179
+ @ec2inst.running?(@awsid) rescue nil
180
180
  end
181
181
 
182
182
  end
data/lib/rudy/metadata.rb CHANGED
@@ -3,6 +3,8 @@ module Rudy
3
3
  module MetaData
4
4
  include Rudy::Huxtable
5
5
 
6
+ attr_reader :sdb_domain
7
+
6
8
  def initialize(*args)
7
9
  a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
8
10
  @sdb = Rudy::AWS::SDB.new(a, s, r)
@@ -10,6 +12,7 @@ module Rudy
10
12
  @rinst = Rudy::AWS::EC2::Instances.new(a, s, r)
11
13
  @rgrp = Rudy::AWS::EC2::Groups.new(a, s, r)
12
14
  @rkey = Rudy::AWS::EC2::KeyPairs.new(a, s, r)
15
+ @sdb_domain = Rudy::DOMAIN
13
16
  init(*args)
14
17
  end
15
18
 
@@ -22,10 +25,17 @@ module Rudy
22
25
  [dat.year, mon, day, Rudy::DELIM, hour, min, Rudy::DELIM, sec].join
23
26
  end
24
27
 
28
+ def destroy
29
+ @sdb.destroy(@sdb_domain, name)
30
+ true
31
+ end
32
+
25
33
  private
26
34
 
27
35
  # Returns a generic zipped Array of metadata
28
36
  # (There is region, zone, environment, role, but no rtype)
37
+ # NOTE: I've encoded some mega bullshit in here. more is actually an Array
38
+ # of name values [n1, v1, n2, v2] (wtf!) which makes local unnecessary.
29
39
  def build_criteria(more=[], less=[], local={})
30
40
  # TODO: This build_criteria treats "more" differently than the
31
41
  # ObjectBase one. Sort it out! (This way is better)
@@ -42,7 +52,7 @@ module Rudy
42
52
  end
43
53
 
44
54
  def to_select(more=[], less=[], local={})
45
- Rudy::AWS::SDB.generate_select ['*'], Rudy::DOMAIN, build_criteria(more, less, local)
55
+ Rudy::AWS::SDB.generate_select ['*'], @sdb_domain, build_criteria(more, less, local)
46
56
  end
47
57
 
48
58
  end
@@ -30,7 +30,9 @@ class Backups
30
30
  end
31
31
 
32
32
  def list_as_hash(more=[], less=[], local={}, &each_backup)
33
- query = to_select([:rtype, 'back'], less, local)
33
+ more ||= []
34
+ more += [:rtype, 'back']
35
+ query = to_select(more, less, local)
34
36
  list = @sdb.select(query) || {}
35
37
  backups = {}
36
38
  list.each_pair do |n,d|
@@ -0,0 +1,38 @@
1
+
2
+
3
+ module Rudy; module MetaData
4
+ class Debug
5
+ include Rudy::MetaData
6
+
7
+ def init
8
+ end
9
+
10
+ def list(more=[], less=[], local={}, &block)
11
+ objects = list_as_hash(more, less, local, &block)
12
+ objects &&= objects.values
13
+ objects
14
+ end
15
+
16
+ def list_as_hash(more=[], less=[], local={}, &block)
17
+ query = to_select(more, less, local)
18
+ list = @sdb.select(query) || {}
19
+ objects = {}
20
+ list.each_pair do |n,d|
21
+ objects[n] = d
22
+ end
23
+ objects.each_pair { |n,obj| block.call(obj) } if block
24
+ objects = nil if objects.empty?
25
+ objects
26
+ end
27
+
28
+
29
+ def to_select(more, less, local)
30
+ query = super(more, less, local)
31
+ # query << " order by created desc"
32
+ puts query if @@global.verbose > 0
33
+ query
34
+ end
35
+
36
+ end
37
+ end; end
38
+
@@ -28,7 +28,7 @@ class Disk < Storable
28
28
 
29
29
  field :created
30
30
 
31
- def init(path=nil, size=nil, device=nil, position=nil)
31
+ def init(path=nil, size=1, device='/dev/sdh', position=nil)
32
32
  @path, @size, @device = path, size, device
33
33
  @rtype = 'disk'
34
34
  @region = @@global.region
@@ -5,6 +5,8 @@ module Rudy
5
5
  module ObjectBase
6
6
  include Rudy::Huxtable
7
7
 
8
+ attr_accessor :sdb_domain
9
+
8
10
  def initialize(*args)
9
11
  a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
10
12
  @sdb = Rudy::AWS::SDB.new(a, s, r)
@@ -12,6 +14,7 @@ module Rudy
12
14
  @rvol = Rudy::AWS::EC2::Volumes.new(a, s, r)
13
15
  @radd = Rudy::AWS::EC2::Addresses.new(a, s, r)
14
16
  @rsnap = Rudy::AWS::EC2::Snapshots.new(a, s, r)
17
+ @sdb_domain = Rudy::DOMAIN
15
18
  init(*args)
16
19
  end
17
20
 
@@ -24,7 +27,8 @@ module Rudy
24
27
  end
25
28
 
26
29
  def to_select(more=[], less=[])
27
- Rudy::AWS::SDB.generate_select ['*'], Rudy::DOMAIN, build_criteria(more, less)
30
+ s = Rudy::AWS::SDB.generate_select ['*'], @sdb_domain, build_criteria(more, less)
31
+ s
28
32
  end
29
33
 
30
34
  def name(identifier, zon, env, rol, pos, *other)
@@ -35,19 +39,19 @@ module Rudy
35
39
  def save(replace=true)
36
40
  replace = true if replace.nil?
37
41
  @sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
38
- @sdb.put(Rudy::DOMAIN, name, self.to_hash, replace) # Always returns nil
42
+ @sdb.put(@sdb_domain, name, self.to_hash, replace) # Always returns nil
39
43
  true
40
44
  end
41
45
 
42
46
  def destroy
43
47
  @sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
44
- @sdb.destroy(Rudy::DOMAIN, name)
48
+ @sdb.destroy(@sdb_domain, name)
45
49
  true
46
50
  end
47
51
 
48
52
  def refresh
49
53
  @sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
50
- h = @sdb.get(Rudy::DOMAIN, name) || {}
54
+ h = @sdb.get(@sdb_domain, name) || {}
51
55
  from_hash(h)
52
56
  end
53
57
 
data/lib/rudy/routines.rb CHANGED
@@ -149,7 +149,8 @@ module Rudy
149
149
 
150
150
  if is_available
151
151
  # TODO: trap rbox errors. We could get an authentication error.
152
- opts = { :keys => root_keypairpath, :user => remote_user, :info => @@global.verbose > 3 }
152
+ opts = { :keys => root_keypairpath, :user => remote_user,
153
+ :info => @@global.verbose > 3, :debug => false }
153
154
  begin
154
155
  rbox = Rye::Box.new(machine.dns_public, opts)
155
156
  Rudy::Utils.waiter(2, 10, STDOUT, nil, 0) { rbox.connect }
@@ -208,11 +209,11 @@ module Rudy
208
209
  enjoy_every_sandwich {
209
210
  if Rudy::Routines::DiskHelper.disks?(routine) # disk
210
211
  task_separator("DISKS")
211
- if rbox.ostype == "sunos"
212
- puts "Sorry, Solaris disks are not supported yet!"
213
- else
212
+ ##if rbox.ostype == "sunos"
213
+ ## puts "Sorry, Solaris disks are not supported yet!"
214
+ ##else
214
215
  Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
215
- end
216
+ ##end
216
217
  end
217
218
  }
218
219
 
@@ -320,7 +321,7 @@ module Rudy
320
321
  end
321
322
 
322
323
  def machine_separator(name, awsid)
323
- ('%s %-63s awsid: %s ' % [$/, name, awsid]).att(:reverse)
324
+ ('%s %-50s awsid: %s ' % [$/, name, awsid]).att(:reverse)
324
325
  end
325
326
 
326
327
  def routine_separator(name)
@@ -78,13 +78,13 @@ module Rudy; module Routines;
78
78
  return
79
79
  else
80
80
  disk.fstype = props[:fstype] || 'ext3'
81
- back = (rback.list(nil, nil, props) || []).first
81
+ more = [:environment, props[:environment]] if props[:environment]
82
+ more += [:role, props[:role]] if props[:role]
83
+ back = (rback.list(more, nil) || []).first
82
84
  raise "No backup found" unless back
83
85
  puts "Found backup #{back.name} "
84
86
  end
85
87
 
86
-
87
-
88
88
  unless disk.exists? # Checks the EBS volume
89
89
  msg = "Creating volume from snapshot (#{back.awsid})... "
90
90
  disk.create(back.size, @@global.zone, back.awsid)
@@ -210,6 +210,76 @@ module Rudy; module Routines;
210
210
  end
211
211
  end
212
212
 
213
+
214
+
215
+
216
+ def attach(disks)
217
+ rdisk = Rudy::Disks.new
218
+
219
+ disks.each_pair do |path, props|
220
+ disk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
221
+ olddisk = rdisk.get(disk.name)
222
+ if olddisk && olddisk.exists?
223
+ disk.update
224
+ puts "Disk found: #{olddisk.name}"
225
+ if disk.attached?
226
+ puts "In use. Skipping...".color(:red)
227
+ return
228
+ else
229
+ disk = olddisk
230
+ end
231
+ else
232
+ puts "Creating #{disk.name} "
233
+ end
234
+ p disk
235
+ p [disk.exists?, disk.available?, olddisk.exists?, olddisk.available?]
236
+ disk.save
237
+
238
+ unless disk.exists? # Checks the EBS volume
239
+ msg = "Creating volume... "
240
+ disk.create
241
+ Rudy::Utils.waiter(2, 60, STDOUT, msg) {
242
+ disk.available?
243
+ }
244
+ end
245
+
246
+ unless disk.attached?
247
+ msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
248
+ disk.attach(@machine.awsid)
249
+ Rudy::Utils.waiter(2, 10, STDOUT, msg) {
250
+ disk.attached?
251
+ }
252
+ end
253
+ end
254
+ end
255
+
256
+ def detach(disks, destroy=false)
257
+ rdisk = Rudy::Disks.new
258
+ disks.each_pair do |path, props|
259
+ adisk = Rudy::MetaData::Disk.new(path, props[:size], props[:device], @machine.position)
260
+ disk = rdisk.get adisk.name
261
+
262
+ if disk == nil
263
+ puts "Not found: #{adisk.name}".color(:red)
264
+ return
265
+ end
266
+
267
+ if disk.attached?
268
+ msg = "Detaching #{disk.awsid}..."
269
+ disk.detach
270
+ Rudy::Utils.waiter(2, 60, STDOUT, msg) {
271
+ disk.available?
272
+ }
273
+ end
274
+
275
+ if destroy
276
+ puts "Destroying volume and metadata... "
277
+ disk.destroy
278
+ end
279
+
280
+ end
281
+ end
282
+
213
283
  def mount(disks)
214
284
  rdisk = Rudy::Disks.new
215
285
  disks.each_pair do |path, props|
@@ -220,13 +290,15 @@ module Rudy; module Routines;
220
290
  return
221
291
  end
222
292
 
223
- msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
224
- disk.attach(@machine.awsid)
225
- Rudy::Utils.waiter(2, 10, STDOUT, msg) {
226
- disk.attached?
227
- }
293
+ unless disk.attached?
294
+ msg = "Attaching #{disk.awsid} to #{@machine.awsid}... "
295
+ disk.attach(@machine.awsid)
296
+ Rudy::Utils.waiter(2, 10, STDOUT, msg) {
297
+ disk.attached?
298
+ }
228
299
 
229
- sleep 2
300
+ sleep 2
301
+ end
230
302
 
231
303
  begin
232
304
  @rbox.mkdir(:p, disk.path)
@@ -19,7 +19,7 @@ module Rudy; module Routines;
19
19
  machines = []
20
20
  generic_machine_runner(:list) do |machine,rbox|
21
21
  puts $/, "Rebooting...", $/
22
- rbox.disconnect
22
+ rbox.disconnect unless rbox.nil?
23
23
  machine.restart
24
24
  sleep 4
25
25
  msg = preliminary_separator("Checking if instance is running...")
data/lib/rudy/utils.rb CHANGED
@@ -17,7 +17,7 @@ module Rudy
17
17
  def external_ip_address
18
18
  ip = nil
19
19
  begin
20
- %w{solutious.com/ip/ myip.dk/ whatismyip.com }.each do |sponge| # w/ backup
20
+ %w{solutious.heroku.com/ip}.each do |sponge|
21
21
  ipstr = Net::HTTP.get(URI.parse("http://#{sponge}")) || ''
22
22
  ip = /([0-9]{1,3}\.){3}[0-9]{1,3}/.match(ipstr).to_s
23
23
  break if ip && !ip.empty?
data/rudy.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "rudy"
3
3
  s.rubyforge_project = 'rudy'
4
- s.version = "0.8.4"
4
+ s.version = "0.8.5"
5
5
  s.summary = "Rudy: Not your grandparents' EC2 deployment tool."
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
@@ -14,11 +14,11 @@
14
14
  s.require_paths = %w[lib]
15
15
  s.rubygems_version = '1.1.1'
16
16
 
17
- s.add_dependency 'drydock', '>= 0.6.3'
18
- s.add_dependency 'caesars', '>= 0.7.0'
17
+ s.add_dependency 'drydock', '>= 0.6.5'
18
+ s.add_dependency 'caesars', '>= 0.7.1'
19
19
  s.add_dependency 'rye', '>= 0.7.4'
20
20
  s.add_dependency 'sysinfo', '>= 0.5.1'
21
- s.add_dependency 'storable', '>= 0.5.2'
21
+ s.add_dependency 'storable', '>= 0.5.3'
22
22
  s.add_dependency 'annoy', '>= 0.5.2'
23
23
 
24
24
  s.add_dependency 'echoe'
@@ -88,6 +88,7 @@
88
88
  lib/rudy/cli/config.rb
89
89
  lib/rudy/cli/disks.rb
90
90
  lib/rudy/cli/machines.rb
91
+ lib/rudy/cli/metadata.rb
91
92
  lib/rudy/cli/routines.rb
92
93
  lib/rudy/config.rb
93
94
  lib/rudy/config/objects.rb
@@ -98,6 +99,7 @@
98
99
  lib/rudy/metadata.rb
99
100
  lib/rudy/metadata/backup.rb
100
101
  lib/rudy/metadata/backups.rb
102
+ lib/rudy/metadata/debug.rb
101
103
  lib/rudy/metadata/disk.rb
102
104
  lib/rudy/metadata/disks.rb
103
105
  lib/rudy/metadata/objectbase.rb
@@ -123,4 +125,3 @@
123
125
 
124
126
 
125
127
  end
126
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rudy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-04 00:00:00 -04:00
12
+ date: 2009-06-09 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.6.3
23
+ version: 0.6.5
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: caesars
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.7.0
33
+ version: 0.7.1
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rye
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 0.5.2
63
+ version: 0.5.3
64
64
  version:
65
65
  - !ruby/object:Gem::Dependency
66
66
  name: annoy
@@ -218,6 +218,7 @@ files:
218
218
  - lib/rudy/cli/config.rb
219
219
  - lib/rudy/cli/disks.rb
220
220
  - lib/rudy/cli/machines.rb
221
+ - lib/rudy/cli/metadata.rb
221
222
  - lib/rudy/cli/routines.rb
222
223
  - lib/rudy/config.rb
223
224
  - lib/rudy/config/objects.rb
@@ -228,6 +229,7 @@ files:
228
229
  - lib/rudy/metadata.rb
229
230
  - lib/rudy/metadata/backup.rb
230
231
  - lib/rudy/metadata/backups.rb
232
+ - lib/rudy/metadata/debug.rb
231
233
  - lib/rudy/metadata/disk.rb
232
234
  - lib/rudy/metadata/disks.rb
233
235
  - lib/rudy/metadata/objectbase.rb