def self.parse(args, test_env = false)
@@quiet = test_env
options = Hashie::Mash.new
set_defaults(options)
opts = OptionParser.new do |opts|
opts.banner = %Q{Usage: occi [OPTIONS]}
opts.separator ""
opts.separator "Options:"
opts.on("-e",
"--endpoint URI",
String,
"OCCI server URI, defaults to #{options.endpoint.inspect}") do |endpoint|
options.endpoint = URI(endpoint).to_s
end
opts.on("-n",
"--auth METHOD",
AUTH_METHODS,
"Authentication method, only: [#{AUTH_METHODS.join('|')}], defaults " "to #{options.auth.type.inspect}") do |auth|
options.auth.type = auth.to_s
end
opts.on("-k",
"--timeout SEC",
Integer,
"Default timeout for all HTTP connections, in seconds") do |timeout|
raise "Timeout has to be a number larger than 0!" if timeout < 1
options.timeout = timeout
end
opts.on("-u",
"--username USER",
String,
"Username for basic or digest authentication, defaults to " "#{options.auth.username.inspect}") do |username|
options.auth.username = username
end
opts.on("-p",
"--password PASSWORD",
String,
"Password for basic, digest and x509 authentication") do |password|
options.auth.password = password
options.auth.user_cert_password = password
end
opts.on("-c",
"--ca-path PATH",
String,
"Path to CA certificates directory, defaults to #{options.auth.ca_path.inspect}") do |ca_path|
raise ArgumentError, "Path specified in --ca-path is not a directory!" unless File.directory? ca_path
raise ArgumentError, "Path specified in --ca-path is not readable!" unless File.readable? ca_path
options.auth.ca_path = ca_path
end
opts.on("-f",
"--ca-file PATH",
String,
"Path to CA certificates in a file") do |ca_file|
raise ArgumentError, "File specified in --ca-file is not a file!" unless File.file? ca_file
raise ArgumentError, "File specified in --ca-file is not readable!" unless File.readable? ca_file
options.auth.ca_file = ca_file
end
opts.on("-s",
"--skip-ca-check",
"Skip server certificate verification [NOT recommended]") do
silence_warnings { OpenSSL::SSL.const_set(:VERIFY_PEER, OpenSSL::SSL::VERIFY_NONE) }
end
opts.on("-F",
"--filter CATEGORY",
String,
"Category type identifier to filter categories from model, must " "be used together with the -m option") do |filter|
options.filter = filter
end
opts.on("-x",
"--user-cred FILE",
String,
"Path to user's x509 credentials, defaults to #{options.auth.user_cert.inspect}") do |user_cred|
raise ArgumentError, "File specified in --user-cred is not a file!" unless File.file? user_cred
raise ArgumentError, "File specified in --user-cred is not readable!" unless File.readable? user_cred
options.auth.user_cert = user_cred
end
opts.on("-X",
"--voms",
"Using VOMS credentials; modifies behavior of the X509 authN module") do |voms|
options.auth.voms = true
end
opts.on("-q",
"--token TOKEN",
String,
"A pre-generated token to be used for authentication purposes") do |token|
raise ArgumentError, "Token cannot be blank!" if token.blank?
options.auth.token = token
end
opts.on("-y",
"--media-type MEDIA_TYPE",
MEDIA_TYPES,
"Media type for client <-> server communication, only: [#{MEDIA_TYPES.join('|')}], " "defaults to #{options.media_type.inspect}") do |media_type|
options.media_type = media_type
end
opts.on("-r",
"--resource RESOURCE",
String,
"Term, identifier or URI of a resource to be queried, required") do |resource|
options.resource = resource
end
opts.on("-t",
"--attribute ATTR",
Array,
"An \"attribute='value'\" pair, mandatory attrs for creating new resource instances: " "[#{REQ_CREATE_ATTRS.join(', ')}]") do |attributes|
options.attributes ||= Occi::Core::Attributes.new
attributes.each do |attribute|
key, value = Occi::Cli::OcciOpts::Helper.parse_attribute(attribute)
options.attributes[key] = value
end
end
opts.on("-T",
"--context CTX_VAR",
Array,
"A \"context_variable='value'\" pair for new 'compute' resource instances, " "only: [#{Occi::Cli::OcciOpts::Helper::ALLOWED_CONTEXT_VARS.join(', ')}]") do |context|
options.context_vars ||= {}
context.each do |ctx|
key, value = Occi::Cli::OcciOpts::Helper.parse_context_variable(ctx)
options.context_vars[key] = value
end
end
opts.on("-a",
"--action ACTION",
ACTIONS,
"Action to be performed on a resource instance, required") do |action|
options.action = action
end
opts.on("-M",
"--mixin IDENTIFIER",
Array,
"Identifier of a mixin, formatted as SCHEME#TERM or SHORT_SCHEME#TERM") do |mixins|
options.mixins ||= Occi::Core::Mixins.new
mixins.each do |mixin|
options.mixins << Occi::Cli::OcciOpts::Helper.parse_mixin(mixin)
end
end
opts.on("-j",
"--link URI",
Array,
"URI of an instance to be linked with the given resource, applicable only for action 'link'") do |links|
options.links ||= []
links.each do |link|
link_relative_path = URI(link).path
raise ArgumentError, "Specified link URI is not valid!" unless link_relative_path.start_with? '/'
options.links << link_relative_path
end
end
opts.on("-g",
"--trigger-action ACTION",
String,
"Action to be triggered on the resource, formatted as SCHEME#TERM or TERM") do |trigger_action|
options.trigger_action = Occi::Cli::OcciOpts::Helper.parse_action(trigger_action)
end
opts.on("-i",
"--entity-type TYPE",
ENTITY_TYPES,
"Entity types to perform discovery on, only: [#{ENTITY_TYPES.join('|')}]") do |entity_type|
options.entity_type = entity_type
end
opts.on("-l",
"--log-to OUTPUT",
LOG_OUTPUTS,
"Log to the specified device, only: [#{LOG_OUTPUTS.join('|')}], defaults to 'stderr'") do |log_to|
options.log.out = STDOUT if log_to.to_s == "stdout"
end
opts.on("-o",
"--output-format FORMAT",
Occi::Cli::ResourceOutputFactory.allowed_formats,
"Output format, only: [#{Occi::Cli::ResourceOutputFactory.allowed_formats.join('|')}], " "defaults to #{options.output_format.to_s.inspect}") do |output_format|
options.output_format = output_format
end
opts.on("-b",
"--log-level LEVEL",
LOG_LEVELS,
"Set the specified logging level, only: [#{LOG_LEVELS.join('|')}]") do |log_level|
unless options.log.level == Occi::Cli::Log::DEBUG
options.log.level = Occi::Cli::Log.const_get(log_level.to_s.upcase)
end
end
opts.on("-w",
"--wait-for-active TIMEOUT",
Integer,
"Wait for TIMEOUT seconds for the created resource to become 'active' before returning, " "defaults to 0 seconds (will be interpreted as 'disabled')") do |wait_for_active|
options.wait_for_active = wait_for_active
end
opts.on_tail("-z",
"--examples",
"Show usage examples") do |examples|
if examples
if @@quiet
exit true
else
file = "#{File.expand_path('..', __FILE__)}/occi_opts/cli_examples.erb"
template = ERB.new(File.new(file).read, nil, '-')
puts template.result(binding)
exit! true
end
end
end
opts.on_tail("-m",
"--dump-model",
"Contact the endpoint and dump its model") do |dump_model|
options.dump_model = dump_model
end
opts.on_tail("-d",
"--debug",
"Enable debugging messages") do |debug|
options.debug = debug
options.log.level = Occi::Cli::Log::DEBUG
end
opts.on_tail("-h",
"--help",
"Show this message") do
if @@quiet
exit true
else
puts opts
exit! true
end
end
opts.on_tail("-v",
"--version",
"Show version") do
if @@quiet
exit true
else
if options.debug
puts "CLI: #{Occi::Cli::VERSION}"
puts "API: #{Occi::Api::VERSION}"
puts "Core: #{Occi::VERSION}"
else
puts Occi::Cli::VERSION
end
exit! true
end
end
end
begin
opts.parse!(args)
rescue Exception => ex
if @@quiet
exit false
else
puts ex.message.capitalize
puts opts
exit!
end
end
check_restrictions options, opts
options
end