EGI-FCTF/rOCCI-cli

View on GitHub
bin/occi

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby

# -------------------------------------------------------------------------- #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
#--------------------------------------------------------------------------- #

require 'rubygems'
require 'pp'
require 'openssl'
require 'highline/import'

require 'occi-cli'

NONPASS_AUTHS = %w(none token oauth2).freeze

# get arguments and validate/parse them to an ostruct
options = Occi::Cli::OcciOpts.parse ARGV

# initialize logger
logger = Occi::Cli::Log.new(options.log[:out])
logger.level = options.log[:level]
options.log[:logger] = logger.api_log

# initialize output factory
output = Occi::Cli::ResourceOutputFactory.new options.output_format

Occi::Cli::Log.info "Starting OCCI client ..."
Occi::Cli::Log.debug "Options: #{options.inspect}"

# running with an empty password, we should ask the user for one
# if auth method is not "none"
if options.auth[:password].nil? || options.auth[:user_cert_password].nil?
  Occi::Cli::Log.debug "Password is not set, asking for it now ..."

  options.auth[:user_cert_password] = ask("Enter a password: ") {
      |q| q.echo = '*'
  } unless NONPASS_AUTHS.include?(options.auth[:type]) || (options.auth[:voms] && options.auth[:type] == "x509")

  options.auth[:password] = options.auth[:user_cert_password]
end

# establish a connection
begin
  Occi::Cli::Log.info "Establishing a connection to #{options.endpoint.inspect} ..."

  options.auto_connect = true
  connect :http, options
rescue OpenSSL::SSL::SSLError => ssl_ex
  # generic SSL error raised whilst establishing a connection
  # possibly an untrusted server cert or invalid user credentials
  Occi::Cli::Log.fatal "An SSL error occurred! Please, make sure your credentials " \
                  "are valid and recognized by the endpoint! Message: #{ssl_ex.message}"

  raise ssl_ex if options.debug
  exit!
rescue OpenSSL::PKey::RSAError => key_ex
  # generic X509 error raised whilst reading user's credentials from a file
  # possibly a wrong password or mangled/unsupported credential format
  Occi::Cli::Log.fatal "An X509 error occurred! Please, make sure you are using the " \
                  "right password and the file contains both your certificate " \
                  "and your private key! Message: #{key_ex.message}"

  raise key_ex if options.debug
  exit!
rescue Errno::ECONNREFUSED
  # the remote server has refused our connection attempt(s)
  # there is nothing we can do ...
  Occi::Cli::Log.fatal "Connection refused by #{options.endpoint.inspect}!"
  exit!
rescue Errno::ETIMEDOUT, Net::OpenTimeout, Net::ReadTimeout
  # connection attempt timed out
  Occi::Cli::Log.fatal "Connection to #{options.endpoint.inspect} timed out!"
  exit!
rescue => ex
  # something went wrong during the execution
  # hide the stack trace in non-debug modes
  Occi::Cli::Log.fatal "An error occurred! Message: #{ex.message}"

  raise ex if options.debug
  exit!
end

# dump the occi model provided by the server and exit
if options.dump_model

  if !model.respond_to? :instance_variables
    Occi::Cli::Log.fatal "Your Ruby doesn't support 'instance_variables' calls!"
    exit!
  end

  collection = model.get options.filter

  # iterate through available instance variables
  collection.instance_variables.each do |inst_var_sym|
    puts "#"*79
    puts "Dumping #{inst_var_sym.to_s.inspect}:"

    inst_var = collection.instance_variable_get(inst_var_sym)
    next unless inst_var.respond_to? :each

    # iterate through collection elements
    inst_var.each do |coll_elm|
      # respect user's output-format preferences
      if options.output_format == :json and coll_elm.respond_to? :as_json
        puts "\n"
        pp coll_elm.as_json
        puts "\n"
      elsif coll_elm.respond_to? :to_string
        puts "\n#{coll_elm.to_string}\n"
      else
        puts "\n#{coll_elm.inspect}\n"
      end
    end

    #
    puts "#"*79
  end

  exit! true
end

# start executing actions
begin

  Occi::Cli::Log.info "Executing action #{options.action.inspect} on #{options.resource.inspect} ..."

  # call the appropriate helper and then format its output
  case options.action
    when :list
      helper_list options, output
    when :describe
      helper_describe options, output
    when :create
      helper_create options, output
    when :link
      helper_link options, output
    when :delete, :unlink
      helper_delete options, output
    when :trigger
      helper_trigger options, output
    when :discover
      helper_discover options, output
    when :update
      helper_update options, output
    when :refresh
      refresh
    when :skip, :test, :dry_run
      Occi::Cli::Log.info "Just a connection test ..."
    else
      raise "Unknown action #{options.action.inspect}!"
  end

rescue Errno::ECONNREFUSED
  # remote server refused our connection attempt(s)
  # even though initial connect was successful
  Occi::Cli::Log.fatal "Connection refused by #{options.endpoint.inspect}!"
  exit!
rescue Errno::ETIMEDOUT, Net::OpenTimeout, Net::ReadTimeout
  # connection attempt timed out
  Occi::Cli::Log.fatal "Connection to #{options.endpoint.inspect} timed out!"
  exit!
rescue => ex
  # something went wrong during the execution
  # hide the stack trace in non-debug modes
  Occi::Cli::Log.fatal "An error occurred! Message: #{ex.message}"

  raise ex if options.debug
  exit!
end

Occi::Cli::Log.info "OCCI client is shutting down ..."