rye 0.9.7 → 0.9.8
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.tar.gz.sig +0 -0
- data/CHANGES.txt +44 -38
- data/README.rdoc +44 -30
- data/Rakefile +41 -82
- data/VERSION +1 -0
- data/gem-public_cert.pem +20 -0
- data/lib/rye.rb +74 -52
- data/lib/rye/box.rb +7 -4
- data/lib/rye/dsl.rb +100 -0
- data/rye.gemspec +95 -55
- data/try/10_basic_tryouts.rb +44 -0
- data/try/12_batch_tryouts.rb +26 -0
- data/try/13_set_tryouts.rb +42 -0
- data/try/14_auth_methods_tryouts.rb +28 -0
- data/try/15_file_tryouts.rb +12 -0
- data/try/20_file_transfer_tryouts.rb +46 -0
- data/try/25_template_upload.rb +37 -0
- data/try/30_safemode_tryouts.rb +85 -0
- data/try/35_basics_with_hop.rb +36 -0
- data/try/70_rye_cli_tryouts.rb +0 -0
- data/try/copying.rb +18 -0
- data/try/keys.rb +141 -0
- data/tst/10-key1 +27 -0
- data/tst/10-key1.pub +1 -0
- data/tst/10-key2 +30 -0
- data/tst/10-key2.pub +1 -0
- data/tst/10_keys_test.rb +88 -0
- data/tst/50_rset_test.rb +54 -0
- data/tst/60-file.mp3 +0 -0
- data/tst/60_rbox_transfer_test.rb +53 -0
- data/tst/65_rbox_file_append_test.rb +53 -0
- data/tst/70_rbox_env_test.rb +19 -0
- data/tst/dsl_example.rb +80 -0
- data/tst/rye.rb +13 -0
- data/tst/shell.rb +280 -0
- data/tst/shell2.rb +278 -0
- data/tst/shell3.rb +280 -0
- data/tst/test_hop.rb +25 -0
- metadata +86 -25
- metadata.gz.sig +0 -0
- data/bin/try +0 -246
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.8
|
data/gem-public_cert.pem
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ8wDQYDVQQDDAZkZWxh
|
3
|
+
bm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZFgNj
|
4
|
+
b20wHhcNMTMwMjA2MTE1NzQ1WhcNMTQwMjA2MTE1NzQ1WjBBMQ8wDQYDVQQDDAZk
|
5
|
+
ZWxhbm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZ
|
6
|
+
FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg1hMtl0XsMuUK
|
7
|
+
AKTgYWv3gjj7vuEsE2EjT+vyBg8/LpqVVwZziiaebJT9IZiQ+sCFqbiakj0b53pI
|
8
|
+
hg1yOaBEmH6/W0L7rwzqaRV9sW1eJs9JxFYQCnd67zUnzj8nnRlOjG+hhIG+Vsij
|
9
|
+
npsGbt28pefuNZJjO5q2clAlfSniIIHfIsU7/StEYu6FUGOjnwryZ0r5yJlr9RrE
|
10
|
+
Gs+q0DW8QnZ9UpAfuDFQZuIqeKQFFLE7nMmCGaA+0BN1nLl3fVHNbLHq7Avk8+Z+
|
11
|
+
ZuuvkdscbHlO/l+3xCNQ5nUnHwq0ADAbMLOlmiYYzqXoWLjmeI6me/clktJCfN2R
|
12
|
+
oZG3UQvvAgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFMSJOEtHzE4l0azv
|
13
|
+
M0JK0kKNToK1MAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAtOdE73qx
|
14
|
+
OH2ydi9oT2hS5f9G0y1Z70Tlwh+VGExyfxzVE9XwC+iPpJxNraiHYgF/9/oky7ZZ
|
15
|
+
R9q0/tJneuhAenZdiQkX7oi4O3v9wRS6YHoWBxMPFKVRLNTzvVJsbmfpCAlp5/5g
|
16
|
+
ps4wQFy5mibElGVlOobf/ghqZ25HS9J6kd0/C/ry0AUtTogsL7TxGwT4kbCx63ub
|
17
|
+
3vywEEhsJUzfd97GCABmtQfRTldX/j7F1z/5wd8p+hfdox1iibds9ZtfaZA3KzKn
|
18
|
+
kchWN9B6zg9r1XMQ8BM2Jz0XoPanPe354+lWwjpkRKbFow/ZbQHcCLCq24+N6b6g
|
19
|
+
dgKfNDzwiDpqCA==
|
20
|
+
-----END CERTIFICATE-----
|
data/lib/rye.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# vim: set sw=2 ts=2 :
|
2
2
|
|
3
|
+
module Rye
|
4
|
+
unless defined?(Rye::HOME)
|
5
|
+
HOME = File.expand_path( File.join(File.dirname(__FILE__), '..') )
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
require 'logger'
|
4
10
|
require 'thread'
|
5
11
|
require 'base64'
|
@@ -19,11 +25,11 @@ require 'esc'
|
|
19
25
|
#
|
20
26
|
# Safely run remote commands via SSH in Ruby.
|
21
27
|
#
|
22
|
-
# Rye is similar to Rush[http://rush.heroku.com] but everything
|
28
|
+
# Rye is similar to Rush[http://rush.heroku.com] but everything
|
23
29
|
# happens over SSH (no HTTP daemon) and the default settings are
|
24
30
|
# less dangerous (for safety). For example, file globs and the
|
25
|
-
# "rm" command are disabled so unless otherwise specified, you
|
26
|
-
# can't do this: <tt>rbox.rm('/etc/**/*')</tt>.
|
31
|
+
# "rm" command are disabled so unless otherwise specified, you
|
32
|
+
# can't do this: <tt>rbox.rm('/etc/**/*')</tt>.
|
27
33
|
#
|
28
34
|
# However, you can do this:
|
29
35
|
#
|
@@ -31,7 +37,7 @@ require 'esc'
|
|
31
37
|
# rset.add_boxes('host1', 'host2', 'host3', 'host4')
|
32
38
|
# rset.ps('aux')
|
33
39
|
#
|
34
|
-
# * See +bin/try+ for a bunch of working examples.
|
40
|
+
# * See +bin/try+ for a bunch of working examples.
|
35
41
|
# * See Rye::Box#initialize for info about disabling safe-mode.
|
36
42
|
#
|
37
43
|
#--
|
@@ -42,22 +48,38 @@ require 'esc'
|
|
42
48
|
#++
|
43
49
|
module Rye
|
44
50
|
extend self
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
|
52
|
+
module VERSION
|
53
|
+
@path = File.join(Rye::HOME, 'VERSION')
|
54
|
+
class << self
|
55
|
+
attr_reader :version, :path
|
56
|
+
def version
|
57
|
+
@version || read_version
|
58
|
+
end
|
59
|
+
def read_version
|
60
|
+
return if @version
|
61
|
+
@version = File.read(path).strip!
|
62
|
+
end
|
63
|
+
def prerelease?() false end
|
64
|
+
def to_a() version.split('.') end
|
65
|
+
def to_s() version end
|
66
|
+
def inspect() version end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
48
70
|
@@sysinfo = nil
|
49
71
|
@@agent_env = Hash.new # holds ssh-agent env vars
|
50
72
|
@@mutex = Mutex.new # for synchronizing threads
|
51
|
-
|
73
|
+
|
52
74
|
# Accessor for an instance of SystemInfo
|
53
75
|
def Rye.sysinfo
|
54
76
|
@@sysinfo = SysInfo.new if @@sysinfo.nil?
|
55
77
|
@@sysinfo
|
56
78
|
end
|
57
|
-
|
79
|
+
|
58
80
|
# Accessor for an instance of SystemInfo
|
59
81
|
def sysinfo; Rye.sysinfo end
|
60
|
-
|
82
|
+
|
61
83
|
class RyeError < RuntimeError; end
|
62
84
|
class NoBoxes < RyeError; end
|
63
85
|
class NoPassword < RyeError
|
@@ -82,19 +104,19 @@ module Rye
|
|
82
104
|
def stdout; @rap.stdout if @rap; end
|
83
105
|
def exit_status; @rap.exit_status if @rap; end
|
84
106
|
end
|
85
|
-
|
86
|
-
# Reload Rye dynamically. Useful with irb.
|
87
|
-
# NOTE: does not reload rye.rb.
|
107
|
+
|
108
|
+
# Reload Rye dynamically. Useful with irb.
|
109
|
+
# NOTE: does not reload rye.rb.
|
88
110
|
def reload
|
89
111
|
pat = File.join(File.dirname(__FILE__), 'rye')
|
90
112
|
%w{key rap cmd box set hop}.each {|lib| load File.join(pat, "#{lib}.rb") }
|
91
113
|
end
|
92
|
-
|
114
|
+
|
93
115
|
def mutex
|
94
116
|
@@mutex
|
95
117
|
end
|
96
|
-
|
97
|
-
# Looks for private keys in +path+ and returns
|
118
|
+
|
119
|
+
# Looks for private keys in +path+ and returns an Array of paths
|
98
120
|
# to the files it finds. Raises an Exception if path does not exist.
|
99
121
|
# If path is a file rather than a directory, it will check whether
|
100
122
|
# that single file is a private key.
|
@@ -105,12 +127,12 @@ module Rye
|
|
105
127
|
else
|
106
128
|
files = [path]
|
107
129
|
end
|
108
|
-
|
130
|
+
|
109
131
|
files = files.select do |file|
|
110
132
|
next if File.directory?(file)
|
111
133
|
pk = nil
|
112
134
|
begin
|
113
|
-
tmp = Rye::Key.from_file(file)
|
135
|
+
tmp = Rye::Key.from_file(file)
|
114
136
|
pk = tmp if tmp.private?
|
115
137
|
rescue OpenSSL::PKey::PKeyError
|
116
138
|
end
|
@@ -118,15 +140,15 @@ module Rye
|
|
118
140
|
end
|
119
141
|
files || []
|
120
142
|
end
|
121
|
-
|
122
|
-
# Add one or more private keys to the SSH Agent.
|
123
|
-
# * +keys+ one or more file paths to private keys used for passwordless logins.
|
143
|
+
|
144
|
+
# Add one or more private keys to the SSH Agent.
|
145
|
+
# * +keys+ one or more file paths to private keys used for passwordless logins.
|
124
146
|
def add_keys(*keys)
|
125
147
|
keys = keys.flatten.compact || []
|
126
148
|
return if keys.empty?
|
127
149
|
Rye.shell("ssh-add", keys)
|
128
150
|
end
|
129
|
-
|
151
|
+
|
130
152
|
# Returns an Array of info about the currently available
|
131
153
|
# SSH keys, as provided by the SSH Agent.
|
132
154
|
#
|
@@ -142,25 +164,25 @@ module Rye
|
|
142
164
|
#end
|
143
165
|
Dir.glob(File.join(Rye.sysinfo.home, '.ssh', 'id_*sa'))
|
144
166
|
end
|
145
|
-
|
167
|
+
|
146
168
|
def remote_host_keys(*hostnames)
|
147
169
|
hostnames = hostnames.flatten.compact || []
|
148
170
|
return if hostnames.empty?
|
149
171
|
Rye.shell("ssh-keyscan", hostnames)
|
150
172
|
end
|
151
|
-
|
152
|
-
# Takes a command with arguments and returns it in a
|
153
|
-
# single String with escaped args and some other stuff.
|
154
|
-
#
|
173
|
+
|
174
|
+
# Takes a command with arguments and returns it in a
|
175
|
+
# single String with escaped args and some other stuff.
|
176
|
+
#
|
155
177
|
# * +cmd+ The shell command name or absolute path.
|
156
|
-
# * +args+ an Array of command arguments.
|
178
|
+
# * +args+ an Array of command arguments.
|
157
179
|
#
|
158
180
|
# The command is searched for in the local PATH (where
|
159
181
|
# Rye is running). An exception is raised if it's not
|
160
182
|
# found. NOTE: Because this happens locally, you won't
|
161
183
|
# want to use this method if the environment is quite
|
162
184
|
# different from the remote machine it will be executed
|
163
|
-
# on.
|
185
|
+
# on.
|
164
186
|
#
|
165
187
|
# The command arguments are passed through Escape.shell_command
|
166
188
|
# (that means you can't use environment variables or asterisks).
|
@@ -177,32 +199,32 @@ module Rye
|
|
177
199
|
end
|
178
200
|
Rye.escape(@safe, found_cmd, *args)
|
179
201
|
end
|
180
|
-
|
181
|
-
# An all ruby implementation of unix "which" command.
|
202
|
+
|
203
|
+
# An all ruby implementation of unix "which" command.
|
182
204
|
#
|
183
205
|
# * +executable+ the name of the executable
|
184
|
-
#
|
206
|
+
#
|
185
207
|
# Returns the absolute path if found in PATH otherwise nil.
|
186
208
|
def which(executable)
|
187
209
|
return unless executable.is_a?(String)
|
188
210
|
return executable if Rye.sysinfo.os == :windows
|
189
211
|
#return executable if File.exists?(executable) # SHOULD WORK, MUST TEST
|
190
212
|
shortname = File.basename(executable)
|
191
|
-
dir = Rye.sysinfo.paths.select do |path| # dir contains all of the
|
192
|
-
next unless File.exists? path # occurrences of shortname
|
193
|
-
Dir.new(path).entries.member?(shortname) # found in the paths.
|
213
|
+
dir = Rye.sysinfo.paths.select do |path| # dir contains all of the
|
214
|
+
next unless File.exists? path # occurrences of shortname
|
215
|
+
Dir.new(path).entries.member?(shortname) # found in the paths.
|
194
216
|
end
|
195
217
|
File.join(dir.first, shortname) unless dir.empty? # Return just the first
|
196
218
|
end
|
197
|
-
|
219
|
+
|
198
220
|
# Execute a local system command (via the shell, not SSH)
|
199
|
-
#
|
221
|
+
#
|
200
222
|
# * +cmd+ the executable path (relative or absolute)
|
201
223
|
# * +args+ Array of arguments to be sent to the command. Each element
|
202
224
|
# is one argument:. i.e. <tt>['-l', 'some/path']</tt>
|
203
225
|
#
|
204
226
|
# NOTE: shell is a bit paranoid so it escapes every argument. This means
|
205
|
-
# you can only use literal values. That means no asterisks too.
|
227
|
+
# you can only use literal values. That means no asterisks too.
|
206
228
|
#
|
207
229
|
# Returns a Rye::Rap object.
|
208
230
|
#
|
@@ -227,27 +249,27 @@ module Rye
|
|
227
249
|
rap.add_exit_status($?)
|
228
250
|
rap
|
229
251
|
end
|
230
|
-
|
252
|
+
|
231
253
|
# Creates a string from +cmd+ and +args+. If +safe+ is true
|
232
|
-
# it will send them through Escape.shell_command otherwise
|
233
|
-
# it will return them joined by a space character.
|
254
|
+
# it will send them through Escape.shell_command otherwise
|
255
|
+
# it will return them joined by a space character.
|
234
256
|
def escape(safe, cmd, *args)
|
235
257
|
args = args.flatten.compact || []
|
236
258
|
safe ? Escape.shell_command(cmd, *args).to_s : [cmd, args].flatten.compact.join(' ')
|
237
259
|
end
|
238
|
-
|
260
|
+
|
239
261
|
def sshagent_info
|
240
262
|
@@agent_env
|
241
263
|
end
|
242
|
-
|
243
|
-
# Returns +str+ with the leading indentation removed.
|
264
|
+
|
265
|
+
# Returns +str+ with the leading indentation removed.
|
244
266
|
# Stolen from http://github.com/mynyml/unindent/ because it was better.
|
245
267
|
def without_indent(str)
|
246
268
|
indent = str.split($/).each {|line| !line.strip.empty? }.map {|line| line.index(/[^\s]/) }.compact.min
|
247
269
|
str.gsub(/^[[:blank:]]{#{indent}}/, '')
|
248
270
|
end
|
249
|
-
|
250
|
-
#
|
271
|
+
|
272
|
+
#
|
251
273
|
# Generates a string of random alphanumeric characters.
|
252
274
|
# * +len+ is the length, an Integer. Default: 8
|
253
275
|
# * +safe+ in safe-mode, ambiguous characters are removed (default: true):
|
@@ -259,7 +281,7 @@ module Rye
|
|
259
281
|
1.upto(len) { |i| str << chars[rand(chars.size-1)] }
|
260
282
|
str
|
261
283
|
end
|
262
|
-
|
284
|
+
|
263
285
|
class Tpl
|
264
286
|
attr_reader :src, :result, :basename
|
265
287
|
def initialize(src, basename='rye-template')
|
@@ -286,13 +308,13 @@ module Rye
|
|
286
308
|
end
|
287
309
|
def to_s() src end
|
288
310
|
end
|
289
|
-
|
290
|
-
private
|
291
|
-
|
311
|
+
|
312
|
+
private
|
313
|
+
|
292
314
|
Rye.reload
|
293
|
-
|
315
|
+
|
294
316
|
end
|
295
317
|
|
296
318
|
|
297
319
|
|
298
|
-
|
320
|
+
|
data/lib/rye/box.rb
CHANGED
@@ -106,6 +106,7 @@ module Rye
|
|
106
106
|
# * :password => the user's password (ignored if there's a valid private key)
|
107
107
|
# * :templates => the template engine to use for uploaded files. One of: :erb (default)
|
108
108
|
# * :sudo => Run all commands via sudo (default: false)
|
109
|
+
# * :password_prompt => Show a password prompt on auth failure (default: true)
|
109
110
|
#
|
110
111
|
# NOTE: +opts+ can also contain any parameter supported by
|
111
112
|
# Net::SSH.start that is not already mentioned above.
|
@@ -132,7 +133,8 @@ module Rye
|
|
132
133
|
:error => STDERR,
|
133
134
|
:getenv => true,
|
134
135
|
:templates => :erb,
|
135
|
-
:quiet => false
|
136
|
+
:quiet => false,
|
137
|
+
:password_prompt => true
|
136
138
|
}.merge(opts)
|
137
139
|
|
138
140
|
# Close the SSH session before Ruby exits. This will do nothing
|
@@ -150,8 +152,9 @@ module Rye
|
|
150
152
|
@rye_ostype, @rye_impltype = @rye_opts.delete(:ostype), @rye_opts.delete(:impltype)
|
151
153
|
@rye_quiet, @rye_sudo = @rye_opts.delete(:quiet), @rye_opts.delete(:sudo)
|
152
154
|
@rye_templates = @rye_opts.delete(:templates)
|
153
|
-
|
154
|
-
|
155
|
+
@rye_password_prompt = @rye_opts.delete(:password_prompt)
|
156
|
+
|
157
|
+
# Store the state of the terminal
|
155
158
|
@rye_stty_save = `stty -g`.chomp rescue nil
|
156
159
|
|
157
160
|
unless @rye_templates.nil?
|
@@ -684,7 +687,7 @@ module Rye
|
|
684
687
|
# only auth method
|
685
688
|
if @rye_opts[:auth_methods] == ["publickey"]
|
686
689
|
raise Net::SSH::AuthenticationFailed
|
687
|
-
elsif STDIN.tty? && retried <= 3
|
690
|
+
elsif @rye_password_prompt && (STDIN.tty? && retried <= 3)
|
688
691
|
STDERR.puts "Passwordless login failed for #{@rye_user}"
|
689
692
|
@rye_opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }.strip
|
690
693
|
@rye_opts[:auth_methods].push *['keyboard-interactive', 'password']
|
data/lib/rye/dsl.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'docile'
|
2
|
+
|
3
|
+
module Rye
|
4
|
+
class Set
|
5
|
+
def run cmd
|
6
|
+
instance_eval &@@command[cmd]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
@hosts, @hostsets, @contexts = {}, {}, {}
|
12
|
+
@parallel = nil
|
13
|
+
|
14
|
+
@@colors = false || ENV['COLORS'] || ENV['TERM'].match(/.*color.*/)
|
15
|
+
@@command = {}
|
16
|
+
|
17
|
+
def parallel state; @parallel = state; end
|
18
|
+
def colors state; @@colors = state; end
|
19
|
+
|
20
|
+
def host(hostname, *args, &block)
|
21
|
+
@hosts[hostname] = Rye::Box.new(hostname, *args) unless @hosts.key? hostname
|
22
|
+
Docile.dsl_eval(Rye::Set.new.add_box(@hosts[hostname]), &block) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def hostset(setname, *args, &block)
|
26
|
+
@hostsets[setname] = Rye::Set.new(setname) unless @hostsets.key? setname
|
27
|
+
args.each do |host|
|
28
|
+
@hosts[host] = Rye::Box.new(host) unless @hosts.key? host
|
29
|
+
@hostsets[setname].add_box @hosts[host] unless @hostsets[setname].boxes.include? @hosts[host]
|
30
|
+
end
|
31
|
+
if @parallel
|
32
|
+
@hostsets[setname].parallel = true
|
33
|
+
Docile.dsl_eval(@hostsets[setname], &block) if block_given?
|
34
|
+
else
|
35
|
+
@hostsets[setname].boxes.each do |host|
|
36
|
+
Docile.dsl_eval(Rye::Set.new.add_box(host), &block) if block_given?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def command_group(name, &block)
|
42
|
+
@@command[name] = Proc.new &block
|
43
|
+
end
|
44
|
+
|
45
|
+
def exit_status_check(cmd, opts={})
|
46
|
+
enable_quiet_mode
|
47
|
+
@pass = opts[:pass_str] || cmd.to_s + ' Passed Status Check'
|
48
|
+
@fail = opts[:fail_str] || cmd.to_s + ' Failed Status Check'
|
49
|
+
def results(obj, out)
|
50
|
+
if obj.exit_status == 0
|
51
|
+
info out, :altstring => @pass
|
52
|
+
else
|
53
|
+
err out, :altstring => @fail
|
54
|
+
end
|
55
|
+
end
|
56
|
+
out = execute cmd
|
57
|
+
if out[0].class == Rye::Rap
|
58
|
+
out.each do |rap|
|
59
|
+
results(rap, out)
|
60
|
+
end
|
61
|
+
elsif out.exit_status == 0
|
62
|
+
results(out, out)
|
63
|
+
end
|
64
|
+
disable_quiet_mode
|
65
|
+
end
|
66
|
+
|
67
|
+
def strwrap(msg, opts={})
|
68
|
+
out = ''
|
69
|
+
unless @@colors
|
70
|
+
msg.each do |str|
|
71
|
+
unless opts.key? :altstring
|
72
|
+
out += str.to_s.gsub!(/^/, "[#{str.obj.hostname}] ") + "\n"
|
73
|
+
else
|
74
|
+
out += "[#{str.obj.hostname}] #{opts[:altstring]}\n"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
else
|
78
|
+
msg.each do |str|
|
79
|
+
unless opts.key? :altstring
|
80
|
+
out += str.to_s.gsub!(/^(.*)$/, str.obj.hostname)
|
81
|
+
else
|
82
|
+
out += "#{str.obj.hostname} " + opts[:altstring]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
out
|
87
|
+
end
|
88
|
+
|
89
|
+
def info msg, *opts
|
90
|
+
STDOUT.puts strwrap(msg, *opts)
|
91
|
+
end
|
92
|
+
|
93
|
+
def err msg, *opts
|
94
|
+
STDOUT.puts strwrap(msg, *opts)
|
95
|
+
end
|
96
|
+
|
97
|
+
def debug msg, *opts
|
98
|
+
STDOUT.puts strwrap(msg, *opts)
|
99
|
+
end
|
100
|
+
|
data/rye.gemspec
CHANGED
@@ -1,61 +1,101 @@
|
|
1
|
-
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
2
7
|
s.name = "rye"
|
3
|
-
s.
|
4
|
-
|
5
|
-
s.
|
6
|
-
s.
|
7
|
-
s.
|
8
|
+
s.version = "0.9.8"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Delano Mandelbaum"]
|
12
|
+
s.cert_chain = ["gem-public_cert.pem"]
|
13
|
+
s.date = "2013-02-06"
|
14
|
+
s.description = "Run SSH commands on a bunch of machines at the same time (from Ruby)."
|
8
15
|
s.email = "delano@solutious.com"
|
9
|
-
s.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
s.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"CHANGES.txt",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"Rudyfile",
|
26
|
+
"VERSION",
|
27
|
+
"gem-public_cert.pem",
|
28
|
+
"lib/esc.rb",
|
29
|
+
"lib/rye.rb",
|
30
|
+
"lib/rye/box.rb",
|
31
|
+
"lib/rye/cmd.rb",
|
32
|
+
"lib/rye/dsl.rb",
|
33
|
+
"lib/rye/hop.rb",
|
34
|
+
"lib/rye/key.rb",
|
35
|
+
"lib/rye/rap.rb",
|
36
|
+
"lib/rye/set.rb",
|
37
|
+
"rye.gemspec",
|
38
|
+
"try/10_basic_tryouts.rb",
|
39
|
+
"try/12_batch_tryouts.rb",
|
40
|
+
"try/13_set_tryouts.rb",
|
41
|
+
"try/14_auth_methods_tryouts.rb",
|
42
|
+
"try/15_file_tryouts.rb",
|
43
|
+
"try/20_file_transfer_tryouts.rb",
|
44
|
+
"try/25_template_upload.rb",
|
45
|
+
"try/30_safemode_tryouts.rb",
|
46
|
+
"try/35_basics_with_hop.rb",
|
47
|
+
"try/70_rye_cli_tryouts.rb",
|
48
|
+
"try/copying.rb",
|
49
|
+
"try/keys.rb",
|
50
|
+
"tst/10-key1",
|
51
|
+
"tst/10-key1.pub",
|
52
|
+
"tst/10-key2",
|
53
|
+
"tst/10-key2.pub",
|
54
|
+
"tst/10_keys_test.rb",
|
55
|
+
"tst/50_rset_test.rb",
|
56
|
+
"tst/60-file.mp3",
|
57
|
+
"tst/60_rbox_transfer_test.rb",
|
58
|
+
"tst/65_rbox_file_append_test.rb",
|
59
|
+
"tst/70_rbox_env_test.rb",
|
60
|
+
"tst/dsl_example.rb",
|
61
|
+
"tst/rye.rb",
|
62
|
+
"tst/shell.rb",
|
63
|
+
"tst/shell2.rb",
|
64
|
+
"tst/shell3.rb",
|
65
|
+
"tst/test_hop.rb"
|
66
|
+
]
|
67
|
+
s.homepage = "https://github.com/delano/rye"
|
68
|
+
s.require_paths = ["lib"]
|
69
|
+
s.rubyforge_project = "rye"
|
70
|
+
s.rubygems_version = "1.8.25"
|
71
|
+
s.signing_key = "/mnt/gem/gem-private_key.pem"
|
72
|
+
s.summary = "Run SSH commands on a bunch of machines at the same time (from Ruby)."
|
55
73
|
|
56
74
|
if s.respond_to? :specification_version then
|
57
|
-
|
58
|
-
|
75
|
+
s.specification_version = 3
|
76
|
+
|
77
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
78
|
+
s.add_runtime_dependency(%q<annoy>, [">= 0"])
|
79
|
+
s.add_runtime_dependency(%q<sysinfo>, [">= 0.7.3"])
|
80
|
+
s.add_runtime_dependency(%q<highline>, [">= 1.5.1"])
|
81
|
+
s.add_runtime_dependency(%q<net-ssh>, [">= 2.0.13"])
|
82
|
+
s.add_runtime_dependency(%q<net-scp>, [">= 1.0.2"])
|
83
|
+
s.add_runtime_dependency(%q<docile>, [">= 1.0.1"])
|
84
|
+
else
|
85
|
+
s.add_dependency(%q<annoy>, [">= 0"])
|
86
|
+
s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
|
87
|
+
s.add_dependency(%q<highline>, [">= 1.5.1"])
|
88
|
+
s.add_dependency(%q<net-ssh>, [">= 2.0.13"])
|
89
|
+
s.add_dependency(%q<net-scp>, [">= 1.0.2"])
|
90
|
+
s.add_dependency(%q<docile>, [">= 1.0.1"])
|
91
|
+
end
|
92
|
+
else
|
93
|
+
s.add_dependency(%q<annoy>, [">= 0"])
|
94
|
+
s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
|
95
|
+
s.add_dependency(%q<highline>, [">= 1.5.1"])
|
96
|
+
s.add_dependency(%q<net-ssh>, [">= 2.0.13"])
|
97
|
+
s.add_dependency(%q<net-scp>, [">= 1.0.2"])
|
98
|
+
s.add_dependency(%q<docile>, [">= 1.0.1"])
|
59
99
|
end
|
60
|
-
|
61
100
|
end
|
101
|
+
|