jdc 0.2.1.pre → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/LICENSE +24 -1277
  2. data/README.md +102 -0
  3. data/bin/jdc +2 -12
  4. data/{lib/tunnel/helper-app → caldecott_helper}/server.rb +5 -5
  5. data/{lib/tunnel/config → config}/clients.yml +2 -2
  6. data/config/micro/paths.yml +22 -0
  7. data/config/micro/refresh_ip.rb +20 -0
  8. data/lib/cli/commands/admin.rb +58 -0
  9. data/lib/cli/commands/apps.rb +1129 -0
  10. data/lib/cli/commands/base.rb +228 -0
  11. data/lib/cli/commands/manifest.rb +56 -0
  12. data/lib/cli/commands/micro.rb +115 -0
  13. data/lib/cli/commands/misc.rb +126 -0
  14. data/lib/cli/commands/services.rb +178 -0
  15. data/lib/cli/commands/user.rb +14 -0
  16. data/lib/cli/config.rb +173 -0
  17. data/lib/cli/console_helper.rb +170 -0
  18. data/lib/cli/core_ext.rb +122 -0
  19. data/lib/cli/errors.rb +19 -0
  20. data/lib/cli/frameworks.rb +265 -0
  21. data/lib/cli/manifest_helper.rb +300 -0
  22. data/lib/cli/runner.rb +505 -0
  23. data/lib/cli/services_helper.rb +84 -0
  24. data/lib/cli/tunnel_helper.rb +332 -0
  25. data/lib/cli/usage.rb +86 -0
  26. data/lib/cli/version.rb +7 -0
  27. data/lib/cli/zip_util.rb +77 -0
  28. data/lib/cli.rb +53 -0
  29. data/lib/jdc/client.rb +457 -0
  30. data/lib/jdc/const.rb +25 -0
  31. data/lib/jdc/micro/switcher/base.rb +97 -0
  32. data/lib/{micro → jdc/micro}/switcher/darwin.rb +3 -5
  33. data/lib/{micro → jdc/micro}/switcher/dummy.rb +1 -1
  34. data/lib/jdc/micro/switcher/linux.rb +16 -0
  35. data/lib/{micro → jdc/micro}/switcher/windows.rb +5 -5
  36. data/lib/{micro → jdc/micro}/vmrun.rb +19 -26
  37. data/lib/{micro → jdc}/micro.rb +15 -15
  38. data/lib/jdc/signature/version.rb +27 -0
  39. data/lib/jdc/signer.rb +13 -0
  40. data/lib/jdc/timer.rb +12 -0
  41. data/lib/jdc.rb +2 -15
  42. metadata +210 -360
  43. data/Rakefile +0 -13
  44. data/lib/admin/README.md +0 -15
  45. data/lib/admin/curl.rb +0 -60
  46. data/lib/admin/guid.rb +0 -89
  47. data/lib/admin/plugin.rb +0 -6
  48. data/lib/admin/service_auth_token.rb +0 -94
  49. data/lib/admin/service_broker/add.rb +0 -47
  50. data/lib/admin/service_broker/service_brokers.rb +0 -24
  51. data/lib/admin/set_quota.rb +0 -44
  52. data/lib/console/README.md +0 -8
  53. data/lib/console/console.rb +0 -187
  54. data/lib/console/plugin.rb +0 -33
  55. data/lib/jdc/cli/app/app.rb +0 -43
  56. data/lib/jdc/cli/app/apps.rb +0 -87
  57. data/lib/jdc/cli/app/base.rb +0 -72
  58. data/lib/jdc/cli/app/delete.rb +0 -95
  59. data/lib/jdc/cli/app/deprecated.rb +0 -11
  60. data/lib/jdc/cli/app/env.rb +0 -78
  61. data/lib/jdc/cli/app/events.rb +0 -45
  62. data/lib/jdc/cli/app/files.rb +0 -137
  63. data/lib/jdc/cli/app/health.rb +0 -26
  64. data/lib/jdc/cli/app/instances.rb +0 -53
  65. data/lib/jdc/cli/app/logs.rb +0 -76
  66. data/lib/jdc/cli/app/push/create.rb +0 -108
  67. data/lib/jdc/cli/app/push/interactions.rb +0 -86
  68. data/lib/jdc/cli/app/push/sync.rb +0 -57
  69. data/lib/jdc/cli/app/push.rb +0 -103
  70. data/lib/jdc/cli/app/rename.rb +0 -35
  71. data/lib/jdc/cli/app/restart.rb +0 -31
  72. data/lib/jdc/cli/app/scale.rb +0 -63
  73. data/lib/jdc/cli/app/start.rb +0 -161
  74. data/lib/jdc/cli/app/stats.rb +0 -67
  75. data/lib/jdc/cli/app/stop.rb +0 -27
  76. data/lib/jdc/cli/domain/base.rb +0 -9
  77. data/lib/jdc/cli/domain/domains.rb +0 -40
  78. data/lib/jdc/cli/domain/map.rb +0 -55
  79. data/lib/jdc/cli/domain/unmap.rb +0 -56
  80. data/lib/jdc/cli/help.rb +0 -15
  81. data/lib/jdc/cli/interactive.rb +0 -105
  82. data/lib/jdc/cli/login_requirements.rb +0 -15
  83. data/lib/jdc/cli/organization/base.rb +0 -14
  84. data/lib/jdc/cli/organization/create.rb +0 -37
  85. data/lib/jdc/cli/organization/delete.rb +0 -63
  86. data/lib/jdc/cli/organization/org.rb +0 -45
  87. data/lib/jdc/cli/organization/orgs.rb +0 -30
  88. data/lib/jdc/cli/organization/rename.rb +0 -37
  89. data/lib/jdc/cli/populators/base.rb +0 -16
  90. data/lib/jdc/cli/populators/organization.rb +0 -32
  91. data/lib/jdc/cli/populators/populator_methods.rb +0 -64
  92. data/lib/jdc/cli/populators/space.rb +0 -33
  93. data/lib/jdc/cli/populators/target.rb +0 -13
  94. data/lib/jdc/cli/route/base.rb +0 -9
  95. data/lib/jdc/cli/route/delete.rb +0 -28
  96. data/lib/jdc/cli/route/map.rb +0 -68
  97. data/lib/jdc/cli/route/routes.rb +0 -26
  98. data/lib/jdc/cli/route/unmap.rb +0 -56
  99. data/lib/jdc/cli/service/base.rb +0 -9
  100. data/lib/jdc/cli/service/bind.rb +0 -44
  101. data/lib/jdc/cli/service/create.rb +0 -159
  102. data/lib/jdc/cli/service/delete.rb +0 -83
  103. data/lib/jdc/cli/service/rename.rb +0 -36
  104. data/lib/jdc/cli/service/service.rb +0 -42
  105. data/lib/jdc/cli/service/service_instance_helper.rb +0 -99
  106. data/lib/jdc/cli/service/services.rb +0 -111
  107. data/lib/jdc/cli/service/unbind.rb +0 -37
  108. data/lib/jdc/cli/space/base.rb +0 -29
  109. data/lib/jdc/cli/space/create.rb +0 -67
  110. data/lib/jdc/cli/space/delete.rb +0 -56
  111. data/lib/jdc/cli/space/rename.rb +0 -38
  112. data/lib/jdc/cli/space/space.rb +0 -66
  113. data/lib/jdc/cli/space/spaces.rb +0 -57
  114. data/lib/jdc/cli/space/switch.rb +0 -19
  115. data/lib/jdc/cli/start/base.rb +0 -41
  116. data/lib/jdc/cli/start/colors.rb +0 -13
  117. data/lib/jdc/cli/start/target.rb +0 -50
  118. data/lib/jdc/cli/start/target_prettifier.rb +0 -17
  119. data/lib/jdc/cli/start/targets.rb +0 -16
  120. data/lib/jdc/cli/user/base.rb +0 -30
  121. data/lib/jdc/cli/user/create.rb +0 -52
  122. data/lib/jdc/cli/user/passwd.rb +0 -37
  123. data/lib/jdc/cli/user/register.rb +0 -43
  124. data/lib/jdc/cli/user/users.rb +0 -32
  125. data/lib/jdc/cli.rb +0 -556
  126. data/lib/jdc/constants.rb +0 -11
  127. data/lib/jdc/errors.rb +0 -19
  128. data/lib/jdc/object_extensions.rb +0 -15
  129. data/lib/jdc/plugin.rb +0 -56
  130. data/lib/jdc/spacing.rb +0 -89
  131. data/lib/jdc/spec_helper.rb +0 -1
  132. data/lib/jdc/test_support.rb +0 -6
  133. data/lib/jdc/version.rb +0 -3
  134. data/lib/manifests/errors.rb +0 -35
  135. data/lib/manifests/loader/builder.rb +0 -39
  136. data/lib/manifests/loader/normalizer.rb +0 -145
  137. data/lib/manifests/loader/resolver.rb +0 -79
  138. data/lib/manifests/loader.rb +0 -31
  139. data/lib/manifests/manifests.rb +0 -344
  140. data/lib/manifests/plugin.rb +0 -140
  141. data/lib/micro/README.md +0 -9
  142. data/lib/micro/errors.rb +0 -4
  143. data/lib/micro/plugin.rb +0 -197
  144. data/lib/micro/switcher/base.rb +0 -79
  145. data/lib/micro/switcher/linux.rb +0 -16
  146. data/lib/tasks/gem_release.rake +0 -42
  147. data/lib/tunnel/README.md +0 -29
  148. data/lib/tunnel/helper-app/Gemfile +0 -10
  149. data/lib/tunnel/helper-app/Gemfile.lock +0 -48
  150. data/lib/tunnel/plugin.rb +0 -183
  151. data/lib/tunnel/tunnel.rb +0 -295
@@ -1,79 +0,0 @@
1
- require "micro/errors"
2
-
3
- module JDCMicro::Switcher
4
- class Base
5
-
6
- def initialize(config)
7
- @config = config
8
-
9
- @vmrun = JDCMicro::VMrun.new(config)
10
- end
11
-
12
- #wrapper methods
13
- def vmx
14
- @vmrun.vmx
15
- end
16
-
17
- def domain
18
- @vmrun.domain
19
- end
20
-
21
- def ip
22
- @vmrun.ip
23
- end
24
-
25
- def running?
26
- @vmrun.running?
27
- end
28
-
29
- def start!
30
- @vmrun.start!
31
- end
32
-
33
- def ready?
34
- @vmrun.ready?
35
- end
36
-
37
- def offline?
38
- @vmrun.offline?
39
- end
40
-
41
- def nat?
42
- @config['online_connection_type'] ||= @vmrun.connection_type
43
- @config["online_connection_type"] == "nat"
44
- end
45
-
46
- def reset_to_nat!
47
- @vmrun.connection_type = 'nat'
48
- @vmrun.reset
49
- end
50
-
51
- def set_host_dns!
52
- @config['domain'] ||= @vmrun.domain
53
- @config['ip'] ||= @vmrun.ip
54
- set_nameserver(@config['domain'], @config['ip'])
55
- end
56
-
57
- def unset_host_dns!
58
- @config['domain'] ||= @vmrun.domain
59
- @config['ip'] ||= @vmrun.ip
60
- unset_nameserver(@config['domain'], @config['ip'])
61
- end
62
-
63
- def offline!
64
- if @vmrun.offline?
65
- raise JDCMicro::MCFError, "Micro Cloud Foundry VM already in offline mode"
66
- else
67
- @vmrun.offline!
68
- end
69
- end
70
-
71
- def online!
72
- if @vmrun.offline?
73
- @vmrun.online!
74
- else
75
- raise JDCMirco::MCFError, "Micro Cloud Foundry already in online mode"
76
- end
77
- end
78
- end
79
- end
@@ -1,16 +0,0 @@
1
- module JDCMicro::Switcher
2
-
3
- class Linux < Base
4
- def set_nameserver(domain, ip)
5
- JDCMicro.run_command("sudo", "sed -i'.backup' '1 i nameserver #{ip}' /etc/resolv.conf")
6
- # lock resolv.conf so Network Manager doesn't clear out the file when offline
7
- JDCMicro.run_command("sudo", "chattr +i /etc/resolv.conf")
8
- end
9
-
10
- def unset_nameserver(domain, ip)
11
- JDCMicro.run_command("sudo", "chattr -i /etc/resolv.conf")
12
- JDCMicro.run_command("sudo", "sed -i'.backup' '/#{ip}/d' /etc/resolv.conf")
13
- end
14
- end
15
-
16
- end
@@ -1,42 +0,0 @@
1
- require 'active_support/core_ext'
2
-
3
- namespace :gem do
4
- desc "Bump gem version, push to RubyGems, push to Github, add release notes"
5
- task :release, [:version] do |_, args|
6
- version = args[:version] || 'rc'
7
- old_version = gem_version
8
-
9
- sh! "gem bump --version #{version} --no-commit"
10
- sh! "git add lib/jdc/version.rb"
11
-
12
- print_with_purpose "Bumping to version #{gem_version}"
13
- #generate_release_notes(old_version)
14
- sh!("git commit -m 'Bumping to version #{gem_version}.'")
15
- sh!("git push")
16
- sh!("gem release --tag")
17
- end
18
-
19
- private
20
- def generate_release_notes(old_version)
21
- print_with_purpose "Generating release notes..."
22
- file_name = "release_#{gem_version}"
23
- sh!("anchorman notes --name=#{file_name} --from=v#{old_version}")
24
- sh!("git add release_notes")
25
- end
26
-
27
- def sh!(cmd)
28
- `#{cmd}`
29
- raise "borked with #{$?}" unless $?.success?
30
- end
31
-
32
- def print_with_purpose(text)
33
- puts "\033[34m#{text}\033[0m"
34
- end
35
-
36
- def gem_version
37
- silence_warnings do
38
- load "lib/jdc/version.rb"
39
- end
40
- Gem::Specification.load("jdc.gemspec").version.to_s
41
- end
42
- end
data/lib/tunnel/README.md DELETED
@@ -1,29 +0,0 @@
1
- [![Build Status](https://travis-ci.org/cloudfoundry/tunnel-cf-plugin.png)](https://travis-ci.org/cloudfoundry/tunnel-cf-plugin)
2
- [![Gem Version](https://badge.fury.io/rb/tunnel-cf-plugin.png)](http://badge.fury.io/rb/tunnel-cf-plugin)
3
-
4
- ## Tunnel
5
- ### Info
6
- This plugin allows you to connect to a Cloud Foundry service using your own command line client. By default, the plugin supports *redis*, *mysql*, *mongodb*, and *postgresql*.
7
-
8
- ### Installation
9
- ```
10
- gem install tunnel-cf-plugin
11
- ```
12
-
13
- ### Usage
14
- ```
15
- tunnel [INSTANCE] [CLIENT] Create a local tunnel to a service.
16
- ```
17
-
18
- You can add support for other command-line clients by providing a `~/.cf/clients.yml` file with the following format:
19
-
20
- ```yaml
21
- service_name:
22
- client_program_name: command line arguments
23
- client_program_name_2:
24
- command: command line arguments
25
- environment:
26
- - ENV_VAR_NAME=env_var_value
27
- ```
28
-
29
-
@@ -1,10 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem 'rack', '~> 1.2.0'
4
- gem 'caldecott', '= 0.0.3'
5
- gem 'bundler'
6
- gem 'em-websocket'
7
- gem 'async_sinatra'
8
- gem 'thin'
9
- gem 'json'
10
- gem 'uuidtools'
@@ -1,48 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- addressable (2.2.6)
5
- async_sinatra (0.5.0)
6
- rack (>= 1.2.1)
7
- sinatra (>= 1.0)
8
- caldecott (0.0.3)
9
- addressable (= 2.2.6)
10
- async_sinatra (= 0.5.0)
11
- em-http-request (= 0.3.0)
12
- em-websocket (= 0.3.1)
13
- json (= 1.6.1)
14
- uuidtools (= 2.1.2)
15
- daemons (1.1.8)
16
- em-http-request (0.3.0)
17
- addressable (>= 2.0.0)
18
- escape_utils
19
- eventmachine (>= 0.12.9)
20
- em-websocket (0.3.1)
21
- addressable (>= 2.1.1)
22
- eventmachine (>= 0.12.9)
23
- escape_utils (0.2.4)
24
- eventmachine (0.12.10)
25
- json (1.6.1)
26
- rack (1.2.5)
27
- sinatra (1.2.8)
28
- rack (~> 1.1)
29
- tilt (>= 1.2.2, < 2.0)
30
- thin (1.4.1)
31
- daemons (>= 1.0.9)
32
- eventmachine (>= 0.12.6)
33
- rack (>= 1.0.0)
34
- tilt (1.3.3)
35
- uuidtools (2.1.2)
36
-
37
- PLATFORMS
38
- ruby
39
-
40
- DEPENDENCIES
41
- async_sinatra
42
- bundler
43
- caldecott (= 0.0.3)
44
- em-websocket
45
- json
46
- rack (~> 1.2.0)
47
- thin
48
- uuidtools
data/lib/tunnel/plugin.rb DELETED
@@ -1,183 +0,0 @@
1
- require "jdc/cli"
2
- require "tunnel/tunnel"
3
-
4
- module JDCTunnelPlugin
5
- class Tunnel < JDC::CLI
6
- CLIENTS_FILE = "tunnel-clients.yml"
7
- STOCK_CLIENTS = File.expand_path("../config/clients.yml", __FILE__)
8
-
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
28
- instances = client.service_instances
29
- fail "No services available for tunneling." if instances.empty?
30
-
31
- instance = input[:instance, instances.sort_by(&:name)]
32
- vendor = instance.service_plan.service.label
33
- clients = tunnel_clients[vendor] || {}
34
- client_name = input[:client, clients]
35
-
36
- tunnel = JDCTunnel.new(client, instance)
37
- port = tunnel.pick_port!(input[:port])
38
-
39
- conn_info =
40
- with_progress("Opening tunnel on port #{c(port, :name)}") do
41
- tunnel.open!
42
- end
43
-
44
- if client_name == "none"
45
- unless quiet?
46
- line
47
- display_tunnel_connection_info(conn_info)
48
-
49
- line
50
- line "Open another shell to run command-line clients or"
51
- line "use a UI tool to connect using the displayed information."
52
- line "Press Ctrl-C to exit..."
53
- end
54
-
55
- tunnel.wait_for_end
56
- else
57
- with_progress("Waiting for local tunnel to become available") do
58
- tunnel.wait_for_start
59
- end
60
-
61
- unless start_local_prog(clients, client_name, conn_info, port)
62
- fail "'#{client_name}' execution failed; is it in your $PATH?"
63
- end
64
- end
65
- end
66
-
67
- def tunnel_clients
68
- return @tunnel_clients if @tunnel_clients
69
- stock_config = YAML.load_file(STOCK_CLIENTS)
70
- custom_config_file = config_file_path
71
-
72
- if File.exists?(custom_config_file)
73
- custom_config = YAML.load_file(custom_config_file)
74
- @tunnel_clients = deep_merge(stock_config, custom_config)
75
- else
76
- @tunnel_clients = stock_config
77
- end
78
- end
79
-
80
- private
81
-
82
- def config_file_path
83
- File.expand_path("#{JDC::CONFIG_DIR}/.jdc/#{CLIENTS_FILE}")
84
- end
85
-
86
- def display_tunnel_connection_info(info)
87
- line "Service connection info:"
88
-
89
- to_show = [nil, nil, nil] # reserved for user, pass, db name
90
- info.keys.each do |k|
91
- case k
92
- when "host", "hostname", "port", "node_id"
93
- # skip
94
- when "user", "username"
95
- # prefer "username" over "user"
96
- to_show[0] = k unless to_show[0] == "username"
97
- when "password"
98
- to_show[1] = k
99
- when "name"
100
- to_show[2] = k
101
- else
102
- to_show << k
103
- end
104
- end
105
- to_show.compact!
106
-
107
- align_len = to_show.collect(&:size).max + 1
108
-
109
- indented do
110
- to_show.each do |k|
111
- # TODO: modify the server services rest call to have explicit knowledge
112
- # about the items to return. It should return all of them if
113
- # the service is unknown so that we don't have to do this weird
114
- # filtering.
115
- line "#{k.ljust align_len}: #{b(info[k])}"
116
- end
117
- end
118
-
119
- line
120
- end
121
-
122
- def start_local_prog(clients, command, info, port)
123
- client = clients[File.basename(command)]
124
-
125
- cmdline = "#{command} "
126
-
127
- case client
128
- when Hash
129
- cmdline << resolve_symbols(client["command"], info, port)
130
- client["environment"].each do |e|
131
- if e =~ /([^=]+)=(["']?)([^"']*)\2/
132
- ENV[$1] = resolve_symbols($3, info, port)
133
- else
134
- fail "Invalid environment variable: #{e}"
135
- end
136
- end
137
- when String
138
- cmdline << resolve_symbols(client, info, port)
139
- else
140
- raise "Unknown client info: #{client.inspect}."
141
- end
142
-
143
- if verbose?
144
- line
145
- line "Launching '#{cmdline}'"
146
- end
147
-
148
- system(cmdline)
149
- end
150
-
151
- def resolve_symbols(str, info, local_port)
152
- str.gsub(/\$\{\s*([^\}]+)\s*\}/) do
153
- sym = $1
154
-
155
- case sym
156
- when "host"
157
- # TODO: determine proper host
158
- "localhost"
159
- when "port"
160
- local_port
161
- when "user", "username"
162
- info["username"]
163
- when /^ask (.+)/
164
- ask($1)
165
- else
166
- info[sym] || raise("Unknown symbol in config: #{sym}")
167
- end
168
- end
169
- end
170
-
171
- def deep_merge(a, b)
172
- merge = proc { |_, old, new|
173
- if old.is_a?(Hash) && new.is_a?(Hash)
174
- old.merge(new, &merge)
175
- else
176
- new
177
- end
178
- }
179
-
180
- a.merge(b, &merge)
181
- end
182
- end
183
- end
data/lib/tunnel/tunnel.rb DELETED
@@ -1,295 +0,0 @@
1
- require "addressable/uri"
2
- require "restclient"
3
- require "uuidtools"
4
-
5
- require "caldecott-client"
6
-
7
- class JDCTunnel
8
- HELPER_NAME = "caldecott"
9
- HELPER_APP = File.expand_path("../helper-app", __FILE__)
10
-
11
- # bump this AND the version info reported by HELPER_APP/server.rb
12
- # this is to keep the helper in sync with any updates here
13
- HELPER_VERSION = "0.0.4"
14
-
15
- def initialize(client, service, port = 10000)
16
- @client = client
17
- @service = service
18
- @port = port
19
- end
20
-
21
- def open!
22
- if helper
23
- auth = helper_auth
24
-
25
- unless helper_healthy?(auth)
26
- delete_helper
27
- auth = create_helper
28
- end
29
- else
30
- auth = create_helper
31
- end
32
-
33
- bind_to_helper if @service && !helper_already_binds?
34
-
35
- info = get_connection_info(auth)
36
-
37
- start_tunnel(info, auth)
38
-
39
- info
40
- end
41
-
42
- def wait_for_start
43
- 10.times do |n|
44
- begin
45
- TCPSocket.open("localhost", @port).close
46
- return true
47
- rescue => e
48
- sleep 1
49
- end
50
- end
51
-
52
- raise "Could not connect to local tunnel."
53
- end
54
-
55
- def wait_for_end
56
- if @local_tunnel_thread
57
- @local_tunnel_thread.join
58
- else
59
- raise "Tunnel wasn't started!"
60
- end
61
- end
62
-
63
- PORT_RANGE = 10
64
- def pick_port!(port = @port)
65
- original = port
66
-
67
- PORT_RANGE.times do |n|
68
- begin
69
- TCPSocket.open("localhost", port)
70
- port += 1
71
- rescue
72
- return @port = port
73
- end
74
- end
75
-
76
- @port = grab_ephemeral_port
77
- end
78
-
79
- private
80
-
81
- def helper
82
- @helper ||= @client.app_by_name(HELPER_NAME)
83
- end
84
-
85
- def create_helper
86
- auth = UUIDTools::UUID.random_create.to_s
87
- push_helper(auth)
88
- start_helper
89
- auth
90
- end
91
-
92
- def helper_auth
93
- helper.env["CALDECOTT_AUTH"]
94
- end
95
-
96
- def helper_healthy?(token)
97
- return false unless helper.healthy?
98
-
99
- begin
100
- response = RestClient.get(
101
- "#{helper_url}/info",
102
- "Auth-Token" => token
103
- )
104
-
105
- info = JSON.parse(response)
106
- if info["version"] == HELPER_VERSION
107
- true
108
- else
109
- stop_helper
110
- false
111
- end
112
- rescue RestClient::Exception
113
- stop_helper
114
- false
115
- end
116
- end
117
-
118
- def helper_already_binds?
119
- helper.binds? @service
120
- end
121
-
122
- def push_helper(token)
123
- app = @client.app
124
- app.name = HELPER_NAME
125
- app.command = "bundle exec ruby server.rb"
126
- app.total_instances = 1
127
- app.memory = 128
128
- app.env = {"CALDECOTT_AUTH" => token}
129
-
130
- space = app.space = @client.current_space
131
- app.create!
132
-
133
- app.bind(@service) if @service
134
-
135
- domain = @client.domains.find { |d| d.owning_organization == nil }
136
-
137
- app.create_route(:domain => domain, :space => space, :host => random_helper_url)
138
-
139
- begin
140
- app.upload(HELPER_APP)
141
- invalidate_tunnel_app_info
142
- rescue
143
- app.delete!
144
- raise
145
- end
146
- end
147
-
148
- def delete_helper
149
- helper.delete!
150
- invalidate_tunnel_app_info
151
- end
152
-
153
- def stop_helper
154
- helper.stop!
155
- invalidate_tunnel_app_info
156
- end
157
-
158
- TUNNEL_CHECK_LIMIT = 60
159
- def start_helper
160
- helper.start!
161
-
162
- seconds = 0
163
- until helper.healthy?
164
- sleep 1
165
- seconds += 1
166
- if seconds == TUNNEL_CHECK_LIMIT
167
- raise "Helper application failed to start."
168
- end
169
- end
170
-
171
- invalidate_tunnel_app_info
172
- end
173
-
174
- def bind_to_helper
175
- helper.bind(@service)
176
- helper.restart!
177
- end
178
-
179
- def invalidate_tunnel_app_info
180
- @helper_url = nil
181
- @helper = nil
182
- end
183
-
184
- def helper_url
185
- return @helper_url if @helper_url
186
-
187
- tun_url = helper.url
188
-
189
- ["https", "http"].each do |scheme|
190
- url = "#{scheme}://#{tun_url}"
191
- begin
192
- RestClient.get(url)
193
-
194
- # https failed
195
- rescue Errno::ECONNREFUSED
196
-
197
- # we expect a 404 since this request isn't auth'd
198
- rescue RestClient::ResourceNotFound
199
- return @helper_url = url
200
- end
201
- end
202
-
203
- raise "Cannot determine URL for #{tun_url}"
204
- end
205
-
206
- def get_connection_info(token)
207
- response = nil
208
- 10.times do
209
- begin
210
- response =
211
- RestClient.get(
212
- helper_url + "/" + safe_path("services", @service.name),
213
- "Auth-Token" => token)
214
-
215
- break
216
- rescue RestClient::Exception => e
217
- sleep 1
218
- end
219
- end
220
-
221
- unless response
222
- raise "Remote tunnel helper is unaware of #{@service.name}!"
223
- end
224
-
225
- is_v2 = @client.is_a?(JFoundry::V2::Client)
226
-
227
- info = JSON.parse(response)
228
- case (is_v2 ? @service.service_plan.service.label : @service.vendor)
229
- when "rabbitmq"
230
- uri = Addressable::URI.parse info["url"]
231
- info["hostname"] = uri.host
232
- info["port"] = uri.port
233
- info["vhost"] = uri.path[1..-1]
234
- info["user"] = uri.user
235
- info["password"] = uri.password
236
- info.delete "url"
237
-
238
- # we use "db" as the "name" for mongo
239
- # existing "name" is junk
240
- when "mongodb"
241
- info["name"] = info["db"]
242
- info.delete "db"
243
-
244
- # our "name" is irrelevant for redis
245
- when "redis"
246
- info.delete "name"
247
-
248
- when "filesystem"
249
- raise "Tunneling is not supported for this type of service"
250
- end
251
-
252
- ["hostname", "port", "password"].each do |k|
253
- raise "Could not determine #{k} for #{@service.name}" if info[k].nil?
254
- end
255
-
256
- info
257
- end
258
-
259
- def start_tunnel(conn_info, auth)
260
- @local_tunnel_thread = Thread.new do
261
- Caldecott::Client.start({
262
- :local_port => @port,
263
- :tun_url => helper_url,
264
- :dst_host => conn_info["hostname"],
265
- :dst_port => conn_info["port"],
266
- :log_file => STDOUT,
267
- :log_level => ENV["JDC_TUNNEL_DEBUG"] || "ERROR",
268
- :auth_token => auth,
269
- :quiet => true
270
- })
271
- end
272
-
273
- at_exit { @local_tunnel_thread.kill }
274
- end
275
-
276
- def random_helper_url
277
- random = sprintf("%x", rand(1000000))
278
- "caldecott-#{random}"
279
- end
280
-
281
- def safe_path(*segments)
282
- segments.flatten.collect { |x|
283
- URI.encode x.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
284
- }.join("/")
285
- end
286
-
287
- def grab_ephemeral_port
288
- socket = TCPServer.new("0.0.0.0", 0)
289
- socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
290
- Socket.do_not_reverse_lookup = true
291
- socket.addr[1]
292
- ensure
293
- socket.close
294
- end
295
- end