sabat-rudy 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/CHANGES.txt +188 -0
  2. data/LICENSE.txt +19 -0
  3. data/README.rdoc +118 -0
  4. data/Rakefile +165 -0
  5. data/Rudyfile +184 -0
  6. data/bin/ird +153 -0
  7. data/bin/rudy +232 -0
  8. data/bin/rudy-ec2 +241 -0
  9. data/bin/rudy-s3 +79 -0
  10. data/bin/rudy-sdb +69 -0
  11. data/examples/README.md +10 -0
  12. data/examples/debian-sinatra-passenger/commands.rb +19 -0
  13. data/examples/debian-sinatra-passenger/machines.rb +32 -0
  14. data/examples/debian-sinatra-passenger/routines.rb +30 -0
  15. data/examples/debian-sinatra-thin/commands.rb +17 -0
  16. data/examples/debian-sinatra-thin/machines.rb +35 -0
  17. data/examples/debian-sinatra-thin/routines.rb +72 -0
  18. data/lib/rudy.rb +170 -0
  19. data/lib/rudy/aws.rb +75 -0
  20. data/lib/rudy/aws/ec2.rb +59 -0
  21. data/lib/rudy/aws/ec2/address.rb +157 -0
  22. data/lib/rudy/aws/ec2/group.rb +301 -0
  23. data/lib/rudy/aws/ec2/image.rb +168 -0
  24. data/lib/rudy/aws/ec2/instance.rb +438 -0
  25. data/lib/rudy/aws/ec2/keypair.rb +104 -0
  26. data/lib/rudy/aws/ec2/snapshot.rb +109 -0
  27. data/lib/rudy/aws/ec2/volume.rb +230 -0
  28. data/lib/rudy/aws/ec2/zone.rb +77 -0
  29. data/lib/rudy/aws/s3.rb +60 -0
  30. data/lib/rudy/aws/sdb.rb +312 -0
  31. data/lib/rudy/aws/sdb/error.rb +47 -0
  32. data/lib/rudy/cli.rb +186 -0
  33. data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
  34. data/lib/rudy/cli/aws/ec2/candy.rb +191 -0
  35. data/lib/rudy/cli/aws/ec2/groups.rb +118 -0
  36. data/lib/rudy/cli/aws/ec2/images.rb +185 -0
  37. data/lib/rudy/cli/aws/ec2/instances.rb +222 -0
  38. data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
  39. data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
  40. data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
  41. data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
  42. data/lib/rudy/cli/aws/s3/buckets.rb +49 -0
  43. data/lib/rudy/cli/aws/s3/store.rb +22 -0
  44. data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
  45. data/lib/rudy/cli/candy.rb +19 -0
  46. data/lib/rudy/cli/config.rb +81 -0
  47. data/lib/rudy/cli/disks.rb +58 -0
  48. data/lib/rudy/cli/machines.rb +114 -0
  49. data/lib/rudy/cli/routines.rb +108 -0
  50. data/lib/rudy/config.rb +116 -0
  51. data/lib/rudy/config/objects.rb +148 -0
  52. data/lib/rudy/global.rb +130 -0
  53. data/lib/rudy/guidelines.rb +18 -0
  54. data/lib/rudy/huxtable.rb +373 -0
  55. data/lib/rudy/machines.rb +281 -0
  56. data/lib/rudy/metadata.rb +51 -0
  57. data/lib/rudy/metadata/backup.rb +113 -0
  58. data/lib/rudy/metadata/backups.rb +65 -0
  59. data/lib/rudy/metadata/disk.rb +177 -0
  60. data/lib/rudy/metadata/disks.rb +67 -0
  61. data/lib/rudy/metadata/objectbase.rb +104 -0
  62. data/lib/rudy/mixins.rb +2 -0
  63. data/lib/rudy/mixins/hash.rb +25 -0
  64. data/lib/rudy/routines.rb +318 -0
  65. data/lib/rudy/routines/helper.rb +55 -0
  66. data/lib/rudy/routines/helpers/dependshelper.rb +34 -0
  67. data/lib/rudy/routines/helpers/diskhelper.rb +331 -0
  68. data/lib/rudy/routines/helpers/scmhelper.rb +39 -0
  69. data/lib/rudy/routines/helpers/scripthelper.rb +198 -0
  70. data/lib/rudy/routines/helpers/userhelper.rb +37 -0
  71. data/lib/rudy/routines/passthrough.rb +38 -0
  72. data/lib/rudy/routines/reboot.rb +75 -0
  73. data/lib/rudy/routines/release.rb +50 -0
  74. data/lib/rudy/routines/shutdown.rb +33 -0
  75. data/lib/rudy/routines/startup.rb +36 -0
  76. data/lib/rudy/scm.rb +75 -0
  77. data/lib/rudy/scm/git.rb +217 -0
  78. data/lib/rudy/scm/svn.rb +110 -0
  79. data/lib/rudy/utils.rb +365 -0
  80. data/rudy.gemspec +151 -0
  81. data/support/mailtest +40 -0
  82. data/support/randomize-root-password +45 -0
  83. data/support/rudy-ec2-startup +200 -0
  84. data/support/update-ec2-ami-tools +20 -0
  85. data/test/01_mixins/10_hash_test.rb +25 -0
  86. data/test/10_config/00_setup_test.rb +20 -0
  87. data/test/10_config/30_machines_test.rb +69 -0
  88. data/test/15_scm/00_setup_test.rb +20 -0
  89. data/test/15_scm/20_git_test.rb +61 -0
  90. data/test/20_sdb/00_setup_test.rb +16 -0
  91. data/test/20_sdb/10_domains_test.rb +115 -0
  92. data/test/25_ec2/00_setup_test.rb +29 -0
  93. data/test/25_ec2/10_keypairs_test.rb +41 -0
  94. data/test/25_ec2/20_groups_test.rb +131 -0
  95. data/test/25_ec2/30_addresses_test.rb +38 -0
  96. data/test/25_ec2/40_volumes_test.rb +49 -0
  97. data/test/25_ec2/50_snapshots_test.rb +74 -0
  98. data/test/26_ec2_instances/00_setup_test.rb +28 -0
  99. data/test/26_ec2_instances/10_instances_test.rb +83 -0
  100. data/test/26_ec2_instances/50_images_test.rb +13 -0
  101. data/test/30_sdb_metadata/00_setup_test.rb +21 -0
  102. data/test/30_sdb_metadata/10_disks_test.rb +109 -0
  103. data/test/30_sdb_metadata/20_backups_test.rb +102 -0
  104. data/test/coverage.txt +51 -0
  105. data/test/helper.rb +36 -0
  106. metadata +276 -0
@@ -0,0 +1,60 @@
1
+
2
+ module Rudy::AWS
3
+ class S3
4
+
5
+ def initialize(access_key=nil, secret_key=nil, region=nil, debug=nil)
6
+
7
+ url ||= 'http://sdb.amazonaws.com'
8
+ # There is a bug with passing :server to EC2::Base.new so
9
+ # we'll use the environment variable for now.
10
+ #if region && Rudy::AWS.valid_region?(region)
11
+ # "#{region}.sdb.amazonaws.com"
12
+ #end
13
+
14
+ @access_key_id = access_key || ENV['AWS_ACCESS_KEY'] || ENV['AMAZON_ACCESS_KEY_ID']
15
+ @secret_access_key = secret_key || ENV['AWS_SECRET_KEY'] || ENV['AMAZON_SECRET_ACCESS_KEY']
16
+ @base_url = url
17
+ @debug = debug || StringIO.new
18
+
19
+
20
+ AWS::S3::Base.establish_connection!(
21
+ :access_key_id => @access_key_id,
22
+ :secret_access_key => @secret_access_key
23
+ )
24
+
25
+ end
26
+
27
+ def list_buckets
28
+ ::AWS::S3::Service.buckets
29
+ end
30
+
31
+ def create_bucket(name, location=nil)
32
+ opts = {}
33
+ opts[:location] = location.to_s.upcase if location
34
+ ::AWS::S3::Bucket.create(name, opts)
35
+ end
36
+
37
+ def destroy_bucket(name)
38
+ ::AWS::S3::Bucket.delete(name)
39
+ end
40
+
41
+ def find_bucket(name)
42
+ blist = ::AWS::S3::Service.buckets
43
+ blist.select { |bobj| bobj.name == name }.first
44
+ end
45
+
46
+ def list_bucket_objects(name)
47
+ ::AWS::S3::Bucket.objects(name)
48
+ end
49
+
50
+ #def store(path, bucket)
51
+ # fname = File.basename(path)
52
+ # S3Object.store(fname, open(path), bucket)
53
+ #end
54
+
55
+ def bucket_exists?(name)
56
+ b = find_bucket(name)
57
+ !b.nil?
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,312 @@
1
+
2
+ require 'time'
3
+ require 'cgi'
4
+ require 'uri'
5
+ require 'net/http'
6
+ require 'base64'
7
+ require 'openssl'
8
+ require 'rexml/document'
9
+ require 'rexml/xpath'
10
+
11
+ module Rudy
12
+ module AWS
13
+ class SDB
14
+ class NoAccessKey < RuntimeError; end
15
+ class NoSecretKey < RuntimeError; end
16
+ include Rudy::AWS::ObjectBase
17
+
18
+ require 'rudy/aws/sdb/error'
19
+
20
+ def initialize(access_key=nil, secret_key=nil, region=nil, debug=nil)
21
+ raise NoAccessKey if access_key.nil? || access_key.empty?
22
+ raise NoSecretKey if secret_key.nil? || secret_key.empty?
23
+
24
+ url ||= 'http://sdb.amazonaws.com'
25
+ # There is a bug with passing :server to EC2::Base.new so
26
+ # we'll use the environment variable for now.
27
+ #if region && Rudy::AWS.valid_region?(region)
28
+ # "#{region}.sdb.amazonaws.com"
29
+ #end
30
+
31
+ @access_key_id = access_key || ENV['AWS_ACCESS_KEY']
32
+ @secret_access_key = secret_key || ENV['AWS_SECRET_KEY']
33
+ @base_url = url
34
+ @debug = debug || StringIO.new
35
+ end
36
+
37
+ def list_domains(max = nil, token = nil)
38
+ params = { 'Action' => 'ListDomains' }
39
+ params['NextToken'] =
40
+ token unless token.nil? || token.empty?
41
+ params['MaxNumberOfDomains'] =
42
+ max.to_s unless max.nil? || max.to_i == 0
43
+ doc = call(:get, params)
44
+ results = []
45
+ REXML::XPath.each(doc, '//DomainName/text()') do |domain|
46
+ results << domain.to_s
47
+ end
48
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
49
+ results
50
+ end
51
+
52
+ def create_domain(domain)
53
+ call(:post, { 'Action' => 'CreateDomain', 'DomainName'=> domain.to_s })
54
+ true
55
+ end
56
+
57
+ def destroy_domain(domain)
58
+ call(
59
+ :delete,
60
+ { 'Action' => 'DeleteDomain', 'DomainName' => domain.to_s }
61
+ )
62
+ true
63
+ end
64
+
65
+
66
+ # Takes a zipped Array or Hash of criteria.
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]
71
+ query = []
72
+ q.each do |n,v|
73
+ query << "#{Rudy::AWS.escape n}='#{Rudy::AWS.escape v}'"
74
+ end
75
+ "select * from #{domain} where " << query.join(' and ')
76
+ end
77
+
78
+
79
+ # Takes a zipped Array or Hash of criteria.
80
+ # Returns a string suitable for a SimpleDB Query
81
+ def self.generate_query(*args)
82
+ q = args.first.is_a?(Hash)? args.first : Hash[*args.flatten]
83
+ query = []
84
+ q.each do |n,v|
85
+ query << "['#{Rudy::AWS.escape n}'='#{Rudy::AWS.escape v}']"
86
+ end
87
+ query.join(" intersection ")
88
+ end
89
+
90
+
91
+ def select(select, token = nil)
92
+ params = {
93
+ 'Action' => 'Select',
94
+ 'SelectExpression' => select,
95
+ }
96
+ params['NextToken'] =
97
+ token unless token.nil? || token.empty?
98
+
99
+ doc = call(:get, params)
100
+ results = []
101
+ if doc
102
+ REXML::XPath.each(doc, "//Item") do |item|
103
+ name = REXML::XPath.first(item, './Name/text()').to_s
104
+
105
+ attributes = {'Name' => name}
106
+ REXML::XPath.each(item, "./Attribute") do |attr|
107
+ key = REXML::XPath.first(attr, './Name/text()').to_s
108
+ value = REXML::XPath.first(attr, './Value/text()').to_s
109
+ ( attributes[key] ||= [] ) << value
110
+ end
111
+ results << attributes
112
+ end
113
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
114
+ end
115
+
116
+ hash_results = {}
117
+ results.each do |item|
118
+ hash_results[item.delete('Name')] = item
119
+ end
120
+
121
+ hash_results.empty? ? nil : hash_results
122
+ end
123
+
124
+ # <QueryResult><ItemName>in-c2ffrw</ItemName><ItemName>in-72yagt</ItemName><ItemName>in-52j8gj</ItemName>
125
+ def query(domain, query, max = nil, token = nil)
126
+ params = {
127
+ 'Action' => 'Query',
128
+ 'QueryExpression' => query,
129
+ 'DomainName' => domain.to_s
130
+ }
131
+ params['NextToken'] =
132
+ token unless token.nil? || token.empty?
133
+ params['MaxNumberOfItems'] =
134
+ max.to_s unless max.nil? || max.to_i == 0
135
+
136
+
137
+ doc = call(:get, params)
138
+ results = []
139
+ if doc
140
+ REXML::XPath.each(doc, '//ItemName/text()') do |item|
141
+ results << item.to_s
142
+ end
143
+ end
144
+
145
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
146
+ results.empty? ? nil : results
147
+
148
+ end
149
+
150
+
151
+
152
+ # <QueryWithAttributesResult><Item><Name>in-c2ffrw</Name><Attribute><Name>code</Name><Value>in-c2ffrw</Value></Attribute><Attribute><Name>date_created</Name><Value>2008-10-31</Value></Attribute></Item><Item>
153
+ def query_with_attributes(domain, query, max = nil, token = nil)
154
+ params = {
155
+ 'Action' => 'QueryWithAttributes',
156
+ 'QueryExpression' => query,
157
+ 'DomainName' => domain.to_s
158
+ }
159
+ params['NextToken'] =
160
+ token unless token.nil? || token.empty?
161
+ params['MaxNumberOfItems'] =
162
+ max.to_s unless max.nil? || max.to_i == 0
163
+
164
+ doc = call(:get, params)
165
+ results = []
166
+ if doc
167
+ REXML::XPath.each(doc, "//Item") do |item|
168
+ name = REXML::XPath.first(item, './Name/text()').to_s
169
+
170
+ attributes = {'Name' => name}
171
+ REXML::XPath.each(item, "./Attribute") do |attr|
172
+ key = REXML::XPath.first(attr, './Name/text()').to_s
173
+ value = REXML::XPath.first(attr, './Value/text()').to_s
174
+ ( attributes[key] ||= [] ) << value
175
+ end
176
+ results << attributes
177
+ end
178
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
179
+ end
180
+
181
+ hash_results = {}
182
+ results.each do |item|
183
+ hash_results[item.delete('Name')] = item
184
+ end
185
+
186
+ hash_results
187
+ end
188
+
189
+
190
+
191
+ def put_attributes(domain, item, attributes, replace = true)
192
+ replace = true if replace == :replace
193
+ params = {
194
+ 'Action' => 'PutAttributes',
195
+ 'DomainName' => domain.to_s,
196
+ 'ItemName' => item.to_s
197
+ }
198
+ count = 0
199
+
200
+ attributes.each do | key, values |
201
+ ([]<<values).flatten.each do |value|
202
+ params["Attribute.#{count}.Name"] = key.to_s
203
+ params["Attribute.#{count}.Value"] = value.to_s
204
+ params["Attribute.#{count}.Replace"] = replace
205
+ count += 1
206
+ end
207
+ end
208
+
209
+ call(:put, params)
210
+
211
+ true
212
+ end
213
+ alias :put :put_attributes
214
+
215
+ def get_attributes(domain, item)
216
+ doc = call(
217
+ :get,
218
+ {
219
+ 'Action' => 'GetAttributes',
220
+ 'DomainName' => domain.to_s,
221
+ 'ItemName' => item.to_s
222
+ }
223
+ )
224
+ attributes = {}
225
+ if doc
226
+ REXML::XPath.each(doc, "//Attribute") do |attr|
227
+ key = REXML::XPath.first(attr, './Name/text()').to_s
228
+ value = REXML::XPath.first(attr, './Value/text()').to_s
229
+ ( attributes[key] ||= [] ) << value
230
+ end
231
+ end
232
+ attributes = nil if attributes.empty?
233
+ attributes
234
+ end
235
+ alias :get :get_attributes
236
+
237
+
238
+ def delete_attributes(domain, item)
239
+ call(
240
+ :delete,
241
+ {
242
+ 'Action' => 'DeleteAttributes',
243
+ 'DomainName' => domain.to_s,
244
+ 'ItemName' => item.to_s
245
+ }
246
+ )
247
+ true
248
+ end
249
+ alias :destroy :delete_attributes
250
+
251
+
252
+
253
+ protected
254
+
255
+ def call(method, params)
256
+ params.merge!( {
257
+ 'Version' => '2007-11-07',
258
+ 'SignatureVersion' => '1',
259
+ 'AWSAccessKeyId' => @access_key_id,
260
+ 'Timestamp' => Time.now.gmtime.iso8601
261
+ }
262
+ )
263
+ data = ''
264
+ query = []
265
+
266
+ params.keys.sort_by { |k| k.upcase }.each do |key|
267
+ data << "#{key}#{params[key].to_s}"
268
+ query << "#{key}=#{CGI::escape(params[key].to_s)}"
269
+ end
270
+
271
+ digest = OpenSSL::Digest::Digest.new('sha1')
272
+ hmac = OpenSSL::HMAC.digest(digest, @secret_access_key, data)
273
+ signature = Base64.encode64(hmac).strip
274
+ query << "Signature=#{CGI::escape(signature)}"
275
+ query = query.join('&')
276
+ url = "#{@base_url}?#{query}"
277
+ uri = URI.parse(url)
278
+ @debug.puts("#{url}") if @debug
279
+
280
+ response = execute_request(nil) {
281
+ Net::HTTP.new(uri.host, uri.port).send_request(method, uri.request_uri)
282
+ }
283
+
284
+ if !response.nil?
285
+
286
+ @debug.puts("#{response.code}\n#{response.body}") if @debug
287
+ raise(ConnectionError.new(response)) unless (200..400).include?(
288
+ response.code.to_i
289
+ )
290
+
291
+
292
+ doc = REXML::Document.new(response.body)
293
+ error = doc.get_elements('*/Errors/Error')[0]
294
+ raise(
295
+ Module.class_eval(
296
+ "AwsSdb::#{error.get_elements('Code')[0].text}Error"
297
+ ).new(
298
+ error.get_elements('Message')[0].text,
299
+ doc.get_elements('*/RequestID')[0].text
300
+ )
301
+ ) unless error.nil?
302
+ else
303
+ doc = nil
304
+ end
305
+ doc
306
+ end
307
+ end
308
+
309
+ end
310
+ end
311
+
312
+
@@ -0,0 +1,47 @@
1
+ module Rudy
2
+ module AWS
3
+ class SDB
4
+
5
+ class Error < RuntimeError ; end
6
+
7
+ class RequestError < Error
8
+ attr_reader :request_id
9
+
10
+ def initialize(message, request_id=nil)
11
+ super(message)
12
+ @request_id = request_id
13
+ end
14
+ end
15
+
16
+ class InvalidDomainNameError < RequestError ; end
17
+ class InvalidParameterValueError < RequestError ; end
18
+ class InvalidNextTokenError < RequestError ; end
19
+ class InvalidNumberPredicatesError < RequestError ; end
20
+ class InvalidNumberValueTestsError < RequestError ; end
21
+ class InvalidQueryExpressionError < RequestError ; end
22
+ class MissingParameterError < RequestError ; end
23
+ class NoSuchDomainError < RequestError ; end
24
+ class NumberDomainsExceededError < RequestError ; end
25
+ class NumberDomainAttributesExceededError < RequestError ; end
26
+ class NumberDomainBytesExceededError < RequestError ; end
27
+ class NumberItemAttributesExceededError < RequestError ; end
28
+ class RequestTimeoutError < RequestError ; end
29
+
30
+ class FeatureDeprecatedError < RequestError ; end
31
+
32
+ class ConnectionError < Rudy::Error
33
+ attr_reader :response
34
+
35
+ def initialize(response)
36
+ super(
37
+ "#{response.code} \
38
+ #{response.message if response.respond_to?(:message)}"
39
+ )
40
+ @response = response
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+ end
data/lib/rudy/cli.rb ADDED
@@ -0,0 +1,186 @@
1
+
2
+ require 'drydock'
3
+
4
+
5
+ module Rudy
6
+
7
+ # = CLI
8
+ #
9
+ # These classes provide the functionality for the Command
10
+ # line interfaces. See the bin/ files if you're interested.
11
+ #
12
+ module CLI
13
+ class NoCred < RuntimeError #:nodoc
14
+ end
15
+
16
+ class Output < Storable
17
+ # TODO: Use for all CLI responses
18
+ # Messages and errors should be in @@global.format
19
+ # Should print messages as they come
20
+ end
21
+
22
+ class CommandBase < Drydock::Command
23
+ include Rudy::Huxtable
24
+
25
+ attr_reader :config
26
+
27
+ protected
28
+ def init
29
+
30
+ if Drydock.debug?
31
+ #Caesars.enable_debug
32
+ Rudy.enable_debug
33
+ end
34
+
35
+ # The CLI wants output!
36
+ Rudy::Huxtable.update_logger STDOUT
37
+
38
+ # Send The Huxtables the global values from the command-line
39
+ Rudy::Huxtable.update_global @global
40
+
41
+ # Reload configuration. This must come after update_global
42
+ # so it will catch the @@global.config path (if supplied).
43
+ begin
44
+ Rudy::Huxtable.update_config
45
+ rescue Caesars::SyntaxError => ex
46
+ STDERR.puts ex.message
47
+ STDERR.puts ex.backtrace if @@global.verbose > 0
48
+ exit 81
49
+ end
50
+
51
+ # And then update global again b/c some values come from @@config
52
+ Rudy::Huxtable.update_global
53
+
54
+ @@global.nocolor ? String.disable_color : String.enable_color
55
+ @@global.yes ? Annoy.enable_skip : Annoy.disable_skip
56
+
57
+ unless @@global.accesskey && @@global.secretkey
58
+ STDERR.puts "No AWS credentials. Check your configs!"
59
+ STDERR.puts "Try: rudy init"
60
+ exit 1
61
+ end
62
+
63
+ if @@global.environment =~ /^prod/ && Drydock.debug?
64
+ puts Rudy::Utils.banner("PRODUCTION ACCESS IS DISABLED IN DEBUG MODE")
65
+ exit 1
66
+ end
67
+
68
+ end
69
+
70
+ def execute_action(emsg="Failed", &action)
71
+ begin
72
+ ret = action.call
73
+ raise emsg unless ret
74
+ ret
75
+ rescue Rudy::AWS::EC2::NoAMI => ex
76
+ raise Drydock::OptError.new('-a', @alias)
77
+ end
78
+ end
79
+
80
+ def execute_check(level=:medium)
81
+ ret = Annoy.are_you_sure?(level)
82
+ exit 0 unless ret
83
+ ret
84
+ end
85
+
86
+ # Print a default header to the screen for every command.
87
+ #
88
+ def print_header
89
+
90
+ # Send The Huxtables the global values again because they could be
91
+ # updated after initialization but before the command was executed
92
+ Rudy::Huxtable.update_global @global
93
+
94
+ puts Rudy::CLI.generate_header(@@global, @@config) if @@global.print_header
95
+
96
+ unless @@global.quiet
97
+ if @@global.environment == "prod"
98
+ msg = "YOU ARE PLAYING WITH PRODUCTION"
99
+ puts Rudy::Utils.banner(msg, :normal), $/
100
+ end
101
+ puts Rudy::Utils.banner("THIS IS EC2"), $/ if Rudy.in_situ?
102
+ end
103
+ end
104
+
105
+ 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)
109
+ end
110
+
111
+ end
112
+
113
+ def self.generate_header(global, config)
114
+ return "" if global.quiet
115
+ header = StringIO.new
116
+ title, name = "RUDY v#{Rudy::VERSION}", config.accounts.aws.name
117
+ now_utc = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")
118
+ criteria = []
119
+ [:region, :zone, :environment, :role, :position].each do |n|
120
+ key, val = n.to_s.slice(0,1).att, global.send(n)
121
+ key = 'R' if n == :region
122
+ next unless val
123
+ criteria << "#{key.att}:#{val.to_s.bright}"
124
+ end
125
+ if config.accounts && config.accounts.aws
126
+ if global.verbose > 0
127
+ header.puts '%s -- %s -- %s UTC' % [title, name, now_utc]
128
+ end
129
+ header.puts '[%s]' % [criteria.join(" ")], $/
130
+ end
131
+ header.rewind
132
+ header.read
133
+ end
134
+
135
+
136
+ # A base for all Drydock executables (bin/rudy etc...).
137
+ class Base
138
+ extend Drydock
139
+
140
+ before do |obj|
141
+ # Don't print Rudy header unless requested to
142
+ obj.global.print_header = false if (obj.global.verbose == 0)
143
+ @start = Time.now
144
+ end
145
+
146
+ after do |obj|
147
+ if obj.global.verbose > 0
148
+ puts
149
+ @elapsed = Time.now - @start
150
+ puts "Elapsed: %.2f seconds" % @elapsed.to_f if @elapsed > 0.1
151
+ end
152
+ end
153
+
154
+
155
+ # These globals are used by all bin/ executables
156
+ global :A, :accesskey, String, "AWS Access Key"
157
+ global :S, :secretkey, String, "AWS Secret Access Key"
158
+ global :R, :region, String, "Amazon service region (ie: #{Rudy::DEFAULT_REGION})"
159
+ global :z, :zone, String, "Amazon Availability zone (ie: #{Rudy::DEFAULT_ZONE})"
160
+ global :u, :user, String, "Provide a username (ie: #{Rudy::DEFAULT_USER})"
161
+ global :k, :pkey, String, "Path to the private SSH key"
162
+ global :f, :format, String, "Output format"
163
+ global :n, :nocolor, "Disable output colors"
164
+ global :C, :config, String, "Specify another configuration file to read (ie: #{Rudy::CONFIG_FILE})"
165
+ global :Y, :yes, "Assume a correct answer to confirmation questions"
166
+ global :q, :quiet, "Run with less output"
167
+ global :O, :offline, "Be cool about the internet being down"
168
+ global :v, :verbose, "Increase verbosity of output (i.e. -v or -vv or -vvv)" do
169
+ @verbose ||= 0
170
+ @verbose += 1
171
+ end
172
+ global :V, :version, "Display version number" do
173
+ puts "Rudy version: #{Rudy::VERSION}"
174
+ exit 0
175
+ end
176
+
177
+ end
178
+
179
+
180
+ end
181
+
182
+ end
183
+
184
+ Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'cli', '**', '*.rb')
185
+
186
+