rudy 0.7.1 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +7 -0
- data/Rudyfile +1 -1
- data/bin/rudy-ec2 +7 -8
- data/lib/annoy.rb +27 -3
- data/lib/rudy.rb +1 -1
- data/lib/rudy/aws.rb +2 -1
- data/lib/rudy/aws/ec2/instance.rb +8 -1
- data/lib/rudy/aws/sdb.rb +32 -24
- data/lib/rudy/cli.rb +1 -0
- data/lib/rudy/cli/aws/ec2/candy.rb +1 -1
- data/lib/rudy/cli/aws/ec2/groups.rb +0 -3
- data/lib/rudy/cli/aws/ec2/instances.rb +34 -3
- data/lib/rudy/cli/aws/ec2/keypairs.rb +1 -1
- data/lib/rudy/cli/routines.rb +1 -1
- data/lib/rudy/global.rb +2 -0
- data/lib/rudy/routines.rb +3 -6
- data/lib/rudy/utils.rb +1 -1
- data/rudy.gemspec +1 -1
- metadata +2 -2
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
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]
|
58
|
-
usage "rudy-ec2
|
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
|
-
|
190
|
-
|
191
|
-
|
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
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
|
-
|
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
|
-
|
102
|
-
|
101
|
+
if doc
|
102
|
+
REXML::XPath.each(doc, "//Item") do |item|
|
103
|
+
name = REXML::XPath.first(item, './Name/text()').to_s
|
103
104
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
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
|
-
|
138
|
-
|
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
|
-
|
163
|
-
|
166
|
+
if doc
|
167
|
+
REXML::XPath.each(doc, "//Item") do |item|
|
168
|
+
name = REXML::XPath.first(item, './Name/text()').to_s
|
164
169
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
170
177
|
end
|
171
|
-
results
|
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
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
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
|
-
|
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
|
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."
|
data/lib/rudy/cli/routines.rb
CHANGED
data/lib/rudy/global.rb
CHANGED
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
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.
|
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-
|
12
|
+
date: 2009-05-05 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|