rudy 0.7.1 → 0.7.3

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.
data/CHANGES.txt CHANGED
@@ -8,6 +8,13 @@ RUDY, CHANGES
8
8
  * TODO: Tests for AWS HTTPS
9
9
 
10
10
 
11
+ #### 0.7.2 (2009-04-04) ###############################
12
+
13
+ * FIXED: cli/routine.rb release method wasn't sending command alias (which broke rerelease)
14
+ * ADDED: global.offline for being cool when Internet is down
15
+ * ADDED: Better handling in aws/sdb when call returns nil (Internet is down)
16
+
17
+
11
18
  #### 0.7.1 (2009-04-04) ###############################
12
19
 
13
20
  * FIXED: rudy wasn't honouring -C option for specifying a config file
data/Rudyfile CHANGED
@@ -123,7 +123,7 @@ routines do
123
123
 
124
124
  shutdown do # $ rudy shutdown
125
125
  before :root do # Run remote SSH commands before shutdown
126
- mysqld_initd
126
+ #mysqld_initd
127
127
  end
128
128
 
129
129
  disks do
data/bin/rudy-ec2 CHANGED
@@ -23,6 +23,8 @@ require 'drydock'
23
23
  module RudyCLI_EC2
24
24
  extend Drydock
25
25
 
26
+ debug :off
27
+ default :instances
26
28
 
27
29
  # ----------------------------------- AMAZON EC2 COMMANDS --------
28
30
  # ------------------------------------------------------------------
@@ -47,6 +49,8 @@ module RudyCLI_EC2
47
49
 
48
50
  about "Amazon EC2 instance console output"
49
51
  usage "rudy-ec2 console [-g group] [instance ID]"
52
+ usage "rudy-ec2 [-k path/2/privatekey] console [instance ID]"
53
+ usage "NOTE: Private key is required only for Windows instances"
50
54
  option :g, :group, String, "A security group name"
51
55
  argv :awsid
52
56
  command :consoles => Rudy::CLI::AWS::EC2::Instances
@@ -54,8 +58,8 @@ module RudyCLI_EC2
54
58
  command_alias :consoles, :c
55
59
 
56
60
  about "Copy files to or from machines."
57
- usage "rudy-ec2 copy [-p] [-r] [-u user] [-k path/2/privatekey] source target"
58
- usage "rudy-ec2 upload -k path/2/privatekey -u username local-source target"
61
+ usage "rudy-ec2 copy [-p] [-r] source target"
62
+ usage "rudy-ec2 [-u user] [-k path/2/privatekey] upload local-source target"
59
63
  usage "rudy-ec2 download remote-source target"
60
64
  usage "NOTE: Use quotes when using a tilda or asterisk in remote paths ('~/')."
61
65
  usage "rudy-ec2 download '~/*' /tmp/"
@@ -207,12 +211,7 @@ module RudyCLI_EC2
207
211
  command_alias :zones, :zone
208
212
  command_alias :zones, :z
209
213
 
210
-
211
- # -------------------------------- RUDY-EC2 MISCELLANEOUS --------
212
- # ------------------------------------------------------------------
213
-
214
- default :instances
215
- debug :off
214
+
216
215
 
217
216
  end
218
217
 
data/lib/annoy.rb CHANGED
@@ -186,9 +186,12 @@ class Annoy
186
186
  begin
187
187
  success = Timeout::timeout(period || @@period) do
188
188
  regexp &&= Regexp.new regexp
189
- writer.print msg
190
- writer.flush if writer.respond_to?(:flush)
191
- response = Annoy.get_response
189
+ highline = HighLine.new
190
+ response = highline.ask(msg) { |q|
191
+ q.echo = '*' # Don't display response
192
+ q.overwrite = true # Erase the question afterwards
193
+ q.whitespace = :strip # Remove whitespace from the response
194
+ }
192
195
  regexp.match(response)
193
196
  end
194
197
  rescue Timeout::Error => ex
@@ -197,6 +200,27 @@ class Annoy
197
200
  end
198
201
  end
199
202
 
203
+
204
+ def Annoy.timed_display(msg, writer, period=nil)
205
+ return true unless STDIN.tty? # Only ask a question if there's a human
206
+ if Annoy.skip?
207
+ #writer.puts msg
208
+ return true
209
+ end
210
+ begin
211
+ period ||= @@period
212
+ success = Timeout::timeout(period) do
213
+ writer.puts "Message will display for #{period} seconds"
214
+ writer.print msg
215
+ writer.flush if writer.respond_to?(:flush)
216
+ sleep period+1
217
+ end
218
+ rescue Timeout::Error => ex
219
+ writer.print "\r" << ' '*msg.size
220
+ end
221
+
222
+ true
223
+ end
200
224
 
201
225
  private
202
226
  def Annoy.get_response(writer=STDOUT)
data/lib/rudy.rb CHANGED
@@ -45,7 +45,7 @@ module Rudy
45
45
  unless defined?(MAJOR)
46
46
  MAJOR = 0.freeze
47
47
  MINOR = 7.freeze
48
- TINY = 1.freeze
48
+ TINY = 3.freeze
49
49
  end
50
50
  def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
51
51
  def self.to_f; self.to_s.to_f; end
data/lib/rudy/aws.rb CHANGED
@@ -23,6 +23,7 @@ module Rudy
23
23
  end
24
24
 
25
25
  module ObjectBase
26
+ include Rudy::Huxtable
26
27
 
27
28
  protected
28
29
 
@@ -52,9 +53,9 @@ module Rudy
52
53
  rescue Timeout::Error => ex
53
54
  STDERR.puts "Timeout (#{timeout}): #{ex.message}!"
54
55
  rescue SocketError => ex
55
- raise SocketError, "Check your Internets!"
56
56
  #STDERR.puts ex.message
57
57
  #STDERR.puts ex.backtrace
58
+ raise SocketError, "Check your Internets!" unless @@global.offline
58
59
  ensure
59
60
  response ||= default
60
61
  end
@@ -30,7 +30,14 @@ module Rudy::AWS
30
30
 
31
31
  def to_s(with_title=false)
32
32
  lines = []
33
- lines << "%s (%s)" % [liner_note, @groups.join(', ')]
33
+ if @groups
34
+ gpstr = [@groups].flatten.compact.join(', ')
35
+ gpstr &&= "(#{gpstr})"
36
+ else
37
+ gpstr = ''
38
+ end
39
+
40
+ lines << "%s %s" % [liner_note, gpstr]
34
41
  #if self.running?
35
42
  # k, g = @keyname || 'no-keypair', self.groups.join(', ')
36
43
  # lines << @@sformat % %w{zone size ami keyname groups} if with_title
data/lib/rudy/aws/sdb.rb CHANGED
@@ -98,18 +98,20 @@ module Rudy
98
98
 
99
99
  doc = call(:get, params)
100
100
  results = []
101
- REXML::XPath.each(doc, "//Item") do |item|
102
- name = REXML::XPath.first(item, './Name/text()').to_s
101
+ if doc
102
+ REXML::XPath.each(doc, "//Item") do |item|
103
+ name = REXML::XPath.first(item, './Name/text()').to_s
103
104
 
104
- attributes = {'Name' => name}
105
- REXML::XPath.each(item, "./Attribute") do |attr|
106
- key = REXML::XPath.first(attr, './Name/text()').to_s
107
- value = REXML::XPath.first(attr, './Value/text()').to_s
108
- ( attributes[key] ||= [] ) << value
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
109
112
  end
110
- results << attributes
113
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
111
114
  end
112
- #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
113
115
 
114
116
  hash_results = {}
115
117
  results.each do |item|
@@ -134,8 +136,10 @@ module Rudy
134
136
 
135
137
  doc = call(:get, params)
136
138
  results = []
137
- REXML::XPath.each(doc, '//ItemName/text()') do |item|
138
- results << item.to_s
139
+ if doc
140
+ REXML::XPath.each(doc, '//ItemName/text()') do |item|
141
+ results << item.to_s
142
+ end
139
143
  end
140
144
 
141
145
  #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
@@ -159,18 +163,20 @@ module Rudy
159
163
 
160
164
  doc = call(:get, params)
161
165
  results = []
162
- REXML::XPath.each(doc, "//Item") do |item|
163
- name = REXML::XPath.first(item, './Name/text()').to_s
166
+ if doc
167
+ REXML::XPath.each(doc, "//Item") do |item|
168
+ name = REXML::XPath.first(item, './Name/text()').to_s
164
169
 
165
- attributes = {'Name' => name}
166
- REXML::XPath.each(item, "./Attribute") do |attr|
167
- key = REXML::XPath.first(attr, './Name/text()').to_s
168
- value = REXML::XPath.first(attr, './Value/text()').to_s
169
- ( attributes[key] ||= [] ) << value
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
170
177
  end
171
- results << attributes
178
+ #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
172
179
  end
173
- #return results, REXML::XPath.first(doc, '//NextToken/text()').to_s
174
180
 
175
181
  hash_results = {}
176
182
  results.each do |item|
@@ -216,10 +222,12 @@ module Rudy
216
222
  }
217
223
  )
218
224
  attributes = {}
219
- REXML::XPath.each(doc, "//Attribute") do |attr|
220
- key = REXML::XPath.first(attr, './Name/text()').to_s
221
- value = REXML::XPath.first(attr, './Value/text()').to_s
222
- ( attributes[key] ||= [] ) << value
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
223
231
  end
224
232
  attributes = nil if attributes.empty?
225
233
  attributes
data/lib/rudy/cli.rb CHANGED
@@ -154,6 +154,7 @@ module Rudy
154
154
  global :C, :config, String, "Specify another configuration file to read (ie: #{Rudy::CONFIG_FILE})"
155
155
  global :Y, :yes, "Assume a correct answer to confirmation questions"
156
156
  global :q, :quiet, "Run with less output"
157
+ global :O, :offline, "Be cool about the internet being down"
157
158
  global :v, :verbose, "Increase verbosity of output (i.e. -v or -vv or -vvv)" do
158
159
  @verbose ||= 0
159
160
  @verbose += 1
@@ -6,7 +6,7 @@ module AWS; module EC2;
6
6
 
7
7
  def status_valid?
8
8
  avail = Rudy::Utils.service_available?('status.aws.amazon.com', 80, 5)
9
- raise ServiceUnavailable, 'status.aws.amazon.com' unless avail
9
+ raise ServiceUnavailable, 'status.aws.amazon.com' unless @@global.offline || avail
10
10
  true
11
11
  end
12
12
  def status
@@ -14,12 +14,9 @@ module AWS; module EC2;
14
14
  end
15
15
  def create_groups
16
16
  opts = check_options
17
- puts "Creating #{@argv.name}"
18
-
19
17
  execute_action {
20
18
  @rgroups.create(@argv.name, @option.description, opts[:addresses], opts[:ports], opts[:protocols])
21
19
  }
22
-
23
20
  @rgroups.list(@argv.name) do |group|
24
21
  puts @@global.verbose > 0 ? group.inspect : group.dump(@@global.format)
25
22
  end
@@ -113,6 +113,10 @@ module AWS; module EC2;
113
113
 
114
114
  def consoles_valid?
115
115
  @rinst = Rudy::AWS::EC2::Instances.new(@@global.accesskey, @@global.secretkey, @@global.region)
116
+ if @@global.pkey
117
+ raise "Cannot find file #{@@global.pkey}" unless File.exists?(@@global.pkey)
118
+ raise "Insecure permissions for #{@@global.pkey}" unless (File.stat(@@global.pkey).mode & 600) == 0
119
+ end
116
120
  raise "No instances" unless @rinst.any?
117
121
  true
118
122
  end
@@ -123,11 +127,35 @@ module AWS; module EC2;
123
127
  opts[:id] &&= [opts[:id]].flatten
124
128
 
125
129
  lt = @rinst.list_group(opts[:group], :any, opts[:id]) do |inst|
126
- puts '-'*50
127
- puts "Console for: #{inst.liner_note}", $/
130
+ puts instance_separator(inst.dns_public || inst.state, inst.awsid)
128
131
  console = @rinst.console(inst.awsid)
129
132
  output = console ? Base64.decode64(console) : "Unavailable"
130
- puts output.noansi # Remove color and clear, etc...
133
+
134
+ # The linux console can include ANSI escape codes for color,
135
+ # clear screen etc... We strip them out to get rid of the
136
+ # clear specifically. Otherwise the display is messed!
137
+ output &&= output.noansi
138
+
139
+ puts output
140
+
141
+ if output.match(/<Password>(.+)<\/Password>/m) # /m, match multiple lines
142
+ puts
143
+ if @@global.pkey
144
+ encrtypted_text = ($1 || '').strip
145
+ k = Rye::Key.from_file(@@global.pkey)
146
+ pword = k.decrypt(encrtypted_text)
147
+ ret = Annoy.pose_question("Display password?\a ", /yes|y|ya|sure|you bet!/i, STDERR)
148
+ if ret
149
+ answer = "%s: %s" % ['password', pword]
150
+ Annoy.timed_display(answer, STDERR, 10)
151
+ end
152
+ puts
153
+ else
154
+ puts "Please supply a private key path to decode the administrator password"
155
+ puts "rudy-ec2 -k path/2/privatekey console [-g group] [instance ID]"
156
+ end
157
+ end
158
+
131
159
  end
132
160
 
133
161
  end
@@ -184,6 +212,9 @@ module AWS; module EC2;
184
212
  status
185
213
  end
186
214
 
215
+ def instance_separator(name, awsid)
216
+ ('%s %-63s awsid: %s ' % [$/, name, awsid]).att(:reverse)
217
+ end
187
218
 
188
219
  end
189
220
 
@@ -12,7 +12,7 @@ module AWS; module EC2;
12
12
  def create_keypairs
13
13
  rkey = Rudy::AWS::EC2::KeyPairs.new(@@global.accesskey, @@global.secretkey, @@global.region)
14
14
  kp = execute_action { rkey.create(@argv.name) }
15
- if %w[s string].member?(@@global.format)
15
+ if [:s, :string].member?(@@global.format)
16
16
  puts "Name: #{kp.name}"
17
17
  puts "Fingerprint: #{kp.fingerprint}", $/
18
18
  puts "Copy the following private key data into a file."
@@ -31,7 +31,7 @@ module Rudy; module CLI;
31
31
  end
32
32
 
33
33
  def release_valid?
34
- @rr = Rudy::Routines::Release.new
34
+ @rr = Rudy::Routines::Release.new(@alias) # Important: could be rerelease
35
35
  @rr.raise_early_exceptions
36
36
  true
37
37
  end
data/lib/rudy/global.rb CHANGED
@@ -34,6 +34,8 @@ module Rudy
34
34
  field :local_user
35
35
  field :local_hostname
36
36
 
37
+ field :offline
38
+
37
39
  field :config => String
38
40
 
39
41
  attr_accessor :print_header
data/lib/rudy/routines.rb CHANGED
@@ -91,7 +91,6 @@ module Rudy
91
91
  }
92
92
  end
93
93
 
94
-
95
94
  # TODO: trap rbox errors. We could get an authentication error.
96
95
  opts = { :keys => root_keypairpath, :user => 'root', :info => @@global.verbose > 0 }
97
96
  begin
@@ -125,12 +124,12 @@ module Rudy
125
124
  puts task_separator("AUTHORIZE USER")
126
125
  Rudy::Routines::UserHelper.authorize(@routine, machine, rbox)
127
126
  end
128
-
127
+ #puts 1
129
128
  if Rudy::Routines::ScriptHelper.before?(@routine) # before
130
129
  puts task_separator("REMOTE SHELL")
131
130
  Rudy::Routines::ScriptHelper.before(@routine, sconf, machine, rbox)
132
131
  end
133
-
132
+ #puts 2
134
133
  if Rudy::Routines::DiskHelper.disks?(@routine) # disk
135
134
  puts task_separator("DISKS")
136
135
  if rbox.ostype == "sunos"
@@ -139,7 +138,7 @@ module Rudy
139
138
  Rudy::Routines::DiskHelper.execute(@routine, machine, rbox)
140
139
  end
141
140
  end
142
-
141
+
143
142
  # Startup, shutdown, release, deploy, etc...
144
143
  routine_action.call(machine, rbox) if routine_action
145
144
 
@@ -210,8 +209,6 @@ module Rudy
210
209
  end
211
210
 
212
211
  def machine_separator(name, awsid)
213
- dashes = 80 - name.size #
214
- dashes = 0 if dashes < 1
215
212
  ('%s %-63s awsid: %s ' % [$/, name, awsid]).att(:reverse)
216
213
  end
217
214
 
data/lib/rudy/utils.rb CHANGED
@@ -21,7 +21,7 @@ module Rudy
21
21
  ip = /([0-9]{1,3}\.){3}[0-9]{1,3}/.match(ipstr).to_s
22
22
  break if ip && !ip.empty?
23
23
  end
24
- rescue SocketError, Errno::ETIMEDOUT
24
+ rescue SocketError, Errno::ETIMEDOUT => ex
25
25
  STDERR.puts "Connection Error. Check your internets!"
26
26
  end
27
27
  ip += "/32" if ip
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.7.1"
4
+ s.version = "0.7.3"
5
5
  s.summary = "Rudy: Not your grandparents' EC2 deployment tool."
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
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.7.1
4
+ version: 0.7.3
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-05-04 00:00:00 -04:00
12
+ date: 2009-05-05 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency