delano-rye 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -4,6 +4,14 @@ TODO
4
4
 
5
5
  * Fingerprints: ssh-keygen -l -f id_rsa_repos.pub
6
6
 
7
+ #### 0.5.0 (2009-04-18) #############################
8
+
9
+ * ADDED: Rye::Box.switch_user
10
+ * ADDED: Several new commands to Rye::Cmd
11
+ * ADDED: Rye::Box.authorize_keys_local and "rye authorize-local
12
+ * FIXED: Bug in connect which prevented key-based logins for reconnections
13
+ * FIXED: Method errors in JRuby
14
+
7
15
 
8
16
  #### 0.4.3 (2009-04-14) #############################
9
17
 
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- = Rye - v0.4
1
+ = Rye - v0.5
2
2
 
3
3
  Safely run SSH commands on a bunch of machines at the same time (from Ruby).
4
4
 
data/bin/rye CHANGED
@@ -43,8 +43,8 @@ command :authorize do |obj|
43
43
 
44
44
  obj.argv.each do |hostname|
45
45
 
46
- rbox = Rye::Box.new(hostname, opts).connect
47
46
  puts "Authorizing #{rbox.opts[:user]}@#{hostname}"
47
+ rbox = Rye::Box.new(hostname, opts).connect
48
48
  puts "Added public keys for: ", rbox.authorize_keys
49
49
  puts "Now try: " << "ssh #{rbox.opts[:user]}@#{hostname}"
50
50
 
@@ -53,6 +53,17 @@ command :authorize do |obj|
53
53
  end
54
54
  command_alias :authorize, :authorise
55
55
 
56
+ desc "Add your public keys to your current account on this machine"
57
+ command :authorize_local do |obj|
58
+ user = Rye.sysinfo.user
59
+ puts "Authorizing #{user}@localhost"
60
+ rbox = Rye::Box.new('localhost').connect
61
+ puts "Added public keys for: ", rbox.authorize_keys_local
62
+ puts "Now try: " << "ssh #{user}@localhost"
63
+
64
+ end
65
+ command_alias :local_authorize, :local_authorise
66
+
56
67
 
57
68
  desc "Generate a public key from a private key"
58
69
 
data/bin/try CHANGED
@@ -107,6 +107,7 @@ puts %Q(
107
107
 
108
108
  rset = Rye::Set.new('default', :parallel => true)
109
109
  rbox = Rye::Box.new
110
+ p rbox
110
111
 
111
112
  rset.add_keys('/private/key/path') # For passwordless logins
112
113
  rset.add_boxes(rbox, 'localhost') # Add boxes as hostnames or objects
data/lib/rye.rb CHANGED
@@ -35,7 +35,7 @@ module Rye
35
35
  extend self
36
36
 
37
37
  unless defined?(SYSINFO)
38
- VERSION = 0.4.freeze
38
+ VERSION = 0.5.freeze
39
39
  SYSINFO = SystemInfo.new.freeze
40
40
  end
41
41
 
data/lib/rye/box.rb CHANGED
@@ -123,8 +123,12 @@ module Rye
123
123
  @current_working_directory = key
124
124
  self
125
125
  end
126
- alias :cd :'[]'
127
-
126
+ # alias :cd :'[]' # fix for jruby
127
+ def cd(key=nil);
128
+ @current_working_directory = key
129
+ self
130
+ end
131
+
128
132
  # Open an SSH session with +@host+. This called automatically
129
133
  # when you the first comamnd is run if it's not already connected.
130
134
  # Raises a Rye::NoHost exception if +@host+ is not specified.
@@ -133,9 +137,10 @@ module Rye
133
137
  def connect
134
138
  raise Rye::NoHost unless @host
135
139
  disconnect if @ssh
136
- debug "Opening connection to #{@host}"
140
+ debug "Opening connection to #{@host} as #{@opts[:user]}"
137
141
  highline = HighLine.new # Used for password prompt
138
142
  retried = 0
143
+
139
144
  begin
140
145
  @ssh = Net::SSH.start(@host, @opts[:user], @opts || {})
141
146
  rescue Net::SSH::AuthenticationFailed => ex
@@ -143,7 +148,7 @@ module Rye
143
148
  if STDIN.tty? && retried <= 3
144
149
  @opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }
145
150
  @opts[:auth_methods] ||= []
146
- @opts[:auth_methods] = %w(password)
151
+ @opts[:auth_methods] << 'password'
147
152
  retry
148
153
  else
149
154
  STDERR.puts "Authentication failed."
@@ -151,10 +156,38 @@ module Rye
151
156
  end
152
157
  end
153
158
 
159
+ # We add :auth_methods (a Net::SSH joint) to force asking for a
160
+ # password if the initial (key-based) authentication fails. We
161
+ # need to delete the key from @opts otherwise it lingers until
162
+ # the next connection (if we switch_user is called for example).
163
+ @opts.delete :auth_methods if @opts.has_key?(:auth_methods)
164
+
154
165
  @ssh.is_a?(Net::SSH::Connection::Session) && !@ssh.closed?
155
166
  self
156
167
  end
157
168
 
169
+ # Close the SSH session with +@host+. This is called
170
+ # automatically at exit if the connection is open.
171
+ def disconnect
172
+ return unless @ssh && !@ssh.closed?
173
+ @ssh.loop(0.1) { @ssh.busy? }
174
+ debug "Closing connection to #{@ssh.host}"
175
+ @ssh.close
176
+ end
177
+
178
+ # Reconnect as another user
179
+ # * +newuser+ The username to reconnect as
180
+ #
181
+ # NOTE: if there is an open connection, it's disconnected
182
+ # and a new one is opened for the given user.
183
+ def switch_user(newuser)
184
+ return if newuser.to_s == self.user.to_s
185
+ @opts ||= {}
186
+ @opts[:user] = newuser
187
+ disconnect
188
+ connect
189
+ end
190
+
158
191
  # Open an interactive SSH session. This only works if STDIN.tty?
159
192
  # returns true. Otherwise it returns the SSH command that would
160
193
  # have been run. This requires the SSH command-line executable (ssh).
@@ -169,15 +202,6 @@ module Rye
169
202
  system(cmd)
170
203
  end
171
204
 
172
- # Close the SSH session with +@host+. This is called
173
- # automatically at exit if the connection is open.
174
- def disconnect
175
- return unless @ssh && !@ssh.closed?
176
- @ssh.loop(0.1) { @ssh.busy? }
177
- debug "Closing connection to #{@ssh.host}"
178
- @ssh.close
179
- end
180
-
181
205
  # Add one or more private keys to the SSH Agent.
182
206
  # * +additional_keys+ is a list of file paths to private keys
183
207
  # Returns the instance of Box
@@ -190,7 +214,7 @@ module Rye
190
214
  debug "ssh-add stdout: #{ret.stdout}"
191
215
  debug "ssh-add stderr: #{ret.stderr}"
192
216
  end
193
- self
217
+ self #MUST RETURN itself
194
218
  end
195
219
  alias :add_key :add_keys
196
220
 
@@ -203,6 +227,10 @@ module Rye
203
227
  end
204
228
  alias :add_environment_variable :add_env
205
229
 
230
+ def user
231
+ (@opts || {})[:user]
232
+ end
233
+
206
234
  # See Rye.keys
207
235
  def keys
208
236
  Rye.keys
@@ -236,7 +264,9 @@ module Rye
236
264
  # this box into ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2.
237
265
  # Returns an Array of the private keys files used to generate the public keys.
238
266
  #
239
- # NOTE: authorize_keys disables safe-mode for this box while it runs.
267
+ # NOTE: authorize_keys disables safe-mode for this box while it runs
268
+ # which will hit you funky style if your using a single instance
269
+ # of Rye::Box in a multithreaded situation.
240
270
  #
241
271
  def authorize_keys
242
272
  added_keys = []
@@ -255,11 +285,32 @@ module Rye
255
285
  added_keys
256
286
  end
257
287
 
288
+ # Authorize the current user to login to the local machine via
289
+ # SSH without a password. This is the same functionality as
290
+ # authorize_keys except run with local shell commands.
291
+ def authorize_keys_local
292
+ added_keys = []
293
+ Rye.keys.each do |key|
294
+ path = key[2]
295
+ debug "# Public key for #{path}"
296
+ k = Rye::Key.from_file(path).public_key.to_ssh2
297
+ Rye.shell(:mkdir, :p, :m, '700', '$HOME/.ssh') # Silently create dir if it doesn't exist
298
+ Rye.shell(:echo, "'#{k}' >> $HOME/.ssh/authorized_keys")
299
+ Rye.shell(:echo, "'#{k}' >> $HOME/.ssh/authorized_keys2")
300
+ Rye.shell(:chmod, '-R', '0600', '$HOME/.ssh/authorized_keys*')
301
+ added_keys << path
302
+ end
303
+ added_keys
304
+ end
305
+
258
306
  # A handler for undefined commands.
259
307
  # Raises Rye::CommandNotFound exception.
260
308
  def method_missing(meth, *args, &block)
261
309
  raise Rye::CommandNotFound, "#{meth.to_s} (args: #{args.join(' ')})"
262
310
  end
311
+ def preview_command(*args)
312
+ prep_args(*args).join(' ')
313
+ end
263
314
 
264
315
  private
265
316
 
@@ -300,18 +351,9 @@ module Rye
300
351
  def run_command(*args)
301
352
  debug "run_command with keys: #{Rye.keys.inspect}"
302
353
 
303
- connect if !@ssh || @ssh.closed?
304
- args = args.flatten.compact
305
- args = args.first.split(/\s+/) if args.size == 1
306
- cmd = args.shift
307
-
308
- # Symbols to switches. :l -> -l, :help -> --help
309
- args.collect! do |a|
310
- a = "-#{a}" if a.is_a?(Symbol) && a.to_s.size == 1
311
- a = "--#{a}" if a.is_a?(Symbol)
312
- a
313
- end
354
+ cmd, args = prep_args(*args)
314
355
 
356
+ connect if !@ssh || @ssh.closed?
315
357
  raise Rye::NotConnected, @host unless @ssh && !@ssh.closed?
316
358
 
317
359
  cmd_clean = Rye.escape(@safe, cmd, args)
@@ -336,6 +378,24 @@ module Rye
336
378
  end
337
379
  alias :cmd :run_command
338
380
 
381
+
382
+
383
+ # Takes a list of arguments appropriate for run_command or
384
+ # preview_command and returns: [cmd, args]
385
+ def prep_args(*args)
386
+ args = args.flatten.compact
387
+ args = args.first.split(/\s+/) if args.size == 1
388
+ cmd = args.shift
389
+
390
+ # Symbols to switches. :l -> -l, :help -> --help
391
+ args.collect! do |a|
392
+ a = "-#{a}" if a.is_a?(Symbol) && a.to_s.size == 1
393
+ a = "--#{a}" if a.is_a?(Symbol)
394
+ a
395
+ end
396
+ [cmd, args]
397
+ end
398
+
339
399
  # Executes +command+ via SSH
340
400
  # Returns an Array with 4 elements: [stdout, stderr, exit code, exit signal]
341
401
  def net_ssh_exec!(command)
data/lib/rye/cmd.rb CHANGED
@@ -25,6 +25,8 @@ module Rye;
25
25
  #def rm(*args); cmd('rm', args); end
26
26
  def ps(*args); cmd('ps', args); end
27
27
  def sh(*args); cmd('sh', args); end
28
+ def df(*args); cmd('df', args); end
29
+ def du(*args); cmd('du', args); end
28
30
 
29
31
  def env(*args); cmd "env"; end
30
32
  def pwd(*args); cmd "pwd"; end
@@ -44,15 +46,17 @@ module Rye;
44
46
  def bash(*args); cmd('bash', args); end
45
47
  def echo(*args); cmd('echo', args); end
46
48
  def test(*args); cmd('test', args); end
49
+ def mkfs(*args); cmd('mkfs', args); end
47
50
 
48
- def mount(*args); cmd("mount"); end
51
+ def mount(*args); cmd("mount", args); end
49
52
  def sleep(seconds=1); cmd("sleep", seconds); end
50
53
  def mkdir(*args); cmd('mkdir', args); end
51
54
  def touch(*args); cmd('touch', args); end
52
55
  def uname(*args); cmd('uname', args); end
53
56
  def chmod(*args); cmd('chmod', args); end
54
57
 
55
- def uptime(*args); cmd("uptime"); end
58
+ def umount(*args); cmd("umount", args); end
59
+ def uptime(*args); cmd("uptime", args); end
56
60
  def python(*args); cmd('python', args); end
57
61
  def printenv(*args); cmd('printenv', args); end
58
62
  def hostname(*args); cmd('hostname', args); end
data/lib/rye/set.rb CHANGED
@@ -90,8 +90,12 @@ module Rye
90
90
  run_command(:cd, key)
91
91
  self
92
92
  end
93
- alias :cd :'[]'
94
-
93
+ # alias :cd :'[]' # fix for jruby
94
+ def cd(key=nil)
95
+ run_command(:cd, key)
96
+ self
97
+ end
98
+
95
99
  # Catches calls to Rye::Box commands. If +meth+ is the name of an
96
100
  # instance method defined in Rye::Cmd then we call it against all
97
101
  # the boxes in +@boxes+. Otherwise this method raises a
@@ -118,6 +122,7 @@ module Rye
118
122
 
119
123
  # Run the command on all boxes in parallel
120
124
  def run_command_parallel(meth, *args)
125
+ p @boxes
121
126
  debug "P: #{meth} on #{@boxes.size} boxes (#{@boxes.collect {|b| b.host }.join(', ')})"
122
127
  threads = []
123
128
 
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.4.3"
4
+ s.version = "0.5.0"
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: delano-rye
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum