rye 0.8.11 → 0.8.12
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +12 -1
- data/README.rdoc +1 -0
- data/lib/rye.rb +3 -70
- data/lib/rye/box.rb +22 -11
- data/lib/rye/cmd.rb +4 -3
- data/rye.gemspec +1 -1
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
RYE, CHANGES
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
#### 0.8.12 (2010-01-16) #############################
|
5
|
+
|
6
|
+
* FIXED: Removed dependency on ssh-agent. Also fixes starting
|
7
|
+
many instances of said executable.
|
8
|
+
* FIXED: file_append was overwriting when supplied a String (!)
|
9
|
+
* ADDED: Use SSH config file by default [Justin Case]
|
10
|
+
|
11
|
+
|
12
|
+
#### 0.8.12 (2009-11-06) #############################
|
13
|
+
|
14
|
+
* ADDED: Use SSH config file by default
|
4
15
|
|
5
16
|
#### 0.8.11 (2009-10-30) #############################
|
6
17
|
|
data/README.rdoc
CHANGED
@@ -227,6 +227,7 @@ If you find one let me know!
|
|
227
227
|
* Kalin Harvey (http://rely.ca)
|
228
228
|
* Rush[http://github.com/adamwiggins/rush] and Capistrano[http://github.com/jamis/capistrano/blob/master/lib/capistrano/shell.rb] for the inspiration.
|
229
229
|
* Mike Cline for giving the okay to use the Rye name.
|
230
|
+
* Justin Case (http://github.com/justincase/) for fixes
|
230
231
|
|
231
232
|
|
232
233
|
== More Info
|
data/lib/rye.rb
CHANGED
@@ -42,7 +42,7 @@ require 'esc'
|
|
42
42
|
module Rye
|
43
43
|
extend self
|
44
44
|
|
45
|
-
VERSION = "0.8.
|
45
|
+
VERSION = "0.8.12".freeze unless defined?(VERSION)
|
46
46
|
|
47
47
|
@@sysinfo = nil
|
48
48
|
@@agent_env = Hash.new # holds ssh-agent env vars
|
@@ -94,7 +94,7 @@ module Rye
|
|
94
94
|
end
|
95
95
|
|
96
96
|
# Looks for private keys in +path+ and returns and Array of paths
|
97
|
-
# to the files it
|
97
|
+
# to the files it finds. Raises an Exception if path does not exist.
|
98
98
|
# If path is a file rather than a directory, it will check whether
|
99
99
|
# that single file is a private key.
|
100
100
|
def find_private_keys(path)
|
@@ -127,8 +127,7 @@ module Rye
|
|
127
127
|
end
|
128
128
|
|
129
129
|
# Returns an Array of info about the currently available
|
130
|
-
# SSH keys, as provided by the SSH Agent.
|
131
|
-
# Rye.start_sshagent_environment
|
130
|
+
# SSH keys, as provided by the SSH Agent.
|
132
131
|
#
|
133
132
|
# Returns: [[bits, finger-print, file-path], ...]
|
134
133
|
#
|
@@ -262,74 +261,8 @@ module Rye
|
|
262
261
|
|
263
262
|
private
|
264
263
|
|
265
|
-
# Start the SSH Agent locally. This is important
|
266
|
-
# primarily because Rye relies on it for SSH key
|
267
|
-
# management. If the agent doesn't start then
|
268
|
-
# passwordless logins won't work.
|
269
|
-
#
|
270
|
-
# This method starts an instances of ssh-agent
|
271
|
-
# and sets the appropriate environment so all
|
272
|
-
# local commands run by Rye will have access be aware
|
273
|
-
# of this instance of the agent too.
|
274
|
-
#
|
275
|
-
# The equivalent commands on the shell are:
|
276
|
-
#
|
277
|
-
# $ ssh-agent -s
|
278
|
-
# SSH_AUTH_SOCK=/tmp/ssh-tGvaOXIXSr/agent.12951; export SSH_AUTH_SOCK;
|
279
|
-
# SSH_AGENT_PID=12952; export SSH_AGENT_PID;
|
280
|
-
# $ SSH_AUTH_SOCK=/tmp/ssh-tGvaOXIXSr/agent.12951; export SSH_AUTH_SOCK;
|
281
|
-
# $ SSH_AGENT_PID=12952; export SSH_AGENT_PID;
|
282
|
-
#
|
283
|
-
# NOTE: The OpenSSH library must be installed for this to work.
|
284
|
-
#
|
285
|
-
def start_sshagent_environment
|
286
|
-
return if @@agent_env["SSH_AGENT_PID"]
|
287
|
-
lines = Rye.shell("ssh-agent", '-s') || []
|
288
|
-
lines.each do |line|
|
289
|
-
next unless line.index("echo").nil?
|
290
|
-
line = line.slice(0..(line.index(';')-1))
|
291
|
-
key, value = line.chomp.split( /=/ )
|
292
|
-
@@agent_env[key] = value
|
293
|
-
end
|
294
|
-
ENV["SSH_AUTH_SOCK"] = @@agent_env["SSH_AUTH_SOCK"]
|
295
|
-
ENV["SSH_AGENT_PID"] = @@agent_env["SSH_AGENT_PID"]
|
296
|
-
|
297
|
-
Rye.shell("ssh-add") # Add the user's default keys
|
298
|
-
nil
|
299
|
-
end
|
300
|
-
|
301
|
-
# Kill the local instance of the SSH Agent we started.
|
302
|
-
#
|
303
|
-
# Calls this command via the local shell:
|
304
|
-
#
|
305
|
-
# $ ssh-agent -k
|
306
|
-
#
|
307
|
-
# which uses the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables
|
308
|
-
# to determine which ssh-agent to kill.
|
309
|
-
#
|
310
|
-
def end_sshagent_environment
|
311
|
-
pid = @@agent_env["SSH_AGENT_PID"]
|
312
|
-
Rye.shell("ssh-agent", '-k') || []
|
313
|
-
#Rye.shell("kill", ['-9', pid]) if pid
|
314
|
-
@@agent_env.clear
|
315
|
-
nil
|
316
|
-
end
|
317
|
-
|
318
264
|
Rye.reload
|
319
265
|
|
320
|
-
unless Rye.sysinfo.os == :windows
|
321
|
-
begin
|
322
|
-
@@mutex.synchronize { # One thread only
|
323
|
-
start_sshagent_environment # Run this now
|
324
|
-
at_exit { end_sshagent_environment } # Run this before Ruby exits
|
325
|
-
}
|
326
|
-
rescue => ex
|
327
|
-
STDERR.puts "Error initializing the SSH Agent (is OpenSSH installed?):"
|
328
|
-
STDERR.puts ex.message
|
329
|
-
STDERR.puts ex.backtrace
|
330
|
-
exit 1
|
331
|
-
end
|
332
|
-
end
|
333
266
|
end
|
334
267
|
|
335
268
|
|
data/lib/rye/box.rb
CHANGED
@@ -32,7 +32,7 @@ module Rye
|
|
32
32
|
def host; @rye_host; end
|
33
33
|
def opts; @rye_opts; end
|
34
34
|
def safe; @rye_safe; end
|
35
|
-
def user;
|
35
|
+
def user; @rye_user; end
|
36
36
|
|
37
37
|
# Returns the current value of the stash +@rye_stash+
|
38
38
|
def stash; @rye_stash; end
|
@@ -70,13 +70,14 @@ module Rye
|
|
70
70
|
# A Hash. The keys are exception classes, the values are Procs to execute
|
71
71
|
def exception_hook=(val); @rye_exception_hook = val; end
|
72
72
|
|
73
|
-
# * +host+ The hostname to connect to.
|
73
|
+
# * +host+ The hostname to connect to. Default: localhost.
|
74
|
+
# * +user+ The username to connect as. Default: SSH config file or current shell user.
|
74
75
|
# * +opts+ a hash of optional arguments.
|
75
76
|
#
|
76
77
|
# The +opts+ hash excepts the following keys:
|
77
78
|
#
|
78
|
-
# * :user => the username to connect as. Default: the current user.
|
79
79
|
# * :safe => should Rye be safe? Default: true
|
80
|
+
# * :port => remote server ssh port. Default: SSH config file or 22
|
80
81
|
# * :keys => one or more private key file paths (passwordless login)
|
81
82
|
# * :info => an IO object to print Rye::Box command info to. Default: nil
|
82
83
|
# * :debug => an IO object to print Rye::Box debugging info to. Default: nil
|
@@ -88,14 +89,20 @@ module Rye
|
|
88
89
|
# Net::SSH.start that is not already mentioned above.
|
89
90
|
#
|
90
91
|
def initialize(host='localhost', opts={})
|
92
|
+
ssh_opts = ssh_config_options(host)
|
91
93
|
@rye_exception_hook = {}
|
92
94
|
@rye_host = host
|
93
95
|
|
96
|
+
if opts[:user]
|
97
|
+
@rye_user = opts[:user]
|
98
|
+
else
|
99
|
+
@rye_user = ssh_opts[:user] || Rye.sysinfo.user
|
100
|
+
end
|
101
|
+
|
94
102
|
# These opts are use by Rye::Box and also passed to Net::SSH
|
95
103
|
@rye_opts = {
|
96
|
-
:user => Rye.sysinfo.user,
|
97
104
|
:safe => true,
|
98
|
-
:port =>
|
105
|
+
:port => ssh_opts[:port],
|
99
106
|
:keys => [],
|
100
107
|
:info => nil,
|
101
108
|
:debug => nil,
|
@@ -141,6 +148,10 @@ module Rye
|
|
141
148
|
|
142
149
|
end
|
143
150
|
|
151
|
+
# Parse SSH config files for use with Net::SSH
|
152
|
+
def ssh_config_options(host)
|
153
|
+
return Net::SSH::Config.for(host)
|
154
|
+
end
|
144
155
|
|
145
156
|
# Change the current working directory (sort of).
|
146
157
|
#
|
@@ -201,7 +212,7 @@ module Rye
|
|
201
212
|
def switch_user(newuser)
|
202
213
|
return if newuser.to_s == self.user.to_s
|
203
214
|
@rye_opts ||= {}
|
204
|
-
@
|
215
|
+
@rye_user = newuser
|
205
216
|
disconnect
|
206
217
|
end
|
207
218
|
|
@@ -215,7 +226,7 @@ module Rye
|
|
215
226
|
def interactive_ssh(run=true)
|
216
227
|
debug "interactive_ssh with keys: #{Rye.keys.inspect}"
|
217
228
|
run = false unless STDIN.tty?
|
218
|
-
cmd = Rye.prepare_command("ssh", "#{@
|
229
|
+
cmd = Rye.prepare_command("ssh", "#{@rye_user}@#{@rye_host}")
|
219
230
|
return cmd unless run
|
220
231
|
system(cmd)
|
221
232
|
end
|
@@ -613,12 +624,12 @@ module Rye
|
|
613
624
|
raise Rye::NoHost unless @rye_host
|
614
625
|
return if @rye_ssh && !reconnect
|
615
626
|
disconnect if @rye_ssh
|
616
|
-
debug "Opening connection to #{@rye_host} as #{@
|
627
|
+
debug "Opening connection to #{@rye_host} as #{@rye_user}"
|
617
628
|
highline = HighLine.new # Used for password prompt
|
618
629
|
retried = 0
|
619
630
|
@rye_opts[:keys].compact! # A quick fix in Windows. TODO: Why is there a nil?
|
620
631
|
begin
|
621
|
-
@rye_ssh = Net::SSH.start(@rye_host, @
|
632
|
+
@rye_ssh = Net::SSH.start(@rye_host, @rye_user, @rye_opts || {})
|
622
633
|
rescue Net::SSH::HostKeyMismatch => ex
|
623
634
|
STDERR.puts ex.message
|
624
635
|
print "\a" if @rye_info # Ring the bell
|
@@ -632,7 +643,7 @@ module Rye
|
|
632
643
|
print "\a" if retried == 0 && @rye_info # Ring the bell once
|
633
644
|
retried += 1
|
634
645
|
if STDIN.tty? && retried <= 3
|
635
|
-
STDERR.puts "Passwordless login failed for #{@
|
646
|
+
STDERR.puts "Passwordless login failed for #{@rye_user}"
|
636
647
|
@rye_opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }
|
637
648
|
@rye_opts[:auth_methods] ||= []
|
638
649
|
@rye_opts[:auth_methods] << 'password'
|
@@ -967,7 +978,7 @@ module Rye
|
|
967
978
|
self.mkdir(:p, target) unless self.file_exists?(target)
|
968
979
|
end
|
969
980
|
|
970
|
-
Net::SCP.start(@rye_host, @
|
981
|
+
Net::SCP.start(@rye_host, @rye_user, @rye_opts || {}) do |scp|
|
971
982
|
transfers = []
|
972
983
|
prev = ""
|
973
984
|
files.each do |file|
|
data/lib/rye/cmd.rb
CHANGED
@@ -150,12 +150,13 @@ module Rye;
|
|
150
150
|
# it will be created. If +backup+ is specified, +filepath+ will be
|
151
151
|
# copied to +filepath-previous+ before appending.
|
152
152
|
def file_append(filepath, newcontent, backup=false)
|
153
|
+
content = StringIO.new
|
154
|
+
|
153
155
|
if self.file_exists?(filepath)
|
154
156
|
self.cp filepath, "#{filepath}-previous" if backup
|
155
|
-
|
157
|
+
content = self.file_download filepath
|
156
158
|
end
|
157
|
-
|
158
|
-
content = StringIO.new
|
159
|
+
|
159
160
|
if newcontent.is_a?(StringIO)
|
160
161
|
newcontent.rewind
|
161
162
|
content.puts newcontent.read
|
data/rye.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "rye"
|
3
3
|
s.rubyforge_project = "rye"
|
4
|
-
s.version = "0.8.
|
4
|
+
s.version = "0.8.12"
|
5
5
|
s.summary = "Rye: Safely run SSH commands on a bunch of machines at the same time (from Ruby)."
|
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: rye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.12
|
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:
|
12
|
+
date: 2010-01-16 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|