module RHC
Some parts adapted from golang.org/src/pkg/json/decode.go and golang.org/src/pkg/utf8/utf8.go
Note: A group is a set of parameters defined for a subpart of a config file
Constants
- BOUND_WARNING
- CertificateFile
- CertificateKey
Public Instance Methods
By default, agree should take a single character in interactive
# File lib/rhc/helpers.rb, line 294 def agree(*args, &block) #args.push(interactive?.presence) if args.length == 1 block = lambda do |q| q.validate = /\A(?:y|yes|n|no)\Z/i end unless block_given? super *args, &block end
# File lib/rhc/helpers.rb, line 233 def certificate_file(file) file && OpenSSL::X509::Certificate.new(IO.read(File.expand_path(file))) rescue => e debug e raise OptionParser::InvalidOption.new(nil, "The certificate '#{file}' cannot be loaded: #{e.message} (#{e.class})") end
# File lib/rhc/helpers.rb, line 240 def certificate_fingerprint(file) Digest::SHA1.hexdigest(certificate_file(file).to_der) end
# File lib/rhc/helpers.rb, line 244 def certificate_key(file) file && OpenSSL::PKey::RSA.new(IO.read(File.expand_path(file))) rescue => e debug e raise OptionParser::InvalidOption.new(nil, "The RSA key '#{file}' cannot be loaded: #{e.message} (#{e.class})") end
return supplied ssh executable, if valid (executable, searches $PATH). if none was supplied, return installed ssh, if any.
# File lib/rhc/ssh_helpers.rb, line 472 def check_ssh_executable!(path) if not path discover_ssh_executable.tap do |ssh_cmd| raise RHC::InvalidSSHExecutableException.new("No system SSH available. Please use the --ssh option to specify the path to your SSH executable, or install SSH.#{windows? ? ' We recommend this free application: Git for Windows - a basic git command line and GUI client http://msysgit.github.io/.' : ''}") unless ssh_cmd or has_ssh? end else bin_path = split_path(path)[0] raise RHC::InvalidSSHExecutableException.new("SSH executable '#{bin_path}' does not exist.") unless File.exist?(bin_path) or File.exist?(path) or exe?(bin_path) raise RHC::InvalidSSHExecutableException.new("SSH executable '#{bin_path}' is not executable.") unless File.executable?(path) or File.executable?(bin_path) or exe?(bin_path) path end end
# File lib/rhc/helpers.rb, line 214 def client_from_options(opts) RHC::Rest::Client.new({ :url => openshift_rest_endpoint.to_s, :debug => options.debug, :headers => parse_headers(options.header), :timeout => options.timeout, :warn => BOUND_WARNING, :api_always_auth => options.always_auth }.merge!(ssl_options).merge!(opts)) end
# File lib/rhc/helpers.rb, line 497 def collect_env_vars(items) return nil if items.blank? env_vars = [] Array(items).each do |item| if match = item.match(env_var_regex_pattern) name, value = match.captures env_vars << RHC::Rest::EnvironmentVariable.new({ :name => name, :value => value }) elsif File.file? item File.readlines(item).each do |line| if match = line.match(env_var_regex_pattern) name, value = match.captures env_vars << RHC::Rest::EnvironmentVariable.new({ :name => name, :value => value }) end end end end env_vars end
OVERRIDE: Replaces default commander behavior
# File lib/rhc/helpers.rb, line 325 def color(item, *args) unless (options.raw rescue false) if item.is_a? Array item.map{ |i| $terminal.color(i, *args) } else $terminal.color(item, *args) end else item end end
# File lib/rhc/helpers.rb, line 302 def confirm_action(question) return if options.confirm return if !options.noprompt && paragraph{ agree "#{question} (yes|no): " } raise RHC::ConfirmationError end
# File lib/rhc/helpers.rb, line 263 def debug(*args) $terminal.debug(*args) end
# File lib/rhc/helpers.rb, line 269 def debug? $terminal.debug? end
# File lib/rhc/helpers.rb, line 266 def debug_error(*args) $terminal.debug_error(*args) end
# File lib/rhc/helpers.rb, line 286 def deprecated(msg,short = false) raise DeprecatedError.new(msg % ['an error','a warning',0]) if disable_deprecated? warn "Warning: #{msg}\n" % ['a warning','an error',1] end
# File lib/rhc/helpers.rb, line 282 def deprecated_command(correct, short=false) deprecated("This command is deprecated. Please use '#{correct}' instead.", short) end
# File lib/rhc/helpers.rb, line 278 def disable_deprecated? ENV['DISABLE_DEPRECATED'] == '1' end
# File lib/rhc/helpers.rb, line 536 def discover_windows_executables(&block) #:nocov: if RHC::Helpers.windows? base_path = [] guessing_locations = [] # Look for the base path int the ProgramFiles env var... if program_files = ENV['ProgramFiles']; program_files.present? && File.exists?(program_files) base_path << program_files end # ... and in win32ole drives (drive root or Program Files) begin require 'win32ole' WIN32OLE.new("Scripting.FileSystemObject").tap do |file_system| file_system.Drives.each do |drive| base_path << [ "#{drive.DriveLetter}:\\Program Files (x86)", "#{drive.DriveLetter}:\\Program Files", "#{drive.DriveLetter}:\\Progra~1", "#{drive.DriveLetter}:" ] end end rescue end # executables array from block executable_groups = [] base_path.flatten.uniq.each do |base| executable_groups << yield(base) end # give proper priorities unless executable_groups.empty? length = executable_groups.first.length for i in 1..length do executable_groups.each do |group| guessing_locations << group[i - 1] end end end guessing_locations.flatten.uniq.select {|cmd| File.exist?(cmd) && File.executable?(cmd)} else [] end #:nocov: end
# File lib/rhc/helpers.rb, line 493 def env_var_regex_pattern /^([a-zA-Z_][\w]*)=(.*)$/ end
# File lib/rhc/helpers.rb, line 320 def error(msg, *args) say color(msg, :red), *args end
# File lib/rhc/helpers.rb, line 587 def exe?(executable) ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| File.executable?(File.join(directory, executable.to_s)) end end
# File lib/rhc/helpers.rb, line 273 def exec(cmd) output = Kernel.send(:`, cmd) [$?.exitstatus, output] end
Check if host exists
# File lib/rhc/helpers.rb, line 432 def host_exists?(host) # :nocov: # Patch for BZ840938 to support Ruby 1.8 on machines without /etc/resolv.conf dns = Resolv::DNS.new((Resolv::DNS::Config.default_config_hash || {})) resources = dns.getresources(host, Resolv::DNS::Resource::IN::A) debug("Checking for #{host} from Resolv::DNS: #{resources.inspect}") if debug? resources.present? # :nocov: end
# File lib/rhc/helpers.rb, line 442 def hosts_file_contains?(host) with_tolerant_encoding do begin resolver = Resolv::Hosts.new result = resolver.getaddress host debug("Checking for #{host} from Resolv::Hosts: #{result.inspect}") if debug? result rescue => e debug "Application could not be resolved through Hosts file: #{e.message}(#{e.class})\n #{e.backtrace.join("\n ")}\n Attempting DNS resolution." end end end
# File lib/rhc/helpers.rb, line 312 def info(msg, *args) say color(msg, :cyan), *args end
Output helpers
# File lib/rhc/helpers.rb, line 259 def interactive? $stdin.tty? and $stdout.tty? and not options.noprompt end
Platform helpers
# File lib/rhc/helpers.rb, line 424 def jruby? ; RUBY_PLATFORM =~ /java/i end
# File lib/rhc/helpers.rb, line 427 def mac? ; RbConfig::CONFIG['host_os'] =~ /^darwin/ end
# File lib/rhc/helpers.rb, line 205 def parse_headers(headers) Hash[ Array(headers).map do |header| key, value = header.split(/: */, 2) [key, value || ""] if key.presence end.compact ] end
# File lib/rhc/helpers.rb, line 251 def parse_ssl_version(version) OpenSSL::SSL::SSLContext::METHODS.find{ |m| m.to_s.downcase == version.to_s.downcase } or raise OptionParser::InvalidOption.new(nil, "The provided SSL version '#{version}' is not valid. Supported values: #{OpenSSL::SSL::SSLContext::METHODS.map(&:to_s).map(&:downcase).join(', ')}") unless version.nil? end
# File lib/rhc/helpers.rb, line 343 def pluralize(count, s) count == 1 ? "#{count} #{s}" : "#{count} #{s}s" end
results
highline helper which creates a paragraph with a header to distinguish the final results of a command from other output
# File lib/rhc/helpers.rb, line 416 def results(&block) section(:top => 1, :bottom => 0) do say "RESULT:" yield end end
# File lib/rhc/helpers.rb, line 161 def role_name(s) ROLES[s.downcase] end
Run a command and export its output to the user. Output is not capturable on all platforms.
# File lib/rhc/helpers.rb, line 476 def run_with_tee(cmd) status, stdout, stderr = nil if windows? || jruby? #:nocov: TODO: Test block system(cmd) status = $?.exitstatus #:nocov: else stdout, stderr = [$stdout, $stderr].map{ |t| StringTee.new(t) } status = Open4.spawn(cmd, 'stdout' => stdout, 'stderr' => stderr, 'quiet' => true) stdout, stderr = [stdout, stderr].map(&:string) end [status, stdout, stderr] end
split spaces but preserve sentences between quotes
# File lib/rhc/helpers.rb, line 524 def split_path(s, keep_quotes=false) #:nocov: if keep_quotes s.split(/\s(?=(?:[^"]|"[^"]*")*$)/) elsif RUBY_VERSION.to_f < 1.9 CSV::parse_line(s, fs = ' ') else #ruby 1.9 or newer CSV::parse_line(s, :col_sep => ' ') end #:nocov: end
# File lib/rhc/helpers.rb, line 177 def ssh_string(ssh_url) return nil if ssh_url.blank? uri = URI.parse(ssh_url) "#{uri.user}@#{uri.host}" rescue => e RHC::Helpers.debug_error(e) ssh_url end
# File lib/rhc/helpers.rb, line 186 def ssh_string_parts(ssh_url) uri = URI.parse(ssh_url) [uri.host, uri.user] end
# File lib/rhc/helpers.rb, line 225 def ssl_options { :ssl_version => options.ssl_version, :ca_file => options.ssl_ca_file && File.expand_path(options.ssl_ca_file), :verify_mode => options.insecure ? OpenSSL::SSL::VERIFY_NONE : nil, }.delete_if{ |k,v| v.nil? } end
# File lib/rhc/helpers.rb, line 308 def success(msg, *args) say color(msg, :green), *args end
# File lib/rhc/servers.rb, line 190 def suggest_server_nickname(hostname) suggestion = (case hostname when openshift_online_server_regex 'online' when /^(.*)\.#{openshift_online_server.gsub(/\./, '\.')}$/i $1 else 'server' + ((list.compact.map{|i| i.match(/^server(\d+)$/)}.compact.map{|i| i[1]}.map(&:to_i).max + 1).to_s rescue '1') end) s = nickname_exists?(suggestion) s.present? && s.hostname != hostname ? nil : suggestion end
This will format table headings for a consistent look and feel
If a heading isn't explicitly defined, it will attempt to look up the parts If those aren't found, it will capitalize the string
# File lib/rhc/helpers.rb, line 350 def table_heading(value) # Set the default proc to look up undefined values headings = Hash.new do |hash,key| items = key.to_s.split('_') # Look up each piece individually hash[key] = items.length > 1 ? # Recusively look up the heading for the parts items.map{|x| headings[x.to_sym]}.join(' ') : # Capitalize if this part isn't defined items.first.capitalize end # Predefined headings (or parts of headings) headings.merge!({ :creation_time => "Created", :expires_in_seconds => "Expires In", :uuid => "ID", :id => 'ID', :current_scale => "Current", :scales_from => "Minimum", :scales_to => "Maximum", :gear_sizes => "Allowed Gear Sizes", :consumed_gears => "Gears Used", :max_gears => "Gears Allowed", :max_domains => "Domains Allowed", :compact_members => "Members", :gear_info => "Gears", :plan_id => "Plan", :url => "URL", :ssh_string => "SSH", :connection_info => "Connection URL", :gear_profile => "Gear Size", :visible_to_ssh? => 'Available', :downloaded_cartridge_url => 'From', :auto_deploy => 'Deployment', :sha1 => 'SHA1', :ref => 'Git Reference', :use_authorization_tokens => 'Use Auth Tokens', :ssl_ca_file => 'SSL Cert CA File', :ssl_version => 'SSL Version', :ssl_client_cert_file => 'SSL x509 Client Cert File', :ssl_client_key_file => 'SSL x509 Client Key File', :zones => 'Available Zones' }) headings[value] end
# File lib/rhc/helpers.rb, line 518 def to_boolean(s, or_nil=false) return nil if s.nil? && or_nil s.is_a?(String) ? !!(s =~ /^(true|t|yes|y|1)$/i) : s end
# File lib/rhc/helpers.rb, line 165 def to_host(s) s =~ %r(^http(?:s)?://) ? URI(s).host : s end
# File lib/rhc/helpers.rb, line 169 def to_uri(s) begin URI(s =~ %r(^http(?:s)?://) ? s : "https://#{s}") rescue URI::InvalidURIError raise RHC::InvalidURIException.new(s) end end
# File lib/rhc/helpers.rb, line 191 def token_for_user return options.token if options.token return nil unless options.use_authorization_tokens token_store_user_key = if options.ssl_client_cert_file certificate_fingerprint(options.ssl_client_cert_file) else options.rhlogin end return nil if token_store_user_key.nil? token_store.get(token_store_user_key, options.server) end
# File lib/rhc/helpers.rb, line 426 def unix? ; !jruby? && !windows? end
# File lib/rhc/helpers.rb, line 316 def warn(msg, *args) say color(msg, :yellow), *args end
# File lib/rhc/helpers.rb, line 425 def windows? ; RUBY_PLATFORM =~ /win(32|dows|ce)|djgpp|(ms|cyg|bcc)win|mingw32/i end
# File lib/rhc/helpers.rb, line 455 def with_tolerant_encoding(&block) # :nocov: if RUBY_VERSION.to_f >= 1.9 orig_default_internal = Encoding.default_internal Encoding.default_internal = 'ISO-8859-1' else orig_default_kcode = $KCODE $KCODE = 'N' end yield ensure if RUBY_VERSION.to_f >= 1.9 Encoding.default_internal = orig_default_internal else $KCODE = orig_default_kcode end # :nocov: end
Private Instance Methods
# File lib/rhc/ssh_helpers.rb, line 487 def ssh_add if exe?('ssh-add') #:nocov: `ssh-add 2>&1` #:nocov: end end