delano-rye 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -4,6 +4,12 @@ TODO
4
4
 
5
5
  * Fingerprints: ssh-keygen -l -f id_rsa_repos.pub
6
6
 
7
+ #### 0.6.1 (2009-04-29) #############################
8
+
9
+ * ADDED: Prints message to STDERR when passwordless login fails.
10
+ * ADDED: Highline 1.5.1 to vendor to fix the Ruby 1.9 issue (Highline
11
+ 1.5.1 is not released as a gem yet)
12
+ * CHANGE: Cleaned examples and links in README
7
13
 
8
14
  #### 0.6.0 (2009-04-28) #############################
9
15
 
data/README.rdoc CHANGED
@@ -4,7 +4,6 @@ Safely run SSH commands on a bunch of machines at the same time (from Ruby).
4
4
 
5
5
  Rye is similar to Rush[http://rush.heroku.com] but everything happens over SSH (no HTTP daemon) and the default settings are less powerful (for safety). For example, file globs and the "rm" command are disabled so unless otherwise specified, you can't do this: <tt>rbox.rm('-rf', '/etc/**/*')</tt>.
6
6
 
7
- See the examples below (which are taken from bin/try).
8
7
 
9
8
  == Installation
10
9
 
@@ -15,145 +14,48 @@ One of:
15
14
  $ git clone git://github.com/delano/rye.git
16
15
 
17
16
 
18
- == EXAMPLE 1 -- Basic Usage
19
-
20
- rbox = Rye::Box.new('localhost')
21
-
22
- # Commands are run as methods on the Rye::Box object
23
- puts rbox.uptime # => 11:02 up 16:01, 3 users
24
-
25
- # The response value for all commands is a Rye::Rap object. The rap is a
26
- # subclass of Array so you can treat it as an Array, but it can also act
27
- # like a String if there's only one element.
28
- puts rbox.ls('rye.test') # => ""
29
- puts rbox.ls('rye.test').stderr # => ls: rye.test: No such file or directory
30
-
31
- puts rbox.touch('rye.test') # => ""
32
- puts rbox.rm('rye.test') # => ""
33
-
34
- # You can change directories
35
- puts rbox.pwd # => /home/rye
36
- puts rbox['/usr/bin'].pwd # => /usr/bin
37
- puts rbox.pwd # => /usr/bin
38
- puts rbox.cd('/home/rye').pwd # => /home/rye
39
-
40
- # You can specify environment variables
41
- rbox.setenv(:RYE, "Forty Creek")
42
- rbox.env # => ['HOME=/home/rye', 'RYE=Forty Creek', ...]
43
-
44
- # The commands method returns an Array of available commands:
45
- puts rbox.commands.join(', ') # => pwd, touch, echo, wc, ...
46
-
47
- # When you're done you can disconnect explicitly.
48
- # (Although Rye does this automatically at exit.)
49
- rbox.disconnect
17
+ See bin/try for examples!
50
18
 
51
19
 
52
- == EXAMPLE 2 -- Disabling Safe-Mode
20
+ == EXAMPLE 1 -- SSH Authorization
53
21
 
54
- rbox_safe = Rye::Box.new('localhost')
55
- rbox_wild = Rye::Box.new('localhost', :safe => false)
22
+ Does it annoy you to manually authorize remote SSH accounts? Rye can help!
56
23
 
57
- # Safe-mode is enabled by default. In safe-mode, all command
58
- # arguments are thoroughly escaped. This prevents access to
59
- # environment variables and file globs (among other things).
60
- p rbox_safe.echo('$HOME') # => "$HOME"
61
- p rbox_safe['/etc'].ls('host*') rescue Rye::CommandError # Doesn't exist
62
- p rbox_safe.ls('-l | wc -l') rescue Rye::CommandError # => '|' is not a valid ls arg
24
+ Enable passwordless logins to HOST1 and HOST2:
63
25
 
64
- # Here's the same commands with safe-mode disabled:
65
- p rbox_wild.echo('$HOME') # => "/home/rye"
66
- p rbox_wild['/etc'].ls('host*') # => ["hostconfig", "hosts"]
67
- p rbox_wild.ls('-l | wc -l') # => 110
68
- p rbox_wild.echo('$HOME > /tmp/rye-home') # =>
69
- p rbox_wild.cat('/tmp/rye-home') # => "/home/rye"
26
+ $ rye authorize HOST1 HOST2
70
27
 
28
+ This will copy your public SSH keys to the <tt>~/.ssh/authorized_keys</tt> and <tt>~/.ssh/authorized_keys2</tt> files on the remote machine(s).
71
29
 
72
- == EXAMPLE 3 -- Custom Commands
73
-
74
- rbox = Rye::Box.new('localhost')
75
- rbox.add_keys('/private/key/path') # Specify additional private keys
30
+ See <tt>rye -h</tt> for more info
76
31
 
77
- # There's currently no rye900 command
78
- p rbox.commands.member?('rye9000') # => false
79
32
 
80
- # But we can add our own commands to the Rye::Cmd class. They
81
- # automatically become available to all Rye::Box objects.
82
- module Rye::Cmd
83
- def rye9000(*args)
84
- run_command("ls", args)
85
- end
86
- def somescript(*args)
87
- run_command("/path/to/my/script", args)
88
- end
89
- end
33
+ == EXAMPLE 2 -- Basic Usage
90
34
 
91
- # We can now run rye9000 (with arguments)
92
- p rbox.rye9000('-a') # => [".", "..", ".bashrc", ...]
93
- p rbox.commands.member?('rye9000') # => true
94
-
35
+ rbox = Rye::Box.new('localhost')
36
+ rbox.uptime # => 11:02 up 16:01, 3 users
37
+ rbox['/usr/bin'].pwd # => /usr/bin
38
+
39
+ You can specify environment variables
95
40
 
96
- == EXAMPLE 4 -- Accessing Multiple Machines
41
+ rbox.setenv(:RYE, "Forty Creek")
42
+ rbox.env # => ['HOME=/home/rye', 'RYE=Forty Creek', ...]
43
+
44
+
45
+ == EXAMPLE 3 -- Accessing Multiple Machines
97
46
 
98
47
  rset = Rye::Set.new
99
48
  rbox = Rye::Box.new
100
49
 
101
- rset.add_keys('/private/key/path') # For passwordless logins
102
50
  rset.add_boxes(rbox, 'localhost') # Add boxes as hostnames or objects
103
51
 
104
- # Calling methods on Rye::Set objects is very similar to calling them on
105
- # Rye::Box objects. In fact, it's identical:
52
+ Calling methods on Rye::Set objects is very similar to calling them on Rye::Box objects. In fact, it's identical:
53
+
106
54
  p rset.uptime # => [[14:19:02 up 32 days, 19:35 ...], [14:19:02 up 30 days, 01:35]]
107
55
  p rset['/etc'].ls # => [['file1', 'file2', ...], ['life1', 'life2', ...]]
108
56
 
109
- # Like Rye::Box, the response value is a Rye::Rap object containing the
110
- # responses from each box. Each response is itself a Rye::Rap object.
111
- unames = rset.uname
112
- p unames # => [["Darwin"], ["Darwin"]]
113
- puts unames.class # => Rye::Rap
114
57
 
115
- # The Rye::Rap object also keeps a reference to the object that called the
116
- # command. In this case, it will keep a reference to Rye::Set:
117
- puts unames.set.class # => Rye::Set
118
- puts unames.set == rset # => true
119
- puts unames.size # => 2
120
- puts unames.first # => Darwin
121
- puts unames.first.class # => Rye::Rap
122
- puts unames.first.box.class # => Rye::Box
123
- puts unames.first.box == rbox # => true
124
-
125
- # Envrionment variables can be set the same way as with Rye::Box
126
- rset.setenv(:RYE, "Forty Creek")
127
- p rset.env.first.select { |env| env =~ /RYE/ } # => ["RYE=Forty Creek"]
128
-
129
-
130
- == EXAMPLE 5 -- ERROR HANDLING
131
-
132
- rbox = Rye::Box.new('localhost', :safe => false)
133
-
134
- # Rye follows the standard convention of taking exception to a non-zero
135
- # exit code by raising a Rye::CommandError. In this case, rye9000.test
136
- # is not found by the ls command.
137
- begin
138
- rbox.ls('rye9000.test')
139
- rescue Rye::CommandError => ex
140
- puts ex.exit_code # => 1
141
- puts ex.stderr # => ls: rye.test: No such file or directory
142
- end
143
-
144
- # The Rye:Rap response objects also give you the STDOUT and STDERR
145
- # content separately. Here we redirect STDOUT to STDERR, so this
146
- # will return nothing:
147
- puts rbox.uname('-a 1>&2').stdout # =>
148
-
149
- # It all went to STDERR:
150
- puts rbox.uname('-a 1>&2').stderr # => Darwin ryehost 9.6.0 ...
151
-
152
- # There were no actual error so the exit code should be 0.
153
- puts rbox.uname('-a 1>&2').exit_code # => 0
154
-
155
-
156
- == EXAMPLE 6 -- FILE TRANSFERS
58
+ == EXAMPLE 4 -- FILE TRANSFERS
157
59
 
158
60
  rbox = Rye::Box.new("localhost", :info => true)
159
61
 
@@ -166,7 +68,7 @@ One of:
166
68
  applejack = StringIO.new("Some in-memory content")
167
69
  rbox.upload(applejack, "#{dir_upload}/applejack.txt")
168
70
 
169
- p rbox.ls(dir_upload) # => [README.rdoc, LICENSE.txt, applejack.txt]
71
+ p rbox.ls(dir_upload) # => [README.rdoc, LICENSE.txt, applejack.txt]
170
72
  p rbox.cat("#{dir_upload}/applejack.txt") # => "Some in-memory content"
171
73
 
172
74
  filecontent = StringIO.new
@@ -174,32 +76,13 @@ One of:
174
76
 
175
77
  p filecontent.read
176
78
 
177
- == EXAMPLE 7 -- rye
178
-
179
- Rye comes with a command-line utility called <tt>rye</tt>.
180
-
181
- # Prints the paths to your private keys
182
- $ rye keys
183
-
184
- # Prints the server host keys (suitable for ~/.ssh/known_hosts)
185
- $ rye hostkey HOST1 HOST2
186
-
187
- # Add your public keys to authorized_keys and authorized_keys2
188
- # on a remote machine
189
- $ rye authorize HOST1 HOST2
190
- More info:
191
-
192
- $ rye -h
193
- $ rye COMMAND -h
194
- $ rye show-commands
195
-
196
79
 
197
80
  == About Safe-Mode
198
81
 
199
82
  In safe-mode:
200
83
 
201
84
  * You can't use file globs. This means you can't do this: <tt>rbox.ls('*.rb')</tt>. <tt>~</tt> also doesn't work!
202
- * Command arguments cannot contain environment variables (however, environment variables are available to the commands you run). This means you can't do this: <tt>rbox.echo('$HOME')</tt>.
85
+ * You can't use environment variables as arguments. This means you can't do this: <tt>rbox.echo('$HOME')</tt>. However, environment variables are available to the commands you run.
203
86
  * Pipes and operators don't work: <tt>|, &&, >, <, ||, ~</tt>, etc...
204
87
  * Backticks don't work either: <tt>procs=`ps aux`</tt>
205
88
 
@@ -221,28 +104,28 @@ Rye permits only a limited number of system commands to be run. This default whi
221
104
  * highline
222
105
  * drydock
223
106
 
107
+
224
108
  == Known Issues
225
109
 
226
110
  This list will grow. If you find one let me know!
227
111
 
228
112
  * Rye doesn't read the ~/.ssh/config file yet
229
- * Highline 1.5 not working in Ruby 1.9 (password prompts hang)
230
113
  * Rye uses OpenSSL's ssh-agent (if it exists). Rye starts it up as a child process and shuts it down using at_exit. If you have code in an at_exit that rely's on Rye, make sure your code runs before Rye's at_exit block is called. For example, Drydock uses at_exit too which is why in bin/rye you can see that Drydock is called explicitly so that Rye's at_exit is executed after Drydock executes a command.
231
114
 
115
+
232
116
  == Thanks
233
117
 
234
118
  * Solutious Incorporated (http://solutious.com) for all the orange juice.
235
- * http://github.com/adamwiggins/rush
236
- * http://github.com/jamis/capistrano/blob/master/lib/capistrano/shell.rb
237
- * http://www.nofluffjuststuff.com/blog/david_bock/2008/10/ruby_s_closure_cleanup_idiom_and_net_ssh.html
238
- * http://groups.google.com/group/ruby-talk-google/browse_thread/thread/674a6f6de15ceb49?pli=1
239
- * http://paste.lisp.org/display/6912
119
+ * Kalin Harvey (http://rely.ca)
120
+ * Rush[http://github.com/adamwiggins/rush]
121
+ * Capistrano[http://github.com/jamis/capistrano/blob/master/lib/capistrano/shell.rb]
122
+
240
123
 
241
124
  == More Info
242
125
 
243
- * http://github.com/delano/rye
244
- * http://delano.github.com/rye
245
- * http://www.youtube.com/watch?v=_StUVh6ENuw
126
+ * GitHub[http://github.com/delano/rye]
127
+ * Rdocs[http://delano.github.com/rye]
128
+ * Inspiration[http://www.youtube.com/watch?v=_StUVh6ENuw]
246
129
 
247
130
  == Credits
248
131
 
data/bin/rye CHANGED
@@ -35,7 +35,8 @@ after do
35
35
 
36
36
  end
37
37
 
38
- desc "Add your public keys to one or more remote machines"
38
+ about "Add your public keys to one or more remote machines"
39
+ usage "rye authorize [-u username] host"
39
40
  option :u, :user, String, "Username"
40
41
  argv :hostname
41
42
  command :authorize do |obj|
@@ -56,7 +57,7 @@ command :authorize do |obj|
56
57
  end
57
58
  command_alias :authorize, :authorise
58
59
 
59
- desc "Add your public keys to your current account on this machine"
60
+ about "Add your public keys to your current account on this machine"
60
61
  command :authorize_local do |obj|
61
62
  user = Rye.sysinfo.user
62
63
  puts "Authorizing #{user}@localhost"
@@ -68,11 +69,11 @@ end
68
69
  command_alias :local_authorize, :local_authorise
69
70
 
70
71
 
71
- desc "Generate a public key from a private key"
72
+ about "Generate a public key from a private key"
72
73
 
73
74
 
74
75
 
75
- desc "Fetch the host keys for remote machines (suitable for your ~/.ssh/known_hosts file)"
76
+ about "Fetch the host keys for remote machines (suitable for your ~/.ssh/known_hosts file)"
76
77
  usage "rye hostkey HOSTNAME [HOSTNAME2 HOSTNAME3 ...]"
77
78
  argv :hostname
78
79
  command :hostkeys do |obj|
@@ -84,14 +85,14 @@ end
84
85
  command_alias :hostkeys, :hostkey
85
86
 
86
87
 
87
- desc "Display your private keys"
88
+ about "Display your private keys"
88
89
  command :keys do |obj|
89
90
  Rye.keys.each do |key|
90
91
  puts key.join(' ')
91
92
  end
92
93
  end
93
94
 
94
- desc "Display your public SSH keys"
95
+ about "Display your public SSH keys"
95
96
  usage "rye pubkeys [--pem] [KEYPATH]"
96
97
  option :p, :pem, "Output in PEM format"
97
98
  argv :keypath
data/lib/rye.rb CHANGED
@@ -1,5 +1,7 @@
1
1
 
2
- require 'rubygems' unless defined? Gem
2
+ # Temporary fix before Highline 1.5.1 is release. This fixes
3
+ # a the issue with Ruby 1.9 that causes the prompts to hang.
4
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'vendor', 'highline-1.5.1')
3
5
 
4
6
  require 'tempfile'
5
7
  require 'logger'
@@ -32,6 +34,12 @@ require 'sys'
32
34
  # * See +bin/try+ for a bunch of working examples.
33
35
  # * See Rye::Box#initialize for info about disabling safe-mode.
34
36
  #
37
+ #--
38
+ # The following posts were really helpful when I first wrote Rye:
39
+ # http://www.nofluffjuststuff.com/blog/david_bock/2008/10/ruby_s_closure_cleanup_idiom_and_net_ssh.html
40
+ # http://groups.google.com/group/ruby-talk-google/browse_thread/thread/674a6f6de15ceb49?pli=1
41
+ # http://paste.lisp.org/display/6912
42
+ #++
35
43
  module Rye
36
44
  extend self
37
45
 
data/lib/rye/box.rb CHANGED
@@ -182,6 +182,7 @@ module Rye
182
182
  print "\a" if retried == 0 && @info # Ring the bell once
183
183
  retried += 1
184
184
  if STDIN.tty? && retried <= 3
185
+ STDERR.puts "Passwordless login failed for #{@opts[:user]}"
185
186
  @opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }
186
187
  @opts[:auth_methods] ||= []
187
188
  @opts[:auth_methods] << 'password'
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.6.0"
4
+ s.version = "0.6.1"
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.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum