'host' part is a bit lax; we rely on 'rhc-list-ports' to hand us a reasonable output about the host information, be it numeric or FQDN in IPv4 or IPv6.
# File lib/rhc/commands/port_forward.rb, line 75 def run(app) rest_app = rest_client.find_application(options.namespace, app) ssh_uri = URI.parse(rest_app.ssh_url) say "Using #{rest_app.ssh_url}..." if options.debug forwarding_specs = [] begin say "Checking available ports..." Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh| ssh.exec! "rhc-list-ports" do |channel, stream, data| if stream == :stderr data.each_line do |line| line.chomp! # FIXME: This is really brittle; there must be a better way # for the server to tell us that permission (what permission?) # is denied. raise RHC::PermissionDeniedException.new "Permission denied." if line =~ %rpermission denied/ # ...and also which services are available for the application # for us to forward ports for. if line =~ %r\A\s*(\S+) -> #{HOST_AND_PORT}\z/ debug fs = ForwardingSpec.new($1, $2, $3.to_i) forwarding_specs << fs else debug line end end end end if forwarding_specs.length == 0 # check if the gears have been stopped ggs = rest_app.gear_groups if ggs.any? { |gg| gears = gg.gears true if gears.any? { |g| g["state"] == "stopped" } } warn "Application #{rest_app.name} is stopped. Please restart the application and try again." return 1 else raise RHC::NoPortsToForwardException.new "There are no available ports to forward for this application. Your application may be stopped." end end begin Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh| say "Forwarding ports" forwarding_specs.each do |fs| given_up = nil while !fs.bound? && !given_up begin args = fs.to_fwd_args debug args.inspect ssh.forward.local(*args) fs.bound = true rescue Errno::EADDRINUSE, Errno::EACCES => e warn "#{e} while forwarding port #{fs.port_from}. Trying local port #{fs.port_from+1}" fs.port_from += 1 rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e given_up = true end end end bound_ports = forwarding_specs.select(&:bound?) if bound_ports.length > 0 paragraph { say "To connect to a service running on OpenShift, use the Local address" } items = bound_ports.map do |fs| [fs.service, "#{fs.host_from}:#{fs.port_from}", " => ", "#{fs.remote_host}:#{fs.port_to.to_s}"] end table(items, :header => ["Service", "Local", " ", "OpenShift"]).each { |s| success " #{s}" } end # for failed port forwarding attempts failed_port_forwards = forwarding_specs.select { |fs| !fs.bound? } if failed_port_forwards.length > 0 ssh_cmd_arg = failed_port_forwards.map { |fs| fs.to_cmd_arg }.join(" ") ssh_cmd = "ssh -N #{ssh_cmd_arg} #{ssh_uri.user}@#{ssh_uri.host}" warn "Error forwarding some port(s). You can try to forward manually by running:\n#{ssh_cmd}" else say "Press CTRL-C to terminate port forwarding" end unless forwarding_specs.any?(&:bound?) warn "No ports have been bound" return end ssh.loop { true } end rescue Interrupt results { say "Ending port forward" } return 0 end end rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e ssh_cmd = ["ssh","-N"] unbound_fs = forwarding_specs.select { |fs| !fs.bound? } ssh_cmd += unbound_fs.map { |fs| fs.to_cmd_arg } ssh_cmd += ["#{ssh_uri.user}@#{ssh_uri.host}"] raise RHC::PortForwardFailedException.new("#{e.message + "\n" if options.debug}Error trying to forward ports. You can try to forward manually by running:\n" + ssh_cmd.join(" ")) end 0 rescue RHC::Rest::ConnectionException => e error "Connection to #{openshift_server} failed: #{e.message}" 1 end