rake-pro 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/rake/pro.rb +10 -0
- data/lib/rake/pro/hashex.rb +135 -0
- data/lib/rake/pro/keystore.rb +152 -0
- data/lib/rake/pro/localsh.rb +90 -0
- data/lib/rake/pro/ssh_tunnel.rb +109 -0
- data/lib/rake/pro/version.rb +5 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f63cac62f28dd2f2eb0b2eff0fa951ecd5954418
|
4
|
+
data.tar.gz: 00d40a32a74cf8825d716f4ebcfd9a23402892f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fde4d66bf7f5536bad3ca5a01ab282bbe9608fee7b1af773e1013516bb048fcfc8bb33f2abe177702947928a54a60cffa2605b28601a91faa9dd4b120ac15086
|
7
|
+
data.tar.gz: 73d4987dae92dc995dd9af00c10178e87a0de3845318091cb6877d7f2721676e72022492fbd5a3bc8b3d5463d3d990de1976d890130d2ab4a276a2103ce0c0c6
|
data/lib/rake/pro.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
class Hash
|
2
|
+
def recursive_merge(new_hash)
|
3
|
+
self.merge(new_hash) do |k, old_val, new_val|
|
4
|
+
if new_val.respond_to?(:blank) && new_val.blank?
|
5
|
+
old_val
|
6
|
+
elsif (old_val.kind_of?(Hash) and new_val.kind_of?(Hash))
|
7
|
+
old_val.recursive_merge(new_val)
|
8
|
+
else
|
9
|
+
new_val
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def recursive_merge!(new_hash)
|
15
|
+
self.merge!(new_hash) do |k, old_val, new_val|
|
16
|
+
if new_val.respond_to?(:blank) && new_val.blank?
|
17
|
+
old_val
|
18
|
+
elsif (old_val.kind_of?(Hash) and new_val.kind_of?(Hash))
|
19
|
+
old_val.recursive_merge!(new_val)
|
20
|
+
else
|
21
|
+
new_val
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def match strings
|
27
|
+
select { |key,val|
|
28
|
+
is_match = false
|
29
|
+
strings.each { |findstr|
|
30
|
+
is_match ||= key.downcase.include?(findstr) || val.downcase.include?(findstr)
|
31
|
+
}
|
32
|
+
is_match
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def symbolize_keys
|
37
|
+
inject({}) { |memo,(k,v)|
|
38
|
+
memo[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v;
|
39
|
+
memo
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# CASE
|
45
|
+
# admin@dev,prod:
|
46
|
+
# username: abc
|
47
|
+
# password
|
48
|
+
# returns
|
49
|
+
# scopes : [dev, prod]
|
50
|
+
# sub_key : admin
|
51
|
+
# admin:
|
52
|
+
# username: abc
|
53
|
+
#
|
54
|
+
# CASE:
|
55
|
+
# dev:
|
56
|
+
# url: abc
|
57
|
+
#
|
58
|
+
# returns
|
59
|
+
# scopes: [dev]
|
60
|
+
# subkey: nil
|
61
|
+
#
|
62
|
+
# CASE:
|
63
|
+
# url@dev: abc
|
64
|
+
#
|
65
|
+
# returns:
|
66
|
+
# scopes: [dev]
|
67
|
+
# subkey: url
|
68
|
+
#
|
69
|
+
# CASE:
|
70
|
+
# dev:
|
71
|
+
# url: abc
|
72
|
+
#
|
73
|
+
|
74
|
+
def key_details(k)
|
75
|
+
subkey = scopes = nil
|
76
|
+
sk = k.to_s
|
77
|
+
skp = sk.split('@')
|
78
|
+
subkey = skp.shift.to_sym if (skp.length > 1)
|
79
|
+
scopes = skp[0].split(/\s*[&,\|]\s*/)
|
80
|
+
[scopes.map { |scope| scope.to_sym }, subkey]
|
81
|
+
end
|
82
|
+
|
83
|
+
def promote_key pk
|
84
|
+
pk = pk.to_sym
|
85
|
+
coh = {}
|
86
|
+
promoted = false
|
87
|
+
self.each_pair { |k, v|
|
88
|
+
scopes, subkey = key_details(k)
|
89
|
+
if (scopes.include?(pk))
|
90
|
+
promoted = true
|
91
|
+
if subkey.nil?
|
92
|
+
v.each_pair { |sk, sv|
|
93
|
+
coh[sk] = sv
|
94
|
+
}
|
95
|
+
coh[k] = v
|
96
|
+
else
|
97
|
+
coh[subkey] =v
|
98
|
+
end
|
99
|
+
else
|
100
|
+
if v.is_a?(Hash)
|
101
|
+
coh[k], subpromo = v.promote_key(pk)
|
102
|
+
promoted |= subpromo
|
103
|
+
else
|
104
|
+
coh[k] = v
|
105
|
+
end
|
106
|
+
end
|
107
|
+
}
|
108
|
+
[coh, promoted]
|
109
|
+
end
|
110
|
+
|
111
|
+
def prune_keys pks
|
112
|
+
coh = {}
|
113
|
+
self.each_pair { |k, v|
|
114
|
+
scopes, subkey = key_details(k)
|
115
|
+
prune = false
|
116
|
+
scopes.each { |scope| prune |= pks.include?(scope) }
|
117
|
+
if prune
|
118
|
+
scopes.each { |scope|
|
119
|
+
if !pks.include?(scope)
|
120
|
+
if (subkey.nil?)
|
121
|
+
coh[scope] = v
|
122
|
+
else
|
123
|
+
coh[scope] = {}
|
124
|
+
coh[scope][subkey] = v
|
125
|
+
end
|
126
|
+
end
|
127
|
+
}
|
128
|
+
else
|
129
|
+
coh[k] = v.is_a?(Hash) ? v.prune_keys(pks) : v
|
130
|
+
end
|
131
|
+
}
|
132
|
+
coh
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'yaml'
|
3
|
+
require 'etc'
|
4
|
+
require_relative './hashex'
|
5
|
+
|
6
|
+
module Rake
|
7
|
+
class Application
|
8
|
+
attr_accessor :cfg
|
9
|
+
attr_accessor :scopes
|
10
|
+
attr_accessor :active_dir
|
11
|
+
|
12
|
+
class KeySpace
|
13
|
+
def initialize
|
14
|
+
@cfg_files = []
|
15
|
+
@kvp_stack = []
|
16
|
+
@kvp = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
@kvp[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def values()
|
24
|
+
@kvp
|
25
|
+
end
|
26
|
+
|
27
|
+
def home()
|
28
|
+
Etc.getpwuid.dir;
|
29
|
+
end
|
30
|
+
|
31
|
+
def root()
|
32
|
+
Rake.original_dir
|
33
|
+
end
|
34
|
+
|
35
|
+
def rpath(*paths)
|
36
|
+
return File.join(paths)
|
37
|
+
end
|
38
|
+
|
39
|
+
def push_scope scope
|
40
|
+
(@scopes ||= []).push(scope)
|
41
|
+
end
|
42
|
+
|
43
|
+
def pop_scope
|
44
|
+
@scopes.pop
|
45
|
+
end
|
46
|
+
|
47
|
+
def push_cfg cfg_file
|
48
|
+
#puts "Loading cfg file: #{cfg_file}..."
|
49
|
+
cfg = YAML.load_file(cfg_file).symbolize_keys
|
50
|
+
source = if (cfg.has_key?(:default))
|
51
|
+
cfg[:default]
|
52
|
+
elsif (cfg.has_key?(:source))
|
53
|
+
cfg[:source]
|
54
|
+
elsif (cfg.has_key?(:system))
|
55
|
+
cfg[:system]
|
56
|
+
elsif(cfg.has_key?(:target))
|
57
|
+
cfg[:target]
|
58
|
+
end
|
59
|
+
|
60
|
+
push_scope(source.to_sym) if source
|
61
|
+
@kvp_stack.push(cfg)
|
62
|
+
end
|
63
|
+
|
64
|
+
def pop_cfg
|
65
|
+
@kvp_stack.pop
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_once(cfg_file)
|
69
|
+
unless @cfg_files.include?(cfg_file)
|
70
|
+
if (File.file?(cfg_file))
|
71
|
+
Rake.application.active_dir = File.dirname(cfg_file)
|
72
|
+
push_cfg(cfg_file)
|
73
|
+
end
|
74
|
+
@cfg_files.push(cfg_file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def scope_siblings scope
|
79
|
+
siblings = nil
|
80
|
+
Rake.application.scopes.each { |scope_set|
|
81
|
+
siblings = scope_set if scope_set.include?(scope)
|
82
|
+
}
|
83
|
+
siblings
|
84
|
+
end
|
85
|
+
|
86
|
+
def before_invoke task_details
|
87
|
+
task_name = task_details[0]
|
88
|
+
parts = task_name.split(':')
|
89
|
+
push_scope(parts[0].to_sym) if parts.length == 1
|
90
|
+
|
91
|
+
load_paths = parts.reduce([
|
92
|
+
rpath(root, 'cfg.yml'),
|
93
|
+
rpath(root, '.cfg.yml'),
|
94
|
+
rpath(root, '.cfg-private.yml')
|
95
|
+
]) { |paths, folder|
|
96
|
+
paths.push(rpath(root, folder, 'cfg.yml'))
|
97
|
+
paths.push(rpath(root, folder, '.cfg.yml'))
|
98
|
+
paths.push(rpath(root, folder, '.cfg-private.yml'))
|
99
|
+
paths
|
100
|
+
}
|
101
|
+
load_paths.push(rpath(home, '.cyborg.yml'))
|
102
|
+
|
103
|
+
load_paths.each { |path|
|
104
|
+
load_once(path)
|
105
|
+
}
|
106
|
+
|
107
|
+
# promote and prune the key space
|
108
|
+
pruned = false
|
109
|
+
pruned_stack = []
|
110
|
+
@kvp_stack.each_with_index { |kvp, index|
|
111
|
+
@scopes.each_with_index { |scope, i2|
|
112
|
+
kvp, didprune = kvp.promote_key(scope)
|
113
|
+
siblings = scope_siblings(scope)
|
114
|
+
kvp = kvp.prune_keys(scope_siblings(scope)) if siblings
|
115
|
+
pruned |= (didprune && scope == task_name.to_sym)
|
116
|
+
}
|
117
|
+
pruned_stack.push(kvp)
|
118
|
+
}
|
119
|
+
|
120
|
+
# merge the kvp stack entries into a single map
|
121
|
+
@kvp = pruned_stack.reduce({}) { |acc, kvp|
|
122
|
+
acc.recursive_merge(kvp)
|
123
|
+
}
|
124
|
+
|
125
|
+
[task_name, pruned]
|
126
|
+
end
|
127
|
+
|
128
|
+
def after_invoke task_details
|
129
|
+
task_name = task_details[0]
|
130
|
+
parts = task_name.split(':')
|
131
|
+
if parts.length > 1
|
132
|
+
pop_scope
|
133
|
+
pop_cfg
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
module Intercept
|
141
|
+
def invoke_task *args
|
142
|
+
task_name, pruned = (Rake.application.cfg ||= Application::KeySpace.new).before_invoke(parse_task_string args.first)
|
143
|
+
super if Rake::Task.task_defined?(task_name) || !pruned
|
144
|
+
Rake.application.cfg.after_invoke(parse_task_string args.first)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
Rake::Application.class_eval do
|
151
|
+
prepend Rake::Intercept
|
152
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'open4'
|
2
|
+
|
3
|
+
module Rake
|
4
|
+
|
5
|
+
class CommandNotFound < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class AbnormalExitStatus < StandardError
|
9
|
+
attr_reader :exit_status
|
10
|
+
def initialize(exit_status, error_lines)
|
11
|
+
@exit_status = exit_status
|
12
|
+
super error_lines
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Local
|
17
|
+
|
18
|
+
def sh command_line, opts = {}
|
19
|
+
native_output_only = command_line.include?('--terse') || opts[:terse]
|
20
|
+
if native_output_only
|
21
|
+
command_line.sub!(' --terse', '')
|
22
|
+
opts[:echo] = true
|
23
|
+
opts[:echo_cmd] = false
|
24
|
+
end
|
25
|
+
echo_command_output = opts[:echo] || true
|
26
|
+
command_line = "#{command_line}"
|
27
|
+
puts "$ #{command_line}"
|
28
|
+
command_output = ""
|
29
|
+
status = Open4::popen4(command_line) do |pid, stdin, stdout, stderr|
|
30
|
+
command_output = capture_output(stdout, stderr, echo_command_output, native_output_only)
|
31
|
+
end
|
32
|
+
if status.exitstatus != 0
|
33
|
+
raise AbnormalExitStatus.new(status.exitstatus, command_output) if opts[:raise_on_error]
|
34
|
+
end
|
35
|
+
command_output.strip
|
36
|
+
rescue AbnormalExitStatus
|
37
|
+
raise
|
38
|
+
rescue Errno::ENOENT
|
39
|
+
raise CommandNotFound, "Bash Error. Command or file arguments not found." if opts[:raise_on_error]
|
40
|
+
end
|
41
|
+
|
42
|
+
def capture_output stdout, stderr, echo_command_output, native_output_only
|
43
|
+
stdout_lines = ""
|
44
|
+
stderr_lines = ""
|
45
|
+
command_output = ""
|
46
|
+
loop do
|
47
|
+
begin
|
48
|
+
# check whether stdout, stderr or both are
|
49
|
+
# ready to be read from without blocking
|
50
|
+
IO.select([stdout,stderr]).flatten.compact.each { |io|
|
51
|
+
# stdout, if ready, goes to stdout_lines
|
52
|
+
stdout_lines += io.readpartial(1024) if io.fileno == stdout.fileno
|
53
|
+
# stderr, if ready, goes to stdout_lines
|
54
|
+
stderr_lines += io.readpartial(1024) if io.fileno == stderr.fileno
|
55
|
+
}
|
56
|
+
break if stdout.closed? && stderr.closed?
|
57
|
+
rescue EOFError
|
58
|
+
# Note, readpartial triggers the EOFError too soon. Continue to flush the
|
59
|
+
# pending io (via readpartial) until we have received all characters
|
60
|
+
# out from the IO socket.
|
61
|
+
break if stdout_lines.length == 0 && stderr_lines.length == 0
|
62
|
+
ensure
|
63
|
+
# if we acumulated any complete lines (\n-terminated)
|
64
|
+
# in either stdout/err_lines, output them now
|
65
|
+
stdout_lines.sub!(/.*\n/) {
|
66
|
+
command_output << $&
|
67
|
+
if echo_command_output
|
68
|
+
if native_output_only
|
69
|
+
puts $&.strip
|
70
|
+
else
|
71
|
+
puts $&.strip
|
72
|
+
end
|
73
|
+
end
|
74
|
+
}
|
75
|
+
stderr_lines.sub!(/.*\n/) {
|
76
|
+
command_output << $&
|
77
|
+
if echo_command_output
|
78
|
+
if native_output_only
|
79
|
+
puts $&.strip
|
80
|
+
else
|
81
|
+
puts $&.strip
|
82
|
+
end
|
83
|
+
end
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
command_output
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'net/ssh/gateway'
|
3
|
+
require 'open4'
|
4
|
+
|
5
|
+
module Rake
|
6
|
+
|
7
|
+
class Local
|
8
|
+
|
9
|
+
def sh command_line, opts = {}
|
10
|
+
native_output_only = command_line.include?('--terse') || opts[:terse]
|
11
|
+
if native_output_only
|
12
|
+
command_line.sub!(' --terse', '')
|
13
|
+
opts[:echo] = true
|
14
|
+
opts[:echo_cmd] = false
|
15
|
+
end
|
16
|
+
echo_command_output = opts[:echo] || true
|
17
|
+
command_line = "#{command_line}"
|
18
|
+
puts "$ #{command_line}"
|
19
|
+
command_output = ""
|
20
|
+
status = Open4::popen4(command_line) do |pid, stdin, stdout, stderr|
|
21
|
+
command_output = capture_output(stdout, stderr, echo_command_output, native_output_only)
|
22
|
+
end
|
23
|
+
if status.exitstatus != 0
|
24
|
+
raise AbnormalExitStatus.new(status.exitstatus, command_output) if opts[:raise_on_error]
|
25
|
+
end
|
26
|
+
command_output.strip
|
27
|
+
rescue AbnormalExitStatus
|
28
|
+
raise
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
raise CommandNotFound, "Bash Error. Command or file arguments not found." if opts[:raise_on_error]
|
31
|
+
end
|
32
|
+
|
33
|
+
def capture_output stdout, stderr, echo_command_output, native_output_only
|
34
|
+
stdout_lines = ""
|
35
|
+
stderr_lines = ""
|
36
|
+
command_output = ""
|
37
|
+
loop do
|
38
|
+
begin
|
39
|
+
# check whether stdout, stderr or both are
|
40
|
+
# ready to be read from without blocking
|
41
|
+
IO.select([stdout,stderr]).flatten.compact.each { |io|
|
42
|
+
# stdout, if ready, goes to stdout_lines
|
43
|
+
stdout_lines += io.readpartial(1024) if io.fileno == stdout.fileno
|
44
|
+
# stderr, if ready, goes to stdout_lines
|
45
|
+
stderr_lines += io.readpartial(1024) if io.fileno == stderr.fileno
|
46
|
+
}
|
47
|
+
break if stdout.closed? && stderr.closed?
|
48
|
+
rescue EOFError
|
49
|
+
# Note, readpartial triggers the EOFError too soon. Continue to flush the
|
50
|
+
# pending io (via readpartial) until we have received all characters
|
51
|
+
# out from the IO socket.
|
52
|
+
break if stdout_lines.length == 0 && stderr_lines.length == 0
|
53
|
+
ensure
|
54
|
+
# if we acumulated any complete lines (\n-terminated)
|
55
|
+
# in either stdout/err_lines, output them now
|
56
|
+
stdout_lines.sub!(/.*\n/) {
|
57
|
+
command_output << $&
|
58
|
+
if echo_command_output
|
59
|
+
if native_output_only
|
60
|
+
puts $&.strip
|
61
|
+
else
|
62
|
+
puts $&.strip
|
63
|
+
end
|
64
|
+
end
|
65
|
+
}
|
66
|
+
stderr_lines.sub!(/.*\n/) {
|
67
|
+
command_output << $&
|
68
|
+
if echo_command_output
|
69
|
+
if native_output_only
|
70
|
+
puts $&.strip
|
71
|
+
else
|
72
|
+
puts $&.strip
|
73
|
+
end
|
74
|
+
end
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
command_output
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class SSH
|
83
|
+
class << self
|
84
|
+
def tunnel
|
85
|
+
host = gateway = port = jump = nil
|
86
|
+
cfg = Rake.application.cfg.values
|
87
|
+
if cfg.has_key?(:jumpbox)
|
88
|
+
jump = cfg[:jumpbox]
|
89
|
+
gateway = Net::SSH::Gateway.new(
|
90
|
+
jump[:host], jump[:user],
|
91
|
+
:keys => [jump[:keyfile]] #, :verbose => :debug
|
92
|
+
)
|
93
|
+
host = "127.0.0.1"
|
94
|
+
port = gateway.open(cfg[:host], cfg[:port], jump[:port])
|
95
|
+
else
|
96
|
+
host = cfg[:host]
|
97
|
+
port = cfg[:port]
|
98
|
+
end
|
99
|
+
local = Rake::Local.new
|
100
|
+
yield(local, host, port) if block_given?
|
101
|
+
rescue Net::SSH::AuthenticationFailed => ex
|
102
|
+
puts "\nError: SSH Failed to Authenticate. You may need to run\n $ ssh-add ~/.ssh/#{jump[:keyfile]} # key file\n ** or add this line to your .bashrc.\n\n"
|
103
|
+
ensure
|
104
|
+
gateway.close(port) unless gateway.nil?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rake-pro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dean Hallman
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: open4
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: openssl
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: net-ssh-gateway
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
description: Adds support for key/value store with template expansion, ssh tunneling,
|
98
|
+
local and remote shell improvements etc.
|
99
|
+
email:
|
100
|
+
- rdhallman@gmail.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- lib/rake/pro.rb
|
106
|
+
- lib/rake/pro/hashex.rb
|
107
|
+
- lib/rake/pro/keystore.rb
|
108
|
+
- lib/rake/pro/localsh.rb
|
109
|
+
- lib/rake/pro/ssh_tunnel.rb
|
110
|
+
- lib/rake/pro/version.rb
|
111
|
+
homepage: http://www.github.com/
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.6.13
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Enterprise extensions for Rake.
|
135
|
+
test_files: []
|