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 +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
|