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

agree(*args, &block) click to toggle source

By default, agree should take a single character in interactive

Calls superclass method
# File lib/rhc/helpers.rb, line 292
def agree(*args, &block)
  #args.push(interactive?.presence) if args.length == 1
  block = lambda do |q|
    q.validate = /\A(?:y|yes|n|no)\Z/
  end unless block_given?
  super *args, &block
end
certificate_file(file) click to toggle source
# File lib/rhc/helpers.rb, line 231
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
certificate_fingerprint(file) click to toggle source
# File lib/rhc/helpers.rb, line 238
def certificate_fingerprint(file)
  Digest::SHA1.hexdigest(certificate_file(file).to_der)
end
certificate_key(file) click to toggle source
# File lib/rhc/helpers.rb, line 242
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
client_from_options(opts) click to toggle source
# File lib/rhc/helpers.rb, line 213
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,
    }.merge!(ssl_options).merge!(opts))
end
collect_env_vars(items) click to toggle source
# File lib/rhc/helpers.rb, line 495
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
color(item, *args) click to toggle source

OVERRIDE: Replaces default commander behavior

# File lib/rhc/helpers.rb, line 323
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
confirm_action(question) click to toggle source
# File lib/rhc/helpers.rb, line 300
def confirm_action(question)
  return if options.confirm
  return if !options.noprompt && paragraph{ agree "#{question} (yes|no): " }
  raise RHC::ConfirmationError
end
debug(*args) click to toggle source
# File lib/rhc/helpers.rb, line 261
def debug(*args)
  $terminal.debug(*args)
end
debug?() click to toggle source
# File lib/rhc/helpers.rb, line 267
def debug?
  $terminal.debug?
end
debug_error(*args) click to toggle source
# File lib/rhc/helpers.rb, line 264
def debug_error(*args)
  $terminal.debug_error(*args)
end
deprecated(msg,short = false) click to toggle source
# File lib/rhc/helpers.rb, line 284
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
deprecated_command(correct, short=false) click to toggle source
# File lib/rhc/helpers.rb, line 280
def deprecated_command(correct, short=false)
  deprecated("This command is deprecated. Please use '#{correct}' instead.", short)
end
disable_deprecated?() click to toggle source
# File lib/rhc/helpers.rb, line 276
def disable_deprecated?
  ENV['DISABLE_DEPRECATED'] == '1'
end
discover_windows_executables() { |base| ... } click to toggle source
# File lib/rhc/helpers.rb, line 526
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
env_var_regex_pattern() click to toggle source
# File lib/rhc/helpers.rb, line 491
def env_var_regex_pattern
  /^([a-zA-Z_][\w]*)=(.*)$/
end
error(msg, *args) click to toggle source
# File lib/rhc/helpers.rb, line 318
def error(msg, *args)
  say color(msg, :red), *args
end
exe?(executable) click to toggle source
# File lib/rhc/helpers.rb, line 577
def exe?(executable)
  ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
    File.executable?(File.join(directory, executable.to_s))
  end
end
exec(cmd) click to toggle source
# File lib/rhc/helpers.rb, line 271
def exec(cmd)
  output = Kernel.send(:`, cmd)
  [$?.exitstatus, output]
end
host_exists?(host) click to toggle source

Check if host exists

# File lib/rhc/helpers.rb, line 430
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
hosts_file_contains?(host) click to toggle source
# File lib/rhc/helpers.rb, line 440
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
info(msg, *args) click to toggle source
# File lib/rhc/helpers.rb, line 310
def info(msg, *args)
  say color(msg, :cyan), *args
end
interactive?() click to toggle source

Output helpers

# File lib/rhc/helpers.rb, line 257
def interactive?
  $stdin.tty? and $stdout.tty? and not options.noprompt
end
jruby?() click to toggle source

Platform helpers

# File lib/rhc/helpers.rb, line 422
def jruby? ; RUBY_PLATFORM =~ /java/ end
mac?() click to toggle source
# File lib/rhc/helpers.rb, line 425
def mac? ; RbConfig::CONFIG['host_os'] =~ /^darwin/ end
parse_headers(headers) click to toggle source
# File lib/rhc/helpers.rb, line 204
def parse_headers(headers)
  Hash[
    Array(headers).map do |header|
      key, value = header.split(/: */, 2)
      [key, value || ""] if key.presence
    end.compact
  ]
end
parse_ssl_version(version) click to toggle source
# File lib/rhc/helpers.rb, line 249
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
pluralize(count, s) click to toggle source
# File lib/rhc/helpers.rb, line 341
def pluralize(count, s)
  count == 1 ? "#{count} #{s}" : "#{count} #{s}s"
end
results() { || ... } click to toggle source

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 414
def results(&block)
  section(:top => 1, :bottom => 0) do
    say "RESULT:"
    yield
  end
end
role_name(s) click to toggle source
# File lib/rhc/helpers.rb, line 160
def role_name(s)
  ROLES[s.downcase]
end
run_with_tee(cmd) click to toggle source

Run a command and export its output to the user. Output is not capturable on all platforms.

# File lib/rhc/helpers.rb, line 474
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_path(s, keep_quotes=false) click to toggle source

split spaces but preserve sentences between quotes

# File lib/rhc/helpers.rb, line 522
def split_path(s, keep_quotes=false)
  keep_quotes ? s.split(/\s(?=(?:[^"]|"[^"]*")*$)/) : CSV::parse_line(s, :col_sep => ' ')
end
ssh_string(ssh_url) click to toggle source
# File lib/rhc/helpers.rb, line 176
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
ssh_string_parts(ssh_url) click to toggle source
# File lib/rhc/helpers.rb, line 185
def ssh_string_parts(ssh_url)
  uri = URI.parse(ssh_url)
  [uri.host, uri.user]
end
ssl_options() click to toggle source
# File lib/rhc/helpers.rb, line 223
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
success(msg, *args) click to toggle source
# File lib/rhc/helpers.rb, line 306
def success(msg, *args)
  say color(msg, :green), *args
end
suggest_server_nickname(hostname) click to toggle source
# 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(/\./, '\.')}$/
    $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
table_heading(value) click to toggle source

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 348
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
to_boolean(s, or_nil=false) click to toggle source
# File lib/rhc/helpers.rb, line 516
def to_boolean(s, or_nil=false)
  return nil if s.nil? && or_nil
  s.is_a?(String) ? !!(s =~ /^(true|t|yes|y|1)$/) : s
end
to_host(s) click to toggle source
# File lib/rhc/helpers.rb, line 164
def to_host(s)
  s =~ %r(^http(?:s)?://) ? URI(s).host : s
end
to_uri(s) click to toggle source
# File lib/rhc/helpers.rb, line 168
def to_uri(s)
  begin
    URI(s =~ %r(^http(?:s)?://) ? s : "https://#{s}")
  rescue URI::InvalidURIError
    raise RHC::InvalidURIException.new(s)
  end
end
token_for_user() click to toggle source
# File lib/rhc/helpers.rb, line 190
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
unix?() click to toggle source
# File lib/rhc/helpers.rb, line 424
def unix? ; !jruby? && !windows? end
warn(msg, *args) click to toggle source
# File lib/rhc/helpers.rb, line 314
def warn(msg, *args)
  say color(msg, :yellow), *args
end
windows?() click to toggle source
# File lib/rhc/helpers.rb, line 423
def windows? ; RUBY_PLATFORM =~ /win(32|dows|ce)|djgpp|(ms|cyg|bcc)win|mingw32/ end
with_tolerant_encoding() { || ... } click to toggle source
# File lib/rhc/helpers.rb, line 453
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