tunnel-vmc-plugin 0.1.3 → 0.1.4
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/Rakefile +47 -1
- data/helper-app/Gemfile.lock +4 -4
- data/lib/tunnel-vmc-plugin/plugin.rb +153 -44
- data/lib/tunnel-vmc-plugin/tunnel.rb +6 -124
- data/lib/tunnel-vmc-plugin/version.rb +1 -1
- metadata +68 -72
data/Rakefile
CHANGED
@@ -1 +1,47 @@
|
|
1
|
-
require "
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
require "tunnel-vmc-plugin/version"
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
task :spec => ["bundler:install", "test:spec"]
|
10
|
+
|
11
|
+
desc "Run integration tests"
|
12
|
+
task :test => ["bundler:install", "test:integration"]
|
13
|
+
|
14
|
+
task :build do
|
15
|
+
sh "gem build tunnel-vmc-plugin.gemspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :install => :build do
|
19
|
+
sh "gem install --local tunnel-vmc-plugin-#{VMCTunnel::VERSION}.gem"
|
20
|
+
end
|
21
|
+
|
22
|
+
task :uninstall do
|
23
|
+
sh "gem uninstall tunnel-vmc-plugin"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :reinstall => [:uninstall, :install]
|
27
|
+
|
28
|
+
task :release => :build do
|
29
|
+
sh "gem push tunnel-vmc-plugin-#{VMCTunnel::VERSION}.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace "bundler" do
|
33
|
+
desc "Install gems"
|
34
|
+
task "install" do
|
35
|
+
sh("bundle install")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace "test" do
|
40
|
+
task "spec" do |t|
|
41
|
+
# nothing
|
42
|
+
end
|
43
|
+
|
44
|
+
task "integration" do |t|
|
45
|
+
sh("cd spec && bundle exec rake spec")
|
46
|
+
end
|
47
|
+
end
|
data/helper-app/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
em-websocket (= 0.3.1)
|
13
13
|
json (= 1.6.1)
|
14
14
|
uuidtools (= 2.1.2)
|
15
|
-
daemons (1.1.
|
15
|
+
daemons (1.1.8)
|
16
16
|
em-http-request (0.3.0)
|
17
17
|
addressable (>= 2.0.0)
|
18
18
|
escape_utils
|
@@ -23,11 +23,11 @@ GEM
|
|
23
23
|
escape_utils (0.2.4)
|
24
24
|
eventmachine (0.12.10)
|
25
25
|
json (1.6.1)
|
26
|
-
rack (1.2.
|
27
|
-
sinatra (1.2.
|
26
|
+
rack (1.2.5)
|
27
|
+
sinatra (1.2.8)
|
28
28
|
rack (~> 1.1)
|
29
29
|
tilt (>= 1.2.2, < 2.0)
|
30
|
-
thin (1.
|
30
|
+
thin (1.4.1)
|
31
31
|
daemons (>= 1.0.9)
|
32
32
|
eventmachine (>= 0.12.6)
|
33
33
|
rack (>= 1.0.0)
|
@@ -1,69 +1,178 @@
|
|
1
|
-
require "vmc/
|
1
|
+
require "vmc/cli"
|
2
2
|
require "tunnel-vmc-plugin/tunnel"
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module VMCTunnel
|
5
|
+
class Tunnel < VMC::CLI
|
6
|
+
CLIENTS_FILE = "#{VMC::CONFIG_DIR}/tunnel-clients.yml"
|
7
|
+
STOCK_CLIENTS = File.expand_path("../../../config/clients.yml", __FILE__)
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
desc "Create a local tunnel to a service."
|
10
|
+
group :services, :manage
|
11
|
+
input(:instance, :argument => :optional,
|
12
|
+
:from_given => find_by_name("service instance"),
|
13
|
+
:desc => "Service instance to tunnel to") { |instances|
|
14
|
+
ask("Which service instance?", :choices => instances,
|
15
|
+
:display => proc(&:name))
|
16
|
+
}
|
17
|
+
input(:client, :argument => :optional,
|
18
|
+
:desc => "Client to automatically launch") { |clients|
|
19
|
+
if clients.empty?
|
20
|
+
"none"
|
21
|
+
else
|
22
|
+
ask("Which client would you like to start?",
|
23
|
+
:choices => clients.keys.unshift("none"))
|
24
|
+
end
|
25
|
+
}
|
26
|
+
input(:port, :default => 10000, :desc => "Port to bind the tunnel to")
|
27
|
+
def tunnel(input)
|
28
|
+
instances = client.service_instances
|
29
|
+
fail "No services available for tunneling." if instances.empty?
|
18
30
|
|
19
|
-
|
31
|
+
instance = input[:instance, instances.sort_by(&:name)]
|
32
|
+
clients = tunnel_clients[instance.vendor] || {}
|
33
|
+
client_name = input[:client, clients]
|
20
34
|
|
21
|
-
|
35
|
+
tunnel = CFTunnel.new(client, instance)
|
36
|
+
port = tunnel.pick_port!(input[:port])
|
22
37
|
|
23
|
-
|
38
|
+
conn_info =
|
39
|
+
with_progress("Opening tunnel on port #{c(port, :name)}") do
|
40
|
+
tunnel.open!
|
41
|
+
end
|
24
42
|
|
25
|
-
|
43
|
+
if client_name == "none"
|
44
|
+
unless simple_output?
|
45
|
+
line
|
46
|
+
display_tunnel_connection_info(conn_info)
|
26
47
|
|
27
|
-
|
48
|
+
line
|
49
|
+
line "Open another shell to run command-line clients or"
|
50
|
+
line "use a UI tool to connect using the displayed information."
|
51
|
+
line "Press Ctrl-C to exit..."
|
52
|
+
end
|
28
53
|
|
29
|
-
|
30
|
-
if clients.empty?
|
31
|
-
client_name = "none"
|
54
|
+
tunnel.wait_for_end
|
32
55
|
else
|
33
|
-
|
34
|
-
|
35
|
-
|
56
|
+
with_progress("Waiting for local tunnel to become available") do
|
57
|
+
tunnel.wait_for_start
|
58
|
+
end
|
59
|
+
|
60
|
+
unless start_local_prog(clients, client_name, conn_info, port)
|
61
|
+
fail "'#{client_name}' execution failed; is it in your $PATH?"
|
62
|
+
end
|
36
63
|
end
|
37
64
|
end
|
38
65
|
|
39
|
-
|
40
|
-
|
66
|
+
private
|
67
|
+
|
68
|
+
def display_tunnel_connection_info(info)
|
69
|
+
line "Service connection info:"
|
41
70
|
|
42
|
-
|
43
|
-
|
44
|
-
|
71
|
+
to_show = [nil, nil, nil] # reserved for user, pass, db name
|
72
|
+
info.keys.each do |k|
|
73
|
+
case k
|
74
|
+
when "host", "hostname", "port", "node_id"
|
75
|
+
# skip
|
76
|
+
when "user", "username"
|
77
|
+
# prefer "username" over "user"
|
78
|
+
to_show[0] = k unless to_show[0] == "username"
|
79
|
+
when "password"
|
80
|
+
to_show[1] = k
|
81
|
+
when "name"
|
82
|
+
to_show[2] = k
|
83
|
+
else
|
84
|
+
to_show << k
|
85
|
+
end
|
45
86
|
end
|
87
|
+
to_show.compact!
|
46
88
|
|
47
|
-
|
48
|
-
unless simple_output?
|
49
|
-
puts ""
|
50
|
-
display_tunnel_connection_info(conn_info)
|
89
|
+
align_len = to_show.collect(&:size).max + 1
|
51
90
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
91
|
+
indented do
|
92
|
+
to_show.each do |k|
|
93
|
+
# TODO: modify the server services rest call to have explicit knowledge
|
94
|
+
# about the items to return. It should return all of them if
|
95
|
+
# the service is unknown so that we don't have to do this weird
|
96
|
+
# filtering.
|
97
|
+
line "#{k.ljust align_len}: #{b(info[k])}"
|
98
|
+
end
|
56
99
|
end
|
57
100
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
101
|
+
line
|
102
|
+
end
|
103
|
+
|
104
|
+
def start_local_prog(clients, command, info, port)
|
105
|
+
client = clients[File.basename(command)]
|
106
|
+
|
107
|
+
cmdline = "#{command} "
|
108
|
+
|
109
|
+
case client
|
110
|
+
when Hash
|
111
|
+
cmdline << resolve_symbols(client["command"], info, port)
|
112
|
+
client["environment"].each do |e|
|
113
|
+
if e =~ /([^=]+)=(["']?)([^"']*)\2/
|
114
|
+
ENV[$1] = resolve_symbols($3, info, port)
|
115
|
+
else
|
116
|
+
fail "Invalid environment variable: #{e}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
when String
|
120
|
+
cmdline << resolve_symbols(client, info, port)
|
121
|
+
else
|
122
|
+
raise "Unknown client info: #{client.inspect}."
|
62
123
|
end
|
63
124
|
|
64
|
-
|
65
|
-
|
125
|
+
if verbose?
|
126
|
+
line
|
127
|
+
line "Launching '#{cmdline}'"
|
66
128
|
end
|
129
|
+
|
130
|
+
system(cmdline)
|
131
|
+
end
|
132
|
+
|
133
|
+
def tunnel_clients
|
134
|
+
return @tunnel_clients if @tunnel_clients
|
135
|
+
|
136
|
+
stock = YAML.load_file(STOCK_CLIENTS)
|
137
|
+
clients = File.expand_path CLIENTS_FILE
|
138
|
+
if File.exists? clients
|
139
|
+
user = YAML.load_file(clients)
|
140
|
+
@tunnel_clients = deep_merge(stock, user)
|
141
|
+
else
|
142
|
+
@tunnel_clients = stock
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def resolve_symbols(str, info, local_port)
|
147
|
+
str.gsub(/\$\{\s*([^\}]+)\s*\}/) do
|
148
|
+
sym = $1
|
149
|
+
|
150
|
+
case sym
|
151
|
+
when "host"
|
152
|
+
# TODO: determine proper host
|
153
|
+
"localhost"
|
154
|
+
when "port"
|
155
|
+
local_port
|
156
|
+
when "user", "username"
|
157
|
+
info["username"]
|
158
|
+
when /^ask (.+)/
|
159
|
+
ask($1)
|
160
|
+
else
|
161
|
+
info[sym] || raise("Unknown symbol in config: #{sym}")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def deep_merge(a, b)
|
167
|
+
merge = proc { |old, new|
|
168
|
+
if old === Hash && new === Hash
|
169
|
+
old.merge(new, &merge)
|
170
|
+
else
|
171
|
+
new
|
172
|
+
end
|
173
|
+
}
|
174
|
+
|
175
|
+
a.merge(b, &merge)
|
67
176
|
end
|
68
177
|
end
|
69
178
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "addressable/uri"
|
2
|
+
require "restclient"
|
2
3
|
|
3
4
|
require "caldecott"
|
4
5
|
|
@@ -89,12 +90,7 @@ class CFTunnel
|
|
89
90
|
end
|
90
91
|
|
91
92
|
def helper_auth
|
92
|
-
helper.env
|
93
|
-
name, val = e.split("=", 2)
|
94
|
-
return val if name == "CALDECOTT_AUTH"
|
95
|
-
end
|
96
|
-
|
97
|
-
nil
|
93
|
+
helper.env["CALDECOTT_AUTH"]
|
98
94
|
end
|
99
95
|
|
100
96
|
def helper_healthy?(token)
|
@@ -120,7 +116,7 @@ class CFTunnel
|
|
120
116
|
end
|
121
117
|
|
122
118
|
def helper_already_binds?
|
123
|
-
helper.
|
119
|
+
helper.binds? @service
|
124
120
|
end
|
125
121
|
|
126
122
|
def push_helper(token)
|
@@ -131,8 +127,8 @@ class CFTunnel
|
|
131
127
|
app.url = "#{random_helper_url}.#{target_base}"
|
132
128
|
app.total_instances = 1
|
133
129
|
app.memory = 64
|
134
|
-
app.env =
|
135
|
-
app.services = [@service
|
130
|
+
app.env = { "CALDECOTT_AUTH" => token }
|
131
|
+
app.services = [@service] if @service
|
136
132
|
app.create!
|
137
133
|
|
138
134
|
begin
|
@@ -171,7 +167,7 @@ class CFTunnel
|
|
171
167
|
end
|
172
168
|
|
173
169
|
def bind_to_helper
|
174
|
-
helper.bind(@service
|
170
|
+
helper.bind(@service)
|
175
171
|
helper.restart!
|
176
172
|
end
|
177
173
|
|
@@ -213,7 +209,6 @@ class CFTunnel
|
|
213
209
|
|
214
210
|
break
|
215
211
|
rescue RestClient::Exception => e
|
216
|
-
p [e, e.to_s]
|
217
212
|
sleep 1
|
218
213
|
end
|
219
214
|
end
|
@@ -288,116 +283,3 @@ class CFTunnel
|
|
288
283
|
socket.close
|
289
284
|
end
|
290
285
|
end
|
291
|
-
|
292
|
-
module VMCTunnel
|
293
|
-
CLIENTS_FILE = "#{VMC::CONFIG_DIR}/tunnel-clients.yml"
|
294
|
-
STOCK_CLIENTS = File.expand_path("../../../config/clients.yml", __FILE__)
|
295
|
-
|
296
|
-
def display_tunnel_connection_info(info)
|
297
|
-
puts "Service connection info:"
|
298
|
-
|
299
|
-
to_show = [nil, nil, nil] # reserved for user, pass, db name
|
300
|
-
info.keys.each do |k|
|
301
|
-
case k
|
302
|
-
when "host", "hostname", "port", "node_id"
|
303
|
-
# skip
|
304
|
-
when "user", "username"
|
305
|
-
# prefer "username" over "user"
|
306
|
-
to_show[0] = k unless to_show[0] == "username"
|
307
|
-
when "password"
|
308
|
-
to_show[1] = k
|
309
|
-
when "name"
|
310
|
-
to_show[2] = k
|
311
|
-
else
|
312
|
-
to_show << k
|
313
|
-
end
|
314
|
-
end
|
315
|
-
to_show.compact!
|
316
|
-
|
317
|
-
align_len = to_show.collect(&:size).max + 1
|
318
|
-
|
319
|
-
to_show.each do |k|
|
320
|
-
# TODO: modify the server services rest call to have explicit knowledge
|
321
|
-
# about the items to return. It should return all of them if
|
322
|
-
# the service is unknown so that we don't have to do this weird
|
323
|
-
# filtering.
|
324
|
-
print " #{k.ljust align_len}: #{b(info[k])}"
|
325
|
-
end
|
326
|
-
|
327
|
-
puts ""
|
328
|
-
end
|
329
|
-
|
330
|
-
def start_local_prog(clients, command, info, port)
|
331
|
-
client = clients[File.basename(command)]
|
332
|
-
|
333
|
-
cmdline = "#{command} "
|
334
|
-
|
335
|
-
case client
|
336
|
-
when Hash
|
337
|
-
cmdline << resolve_symbols(client["command"], info, port)
|
338
|
-
client["environment"].each do |e|
|
339
|
-
if e =~ /([^=]+)=(["']?)([^"']*)\2/
|
340
|
-
ENV[$1] = resolve_symbols($3, info, port)
|
341
|
-
else
|
342
|
-
raise "Invalid environment variable: #{e}"
|
343
|
-
end
|
344
|
-
end
|
345
|
-
when String
|
346
|
-
cmdline << resolve_symbols(client, info, port)
|
347
|
-
else
|
348
|
-
raise "Unknown client info: #{client.inspect}."
|
349
|
-
end
|
350
|
-
|
351
|
-
if verbose?
|
352
|
-
puts ""
|
353
|
-
puts "Launching '#{cmdline}'"
|
354
|
-
end
|
355
|
-
|
356
|
-
system(cmdline)
|
357
|
-
end
|
358
|
-
|
359
|
-
def tunnel_clients
|
360
|
-
return @tunnel_clients if @tunnel_clients
|
361
|
-
|
362
|
-
stock = YAML.load_file(STOCK_CLIENTS)
|
363
|
-
clients = File.expand_path CLIENTS_FILE
|
364
|
-
if File.exists? clients
|
365
|
-
user = YAML.load_file(clients)
|
366
|
-
@tunnel_clients = deep_merge(stock, user)
|
367
|
-
else
|
368
|
-
@tunnel_clients = stock
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
def resolve_symbols(str, info, local_port)
|
373
|
-
str.gsub(/\$\{\s*([^\}]+)\s*\}/) do
|
374
|
-
sym = $1
|
375
|
-
|
376
|
-
case sym
|
377
|
-
when "host"
|
378
|
-
# TODO: determine proper host
|
379
|
-
"localhost"
|
380
|
-
when "port"
|
381
|
-
local_port
|
382
|
-
when "user", "username"
|
383
|
-
info["username"]
|
384
|
-
when /^ask (.+)/
|
385
|
-
ask($1)
|
386
|
-
else
|
387
|
-
info[sym] || raise("Unknown symbol in config: #{sym}")
|
388
|
-
end
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
def deep_merge(a, b)
|
393
|
-
merge = proc { |old, new|
|
394
|
-
if old === Hash && new === Hash
|
395
|
-
old.merge(new, &merge)
|
396
|
-
else
|
397
|
-
new
|
398
|
-
end
|
399
|
-
}
|
400
|
-
|
401
|
-
a.merge(b, &merge)
|
402
|
-
end
|
403
|
-
end
|
metadata
CHANGED
@@ -1,81 +1,87 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tunnel-vmc-plugin
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 3
|
10
|
-
version: 0.1.3
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Alex Suraci
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2012-08-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: cfoundry
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.3.18
|
22
|
+
type: :runtime
|
22
23
|
prerelease: false
|
23
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
25
|
none: false
|
25
|
-
requirements:
|
26
|
+
requirements:
|
26
27
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.3.18
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: addressable
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
33
37
|
version: 2.2.6
|
34
38
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: eventmachine
|
38
39
|
prerelease: false
|
39
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
41
|
none: false
|
41
|
-
requirements:
|
42
|
+
requirements:
|
42
43
|
- - ~>
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.2.6
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: eventmachine
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
50
53
|
version: 1.0.0.beta
|
51
54
|
type: :runtime
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: caldecott
|
55
55
|
prerelease: false
|
56
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0.beta
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: caldecott
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
57
65
|
none: false
|
58
|
-
requirements:
|
66
|
+
requirements:
|
59
67
|
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
hash: 21
|
62
|
-
segments:
|
63
|
-
- 0
|
64
|
-
- 0
|
65
|
-
- 5
|
68
|
+
- !ruby/object:Gem::Version
|
66
69
|
version: 0.0.5
|
67
70
|
type: :runtime
|
68
|
-
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.0.5
|
69
78
|
description:
|
70
|
-
email:
|
79
|
+
email:
|
71
80
|
- asuraci@vmware.com
|
72
81
|
executables: []
|
73
|
-
|
74
82
|
extensions: []
|
75
|
-
|
76
83
|
extra_rdoc_files: []
|
77
|
-
|
78
|
-
files:
|
84
|
+
files:
|
79
85
|
- Rakefile
|
80
86
|
- lib/tunnel-vmc-plugin/plugin.rb
|
81
87
|
- lib/tunnel-vmc-plugin/tunnel.rb
|
@@ -86,36 +92,26 @@ files:
|
|
86
92
|
- config/clients.yml
|
87
93
|
homepage: http://cloudfoundry.com/
|
88
94
|
licenses: []
|
89
|
-
|
90
95
|
post_install_message:
|
91
96
|
rdoc_options: []
|
92
|
-
|
93
|
-
require_paths:
|
97
|
+
require_paths:
|
94
98
|
- lib
|
95
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
100
|
none: false
|
97
|
-
requirements:
|
98
|
-
- -
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
|
101
|
-
|
102
|
-
- 0
|
103
|
-
version: "0"
|
104
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
106
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
segments:
|
111
|
-
- 0
|
112
|
-
version: "0"
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
113
111
|
requirements: []
|
114
|
-
|
115
112
|
rubyforge_project: tunnel-vmc-plugin
|
116
113
|
rubygems_version: 1.8.23
|
117
114
|
signing_key:
|
118
115
|
specification_version: 3
|
119
116
|
summary: External access to your services on Cloud Foundry via a Caldecott HTTP tunnel.
|
120
117
|
test_files: []
|
121
|
-
|