class CFTunnelPlugin::Tunnel
Constants
- CLIENTS_FILE
- STOCK_CLIENTS
Public Instance Methods
tunnel()
click to toggle source
# File lib/tunnel/plugin.rb, line 27 def tunnel instances = client.service_instances fail "No services available for tunneling." if instances.empty? instance = input[:instance, instances.sort_by(&:name)] vendor = instance.service_plan.service.label clients = tunnel_clients[vendor] || {} client_name = input[:client, clients] tunnel = CFTunnel.new(client, instance) port = tunnel.pick_port!(input[:port]) conn_info = with_progress("Opening tunnel on port #{c(port, :name)}") do tunnel.open! end if client_name == "none" unless quiet? line display_tunnel_connection_info(conn_info) line line "Open another shell to run command-line clients or" line "use a UI tool to connect using the displayed information." line "Press Ctrl-C to exit..." end tunnel.wait_for_end else with_progress("Waiting for local tunnel to become available") do tunnel.wait_for_start end unless start_local_prog(clients, client_name, conn_info, port) fail "'#{client_name}' execution failed; is it in your $PATH?" end end end
tunnel_clients()
click to toggle source
# File lib/tunnel/plugin.rb, line 67 def tunnel_clients return @tunnel_clients if @tunnel_clients stock_config = YAML.load_file(STOCK_CLIENTS) custom_config_file = config_file_path if File.exists?(custom_config_file) custom_config = YAML.load_file(custom_config_file) @tunnel_clients = deep_merge(stock_config, custom_config) else @tunnel_clients = stock_config end end
Private Instance Methods
config_file_path()
click to toggle source
# File lib/tunnel/plugin.rb, line 82 def config_file_path File.expand_path("#{CF::CONFIG_DIR}/#{CLIENTS_FILE}") end
deep_merge(a, b)
click to toggle source
# File lib/tunnel/plugin.rb, line 171 def deep_merge(a, b) merge = proc { |_, old, new| if old.is_a?(Hash) && new.is_a?(Hash) old.merge(new, &merge) else new end } a.merge(b, &merge) end
display_tunnel_connection_info(info)
click to toggle source
# File lib/tunnel/plugin.rb, line 86 def display_tunnel_connection_info(info) line "Service connection info:" to_show = [nil, nil, nil] # reserved for user, pass, db name info.keys.each do |k| case k when "host", "hostname", "port", "node_id" # skip when "user", "username" # prefer "username" over "user" to_show[0] = k unless to_show[0] == "username" when "password" to_show[1] = k when "name" to_show[2] = k else to_show << k end end to_show.compact! align_len = to_show.collect(&:size).max + 1 indented do to_show.each do |k| # TODO: modify the server services rest call to have explicit knowledge # about the items to return. It should return all of them if # the service is unknown so that we don't have to do this weird # filtering. line "#{k.ljust align_len}: #{b(info[k])}" end end line end
resolve_symbols(str, info, local_port)
click to toggle source
# File lib/tunnel/plugin.rb, line 151 def resolve_symbols(str, info, local_port) str.gsub(/\$\{\s*([^\}]+)\s*\}/) do sym = $1 case sym when "host" # TODO: determine proper host "localhost" when "port" local_port when "user", "username" info["username"] when /^ask (.+)/ ask($1) else info[sym] || raise("Unknown symbol in config: #{sym}") end end end
start_local_prog(clients, command, info, port)
click to toggle source
# File lib/tunnel/plugin.rb, line 122 def start_local_prog(clients, command, info, port) client = clients[File.basename(command)] cmdline = "#{command} " case client when Hash cmdline << resolve_symbols(client["command"], info, port) client["environment"].each do |e| if e =~ /([^=]+)=(["']?)([^"']*)\2/ ENV[$1] = resolve_symbols($3, info, port) else fail "Invalid environment variable: #{e}" end end when String cmdline << resolve_symbols(client, info, port) else raise "Unknown client info: #{client.inspect}." end if verbose? line line "Launching '#{cmdline}'" end system(cmdline) end