jdc 0.2.1 → 0.2.2.pre

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.
Files changed (151) hide show
  1. data/LICENSE +1277 -24
  2. data/Rakefile +13 -0
  3. data/bin/jdc +12 -2
  4. data/lib/admin/README.md +15 -0
  5. data/lib/admin/curl.rb +60 -0
  6. data/lib/admin/guid.rb +89 -0
  7. data/lib/admin/plugin.rb +6 -0
  8. data/lib/admin/service_auth_token.rb +94 -0
  9. data/lib/admin/service_broker/add.rb +47 -0
  10. data/lib/admin/service_broker/service_brokers.rb +24 -0
  11. data/lib/admin/set_quota.rb +44 -0
  12. data/lib/console/README.md +8 -0
  13. data/lib/console/console.rb +187 -0
  14. data/lib/console/plugin.rb +33 -0
  15. data/lib/jdc.rb +15 -2
  16. data/lib/jdc/cli.rb +556 -0
  17. data/lib/jdc/cli/app/app.rb +43 -0
  18. data/lib/jdc/cli/app/apps.rb +87 -0
  19. data/lib/jdc/cli/app/base.rb +72 -0
  20. data/lib/jdc/cli/app/delete.rb +95 -0
  21. data/lib/jdc/cli/app/deprecated.rb +11 -0
  22. data/lib/jdc/cli/app/env.rb +78 -0
  23. data/lib/jdc/cli/app/events.rb +45 -0
  24. data/lib/jdc/cli/app/files.rb +137 -0
  25. data/lib/jdc/cli/app/health.rb +26 -0
  26. data/lib/jdc/cli/app/instances.rb +53 -0
  27. data/lib/jdc/cli/app/logs.rb +76 -0
  28. data/lib/jdc/cli/app/push.rb +103 -0
  29. data/lib/jdc/cli/app/push/create.rb +108 -0
  30. data/lib/jdc/cli/app/push/interactions.rb +86 -0
  31. data/lib/jdc/cli/app/push/sync.rb +57 -0
  32. data/lib/jdc/cli/app/rename.rb +35 -0
  33. data/lib/jdc/cli/app/restart.rb +31 -0
  34. data/lib/jdc/cli/app/scale.rb +63 -0
  35. data/lib/jdc/cli/app/start.rb +161 -0
  36. data/lib/jdc/cli/app/stats.rb +67 -0
  37. data/lib/jdc/cli/app/stop.rb +27 -0
  38. data/lib/jdc/cli/domain/base.rb +9 -0
  39. data/lib/jdc/cli/domain/domains.rb +40 -0
  40. data/lib/jdc/cli/domain/map.rb +55 -0
  41. data/lib/jdc/cli/domain/unmap.rb +56 -0
  42. data/lib/jdc/cli/help.rb +15 -0
  43. data/lib/jdc/cli/interactive.rb +105 -0
  44. data/lib/jdc/cli/login_requirements.rb +15 -0
  45. data/lib/jdc/cli/organization/base.rb +14 -0
  46. data/lib/jdc/cli/organization/create.rb +37 -0
  47. data/lib/jdc/cli/organization/delete.rb +63 -0
  48. data/lib/jdc/cli/organization/org.rb +45 -0
  49. data/lib/jdc/cli/organization/orgs.rb +30 -0
  50. data/lib/jdc/cli/organization/rename.rb +37 -0
  51. data/lib/jdc/cli/populators/base.rb +16 -0
  52. data/lib/jdc/cli/populators/organization.rb +32 -0
  53. data/lib/jdc/cli/populators/populator_methods.rb +64 -0
  54. data/lib/jdc/cli/populators/space.rb +33 -0
  55. data/lib/jdc/cli/populators/target.rb +13 -0
  56. data/lib/jdc/cli/route/base.rb +9 -0
  57. data/lib/jdc/cli/route/delete.rb +28 -0
  58. data/lib/jdc/cli/route/map.rb +68 -0
  59. data/lib/jdc/cli/route/routes.rb +26 -0
  60. data/lib/jdc/cli/route/unmap.rb +56 -0
  61. data/lib/jdc/cli/service/base.rb +9 -0
  62. data/lib/jdc/cli/service/bind.rb +44 -0
  63. data/lib/jdc/cli/service/create.rb +159 -0
  64. data/lib/jdc/cli/service/delete.rb +83 -0
  65. data/lib/jdc/cli/service/rename.rb +36 -0
  66. data/lib/jdc/cli/service/service.rb +42 -0
  67. data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
  68. data/lib/jdc/cli/service/services.rb +111 -0
  69. data/lib/jdc/cli/service/unbind.rb +37 -0
  70. data/lib/jdc/cli/space/base.rb +29 -0
  71. data/lib/jdc/cli/space/create.rb +67 -0
  72. data/lib/jdc/cli/space/delete.rb +56 -0
  73. data/lib/jdc/cli/space/rename.rb +38 -0
  74. data/lib/jdc/cli/space/space.rb +66 -0
  75. data/lib/jdc/cli/space/spaces.rb +57 -0
  76. data/lib/jdc/cli/space/switch.rb +19 -0
  77. data/lib/jdc/cli/start/base.rb +41 -0
  78. data/lib/jdc/cli/start/colors.rb +13 -0
  79. data/lib/jdc/cli/start/target.rb +50 -0
  80. data/lib/jdc/cli/start/target_prettifier.rb +17 -0
  81. data/lib/jdc/cli/start/targets.rb +16 -0
  82. data/lib/jdc/cli/user/base.rb +30 -0
  83. data/lib/jdc/cli/user/create.rb +52 -0
  84. data/lib/jdc/cli/user/passwd.rb +37 -0
  85. data/lib/jdc/cli/user/register.rb +43 -0
  86. data/lib/jdc/cli/user/users.rb +32 -0
  87. data/lib/jdc/constants.rb +11 -0
  88. data/lib/jdc/errors.rb +19 -0
  89. data/lib/jdc/object_extensions.rb +15 -0
  90. data/lib/jdc/plugin.rb +56 -0
  91. data/lib/jdc/spacing.rb +89 -0
  92. data/lib/jdc/spec_helper.rb +1 -0
  93. data/lib/jdc/test_support.rb +6 -0
  94. data/lib/jdc/version.rb +3 -0
  95. data/lib/manifests/errors.rb +35 -0
  96. data/lib/manifests/loader.rb +31 -0
  97. data/lib/manifests/loader/builder.rb +39 -0
  98. data/lib/manifests/loader/normalizer.rb +145 -0
  99. data/lib/manifests/loader/resolver.rb +79 -0
  100. data/lib/manifests/manifests.rb +344 -0
  101. data/lib/manifests/plugin.rb +140 -0
  102. data/lib/micro/README.md +9 -0
  103. data/lib/micro/errors.rb +4 -0
  104. data/lib/{jdc → micro}/micro.rb +15 -15
  105. data/lib/micro/plugin.rb +197 -0
  106. data/lib/micro/switcher/base.rb +79 -0
  107. data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
  108. data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
  109. data/lib/micro/switcher/linux.rb +16 -0
  110. data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
  111. data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
  112. data/lib/tasks/gem_release.rake +42 -0
  113. data/lib/tunnel/README.md +29 -0
  114. data/{config → lib/tunnel/config}/clients.yml +2 -2
  115. data/lib/tunnel/helper-app/Gemfile +10 -0
  116. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  117. data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
  118. data/lib/tunnel/plugin.rb +183 -0
  119. data/lib/tunnel/tunnel.rb +295 -0
  120. metadata +371 -210
  121. data/README.md +0 -102
  122. data/config/micro/paths.yml +0 -22
  123. data/config/micro/refresh_ip.rb +0 -20
  124. data/lib/cli.rb +0 -53
  125. data/lib/cli/commands/admin.rb +0 -58
  126. data/lib/cli/commands/apps.rb +0 -1129
  127. data/lib/cli/commands/base.rb +0 -228
  128. data/lib/cli/commands/manifest.rb +0 -56
  129. data/lib/cli/commands/micro.rb +0 -115
  130. data/lib/cli/commands/misc.rb +0 -126
  131. data/lib/cli/commands/services.rb +0 -178
  132. data/lib/cli/commands/user.rb +0 -14
  133. data/lib/cli/config.rb +0 -173
  134. data/lib/cli/console_helper.rb +0 -170
  135. data/lib/cli/core_ext.rb +0 -122
  136. data/lib/cli/errors.rb +0 -19
  137. data/lib/cli/frameworks.rb +0 -265
  138. data/lib/cli/manifest_helper.rb +0 -300
  139. data/lib/cli/runner.rb +0 -505
  140. data/lib/cli/services_helper.rb +0 -84
  141. data/lib/cli/tunnel_helper.rb +0 -332
  142. data/lib/cli/usage.rb +0 -86
  143. data/lib/cli/version.rb +0 -7
  144. data/lib/cli/zip_util.rb +0 -77
  145. data/lib/jdc/client.rb +0 -457
  146. data/lib/jdc/const.rb +0 -25
  147. data/lib/jdc/micro/switcher/base.rb +0 -97
  148. data/lib/jdc/micro/switcher/linux.rb +0 -16
  149. data/lib/jdc/signature/version.rb +0 -27
  150. data/lib/jdc/signer.rb +0 -13
  151. data/lib/jdc/timer.rb +0 -12
@@ -1,8 +1,10 @@
1
- module JDC::Micro::Switcher
1
+ require "micro/errors"
2
+
3
+ module JDCMicro::Switcher
2
4
 
3
5
  class Darwin < Base
4
6
  def adminrun(command)
5
- JDC::Micro.run_command("osascript", "-e 'do shell script \"#{command}\" with administrator privileges'")
7
+ JDCMicro.run_command("osascript", "-e 'do shell script \"#{command}\" with administrator privileges'")
6
8
  end
7
9
 
8
10
  def set_nameserver(domain, ip)
@@ -11,7 +13,7 @@ module JDC::Micro::Switcher
11
13
  end
12
14
 
13
15
  def unset_nameserver(domain, ip)
14
- err "domain missing" unless domain
16
+ raise JDCMicro::MCFError, "domain missing" unless domain
15
17
  adminrun("rm -f /etc/resolver/#{domain}")
16
18
  end
17
19
  end
@@ -1,5 +1,5 @@
1
1
  # only used for testing
2
- module JDC::Micro::Switcher
2
+ module JDCMicro::Switcher
3
3
 
4
4
  class Dummy < Base
5
5
  def adminrun(command)
@@ -0,0 +1,16 @@
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,19 +1,19 @@
1
- module JDC::Micro::Switcher
1
+ module JDCMicro::Switcher
2
2
 
3
3
  class Windows < Base
4
- def version?
5
- JDC::Micro.run_command("cmd", "/c ver").to_s.scan(/\d+\.\d+/).first.to_f
4
+ def version
5
+ JDCMicro.run_command("cmd", "/c ver").to_s.scan(/\d+\.\d+/).first.to_f
6
6
  end
7
7
 
8
8
  def adminrun(command, args=nil)
9
- if version? > 5.2
9
+ if version > 5.2
10
10
  require 'win32ole'
11
11
  shell = WIN32OLE.new("Shell.Application")
12
12
  shell.ShellExecute(command, args, nil, "runas", 0)
13
13
  else
14
14
  # on older version this will try to run the command, and if you don't have
15
15
  # admin privilges it will tell you so and exit
16
- JDC::Micro.run_command(command, args)
16
+ JDCMicro.run_command(command, args)
17
17
  end
18
18
  end
19
19
 
@@ -1,13 +1,15 @@
1
- module JDC::Micro
1
+ require "micro/errors"
2
+
3
+ module JDCMicro
2
4
  class VMrun
3
5
  attr_reader :vmx, :vmrun
4
6
 
5
7
  def initialize(config)
6
- @platform = config['platform']
8
+ @platform = config[:platform]
7
9
  @user = 'root' # must use root as we muck around with system settings
8
- @password = config['password']
9
- @vmrun = config['vmrun']
10
- @vmx = config['vmx']
10
+ @password = config[:password]
11
+ @vmrun = config[:vmrun]
12
+ @vmx = config[:vmx]
11
13
 
12
14
  # TODO honor TMPDIR
13
15
  if @platform == :windows
@@ -17,6 +19,10 @@ module JDC::Micro
17
19
  end
18
20
  end
19
21
 
22
+ def vmx
23
+ @vmx
24
+ end
25
+
20
26
  def connection_type
21
27
  read_variable('ethernet0.connectionType')
22
28
  end
@@ -35,7 +41,7 @@ module JDC::Micro
35
41
 
36
42
  def domain
37
43
  # switch to Dir.mktmpdir
38
- state_config = JDC::Micro.escape_path(File.join(@temp_dir, 'state.yml'))
44
+ state_config = JDCMicro.escape_path(File.join(@temp_dir, 'state.yml'))
39
45
  run('CopyFileFromGuestToHost', "/var/vcap/bosh/state.yml #{state_config}")
40
46
  bosh_config = YAML.load_file(state_config)
41
47
  bosh_config['properties']['domain']
@@ -43,8 +49,8 @@ module JDC::Micro
43
49
 
44
50
  def ip
45
51
  # switch to Dir.mktmpdir
46
- path = JDC::Micro.escape_path(JDC::Micro.config_file('refresh_ip.rb'))
47
- ip_file = JDC::Micro.escape_path(File.join(@temp_dir, 'ip.txt'))
52
+ path = JDCMicro.escape_path(JDCMicro.config_file('refresh_ip.rb'))
53
+ ip_file = JDCMicro.escape_path(File.join(@temp_dir, 'ip.txt'))
48
54
  run('CopyFileFromHostToGuest', "#{path} /tmp/refresh_ip.rb")
49
55
  run('runProgramInGuest', '/tmp/refresh_ip.rb')
50
56
  run('CopyFileFromGuestToHost', "/tmp/ip.txt #{ip_file}")
@@ -54,7 +60,7 @@ module JDC::Micro
54
60
  def list
55
61
  vms = run("list")
56
62
  vms.delete_if { |line| line =~ /^Total/ }
57
- vms.map { |line| JDC::Micro.escape_path(File.expand_path(line)) }
63
+ vms.map { |line| JDCMicro.escape_path(File.expand_path(line)) }
58
64
  end
59
65
 
60
66
  def offline?
@@ -68,12 +74,12 @@ module JDC::Micro
68
74
  elsif $?.exitstatus == 0
69
75
  return true
70
76
  else
71
- raise "failed to execute vmrun:\n#{result}"
77
+ raise JDCMicro::MCFError, "failed to execute vmrun:\n#{result}"
72
78
  end
73
79
  end
74
80
 
75
81
  def offline!
76
- path = JDC::Micro.escape_path(JDC::Micro.config_file('offline.conf'))
82
+ path = JDCMicro.escape_path(JDCMicro.config_file('offline.conf'))
77
83
  run('CopyFileFromHostToGuest', "#{path} /etc/dnsmasq.d/offline.conf")
78
84
  run('runProgramInGuest', '/usr/bin/touch /var/vcap/micro/offline')
79
85
  run('runProgramInGuest',
@@ -101,7 +107,7 @@ module JDC::Micro
101
107
  elsif $?.exitstatus == 1
102
108
  return false
103
109
  else
104
- raise "failed to execute vmrun:\n#{result}"
110
+ raise JDCMicro::MCFError, "failed to execute vmrun:\n#{result}"
105
111
  end
106
112
  end
107
113
 
@@ -128,14 +134,15 @@ module JDC::Micro
128
134
  if command.include?('Guest')
129
135
  command = "-gu #{@user} -gp #{@password} #{command}"
130
136
  end
131
- JDC::Micro.run_command(@vmrun, "#{command} #{@vmx} #{args}")
137
+ JDCMicro.run_command(@vmrun, "#{command} #{@vmx} #{args}")
132
138
  end
133
139
 
134
140
  def running?
135
141
  vms = list
136
142
  if @platform == :windows
137
- vms.map! { |x| x.downcase }
138
- vms.include?(@vmx.downcase)
143
+ vms.any? { |x|
144
+ x.downcase == @vmx.downcase
145
+ }
139
146
  else
140
147
  # Handle vmx being in a symlinked dir.
141
148
  real_path = nil
@@ -147,19 +154,19 @@ module JDC::Micro
147
154
  end
148
155
  end
149
156
 
150
- def start
157
+ def start!
151
158
  run('start') unless running?
152
159
  end
153
160
 
154
- def stop
161
+ def stop!
155
162
  run('stop') if running?
156
163
  end
157
164
 
158
165
  def self.locate(platform)
159
- paths = YAML.load_file(JDC::Micro.config_file('paths.yml'))
166
+ paths = YAML.load_file(JDCMicro.config_file('paths.yml'))
160
167
  vmrun_paths = paths[platform.to_s]['vmrun']
161
168
  vmrun_exe = @platform == :windows ? 'vmrun.exe' : 'vmrun'
162
- vmrun = JDC::Micro.locate_file(vmrun_exe, "VMware", vmrun_paths)
169
+ vmrun = JDCMicro.locate_file(vmrun_exe, "VMware", vmrun_paths)
163
170
  err "Unable to locate vmrun, please supply --vmrun option" unless vmrun
164
171
  vmrun
165
172
  end
@@ -0,0 +1,42 @@
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
@@ -0,0 +1,29 @@
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
+
@@ -3,12 +3,12 @@ redis:
3
3
 
4
4
  mysql:
5
5
  mysql: --protocol=TCP --host=${host} --port=${port} --user=${user} --password=${password} ${name}
6
- mysqldump: --protocol=TCP --host=${host} --port=${port} --user=${user} --password=${password} ${name} > ${Output file}
6
+ mysqldump: --protocol=TCP --host=${host} --port=${port} --user=${user} --password=${password} ${name} > ${ask Output file}
7
7
 
8
8
  mongodb:
9
9
  mongo: --host ${host} --port ${port} -u ${user} -p ${password} ${name}
10
10
  mongodump: --host ${host} --port ${port} -u ${user} -p ${password} --db ${name}
11
- mongorestore: --host ${host} --port ${port} -u ${user} -p ${password} --db ${name} ${Directory or filename to restore from}
11
+ mongorestore: --host ${host} --port ${port} -u ${user} -p ${password} --db ${name} ${ask Directory or filename to restore from}
12
12
 
13
13
  postgresql:
14
14
  psql:
@@ -0,0 +1,10 @@
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'
@@ -0,0 +1,48 @@
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
@@ -10,7 +10,7 @@ require 'sinatra'
10
10
  require 'json'
11
11
  require 'eventmachine'
12
12
 
13
- port = ENV['JDC_APP_PORT']
13
+ port = ENV['PORT']
14
14
  port ||= 8081
15
15
 
16
16
  # add vcap specific stuff to Caldecott
@@ -24,19 +24,19 @@ class VcapHttpTunnel < Caldecott::Server::HttpTunnel
24
24
  end
25
25
 
26
26
  get '/services' do
27
- services_env = ENV['JDC_SERVICES']
27
+ services_env = ENV['VCAP_SERVICES']
28
28
  return "no services env" if services_env.nil? or services_env.empty?
29
29
  services_env
30
30
  end
31
31
 
32
32
  get '/services/:service' do |service_name|
33
- services_env = ENV['JDC_SERVICES']
33
+ services_env = ENV['VCAP_SERVICES']
34
34
  not_found if services_env.nil?
35
35
 
36
- services = JSON.parse(services_env)
36
+ services = JSON.parse(services_env).values.flatten(1)
37
37
  service = services.find { |s| s["name"] == service_name }
38
38
  not_found if service.nil?
39
- service["options"].to_json
39
+ service["credentials"].to_json
40
40
  end
41
41
  end
42
42
 
@@ -0,0 +1,183 @@
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