Skip to content

Commit

Permalink
Config file may now include logging options. Also adds support to set…
Browse files Browse the repository at this point in the history
… config file by env variable.

Fixes aeolus-incubator#17
  • Loading branch information
cwolferh committed Dec 19, 2012
1 parent 7a78cdd commit c7ed3c6
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 61 deletions.
48 changes: 21 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,27 @@ Revamp of cli tooling for aeolus conductor. Thor scaffolding is in
place, along with ActiveResource-backed interaction with Conductor's
REST api to list or add providers.

Authentication options for the Conductor api can specified in
~/.aeolus-cli as per the old aeolus client. Or, /etc/aeolus-cli is
checked if ~/.aeolus-cli does not exist. Finally, these options may
instead be supplied on the command line with --conductor-url,
--username, and --password.
## Configuration

Connection/auth options for the Conductor API may be specified in a
configuration file in one of three places: the file defined by the
environment variable AEOLUS_CLI_CONF, otherwise ~/.aeolus-cli (if it
exists), otherwise /etc/aeolus-cli (if it exists). Additionaly,
connection/auth options may be set or overridden from the command line
with --conductor-url, --username and --password.

Logging levels also are set in the configuration file.

# Sample configuration file
:conductor:
:url: http://example.com:3013/api
:username: master
:password: ofuniverse
:logging:
# one of DEBUG, WARN, INFO, ERROR or FATAL
:level: WARN
# one of STDOUT, STDERR or /path/to/logfile
:logfile: STDERR

## Exploring the command and sub command usage

Expand Down Expand Up @@ -72,8 +88,6 @@ instead be supplied on the command line with --conductor-url,
## List providers

$ aeolus provider list
I, [2012-10-31T14:18:49.411815 #10688] INFO -- : GET http://localhost:3002/api/providers.xml
I, [2012-10-31T14:18:49.411966 #10688] INFO -- : --> 200 OK 5591 (530.6ms)
Name Provider Type Deltacloud Provider Deltacloud url
ec2-us-east-1 ec2 us-east-1 http://qeblade30.rhq.lab.eng.bos.redhat.com:3002/api
mock mock http://qeblade30.rhq.lab.eng.bos.redhat.com:3002/api
Expand All @@ -83,29 +97,17 @@ instead be supplied on the command line with --conductor-url,
## Add a provider

$ aeolus provider add mock-test21 --deltacloud-url http://qeblade30.rhq.lab.eng.bos.redhat.com:3002/api --provider-type mock
I, [2012-10-31T14:20:18.522110 #10826] INFO -- : GET http://localhost:3002/api/provider_types.xml
I, [2012-10-31T14:20:18.522251 #10826] INFO -- : --> 200 OK 1060 (432.9ms)
I, [2012-10-31T14:20:19.314974 #10826] INFO -- : POST http://localhost:3002/api/providers.xml
I, [2012-10-31T14:20:19.315100 #10826] INFO -- : --> 201 Created 254 (707.5ms)
Provider mock-test21 added with id 23

## Display remote error mesage when trying to add an existing provider

$ aeolus provider add mock-test21 --deltacloud-url http://qeblade30.rhq.lab.eng.bos.redhat.com:3002/api --provider-type mock
I, [2012-10-31T14:20:24.297438 #10873] INFO -- : GET http://localhost:3002/api/provider_types.xml
I, [2012-10-31T14:20:24.297604 #10873] INFO -- : --> 200 OK 1060 (594.1ms)
I, [2012-10-31T14:20:24.919177 #10873] INFO -- : POST http://localhost:3002/api/providers.xml
I, [2012-10-31T14:20:24.919330 #10873] INFO -- : --> 422 100 (535.8ms)
ERROR: Conductor was unable to save the provider
["Provider name has already been taken"]

## List provider accounts

$ aeolus provider_account list
I, [2012-12-11T10:26:20.775263 #1864] INFO -- : GET https://localhost:443/conductor/api/provider_accounts.xml
I, [2012-12-11T10:26:20.775443 #1864] INFO -- : --> 200 OK 285 (104.1ms)
I, [2012-12-11T10:26:20.932803 #1864] INFO -- : GET https://localhost:443/conductor/api/provider_accounts/2.xml
I, [2012-12-11T10:26:20.932911 #1864] INFO -- : --> 200 OK 418 (106.7ms)
Name Provider Username Quota
mock mock mockuser unlimited

Expand All @@ -117,18 +119,10 @@ instead be supplied on the command line with --conductor-url,
<password>mockpassword</password>
</credentials>
$ aeolus provider_account add mock --provider-name mock --credentials-file /tmp/credentials.xml
I, [2012-12-11T09:42:24.823114 #31824] INFO -- : GET https://localhost:443/conductor/api/providers.xml
I, [2012-12-11T09:42:24.823226 #31824] INFO -- : --> 200 OK 245 (110.0ms)
I, [2012-12-11T09:42:26.032696 #31824] INFO -- : POST https://localhost:443/conductor/api/provider_accounts.xml
I, [2012-12-11T09:42:26.032939 #31824] INFO -- : --> 201 Created 418 (1197.6ms)
Provider account mock added with id 2

## Display remote error message when trying to add an existing provider account

$ aeolus provider_account add mock --provider-name mock --credentials-file /tmp/credentials.xml
I, [2012-12-11T10:31:56.555708 #2238] INFO -- : GET https://localhost:443/conductor/api/providers.xml
I, [2012-12-11T10:31:56.555953 #2238] INFO -- : --> 200 OK 245 (113.2ms)
I, [2012-12-11T10:31:56.930892 #2238] INFO -- : POST https://localhost:443/conductor/api/provider_accounts.xml
I, [2012-12-11T10:31:56.931059 #2238] INFO -- : --> 422 Unprocessable Entity 152 (357.4ms)
ERROR: Conductor was unable to save the provider account
["Label has already been taken", "Username has already been taken"]
87 changes: 59 additions & 28 deletions lib/aeolus_cli/common_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class AeolusCli::CommonCli < Thor

def initialize(*args)
super
configure_conductor_connection(options)
load_aeolus_config(options)
end

# abstract-y methods
Expand Down Expand Up @@ -41,17 +41,66 @@ def banner(task, namespace = nil, subcommand = false)
end
end

def configure_conductor_connection(options)
@config = nil
# check default config file locations
["~/.aeolus-cli","/etc/aeolus-cli"].each do |fname|
if is_file?(fname)
@config = YAML::load(File.open(File.expand_path(fname)))
break
def load_aeolus_config(options)
# set logging defaults
ActiveResource::Base.logger = Logger.new(STDOUT)
ActiveResource::Base.logger.level = Logger::WARN

# locate the config file if one exists
config_fname = nil
if ENV.has_key?("AEOLUS_CLI_CONF")
config_fname = ENV["AEOLUS_CLI_CONF"]
if !is_file?(config_fname)
raise AeolusCli::ConfigError.new(
"environment variable AEOLUS_CLI_CONF with value "+
"'#{ ENV['AEOLUS_CLI_CONF']}' does not point to an existing file")
end
else
["~/.aeolus-cli","/etc/aeolus-cli"].each do |fname|
if is_file?(fname)
config_fname = fname
break
end
end
end
if @config != nil
configure_active_resource

# load the config file if we have one
if config_fname != nil
@config = YAML::load(File.open(File.expand_path(config_fname)))
if @config.has_key?(:conductor)
[:url, :password, :username].each do |key|
raise AeolusCli::ConfigError.new \
("Error in configuration file: #{key} is missing"
) unless @config[:conductor].has_key?(key)
end
AeolusCli::Model::Base.site = @config[:conductor][:url]
AeolusCli::Model::Base.user = @config[:conductor][:username]
AeolusCli::Model::Base.password = @config[:conductor][:password]
else
raise AeolusCli::ConfigError.new("Error in configuration file")
end
if @config.has_key?(:logging)
if @config[:logging].has_key?(:logfile)
if @config[:logging][:logfile].upcase == "STDOUT"
ActiveResource::Base.logger = Logger.new(STDOUT)
elsif @config[:logging][:logfile].upcase == "STDERR"
ActiveResource::Base.logger = Logger.new(STDERR)
else
ActiveResource::Base.logger =
Logger.new(@config[:logging][:logfile])
end
end
if @config[:logging].has_key?(:level)
log_level = @config[:logging][:level]
if ! ['DEBUG','WARN','INFO','ERROR','FATAL'].include?(log_level)
raise AeolusCli::ConfigError.new \
("log level specified in configuration #{log_level}, is not valid."+
". shoud be one of DEBUG, WARN, INFO, ERROR or FATAL")
else
ActiveResource::Base.logger.level = eval("Logger::#{log_level}")
end
end
end
end
# allow overrides from command line
if options[:conductor_url]
Expand Down Expand Up @@ -105,24 +154,6 @@ def provider_type_hash
deltacloud_driver_to_provider_type
end

# The two methods below which are related to loading
# site/username/password from a config file such as ~/.aeolus-cli
# are borrowed from original aeolus-cli project
def configure_active_resource
if @config.has_key?(:conductor)
[:url, :password, :username].each do |key|
raise AeolusCli::ConfigError.new(
"Error in configuration file: #{key} is missing") \
unless @config[:conductor].has_key?(key)
end
AeolusCli::Model::Base.site = @config[:conductor][:url]
AeolusCli::Model::Base.user = @config[:conductor][:username]
AeolusCli::Model::Base.password = @config[:conductor][:password]
else
raise AeolusCli::ConfigError.new("Error in configuration file")
end
end

# TODO: Consider ripping all this file-related stuff into a module or
# class for better encapsulation and testability
def is_file?(path)
Expand Down
50 changes: 50 additions & 0 deletions spec/config_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'aeolus_cli/main'

describe "loading configuration-file by environment variable" do

before do
config_file = File.expand_path("spec/sample/aeolus-cli-config")
ENV['AEOLUS_CLI_CONF'] = config_file
end

describe 'with no command line overrides' do
before do
AeolusCli::Provider.start
end
it 'the configuration file should be loaded' do
AeolusCli::Model::Base.site.to_s.should == 'http://example.com:3013/api'
AeolusCli::Model::Base.user.to_s.should == 'master'
AeolusCli::Model::Base.password.to_s.should == 'ofuniverse'
ActiveResource::Base.logger.level.should == Logger::DEBUG
end
end

describe 'with --username override' do
before do
AeolusCli::Provider.start(["--username", "override-user"])
end
it 'the configuration file should be loaded' do
AeolusCli::Model::Base.user.to_s.should == 'override-user'
end
end

describe 'with --password override' do
before do
AeolusCli::Provider.start(["--password", "override-password"])
end
it 'the configuration file should be loaded' do
AeolusCli::Model::Base.password.to_s.should == 'override-password'
end
end

describe 'with --conductor-url override' do
before do
AeolusCli::Provider.start(["--conductor-url",
"https://localhost/conductor/api"])
end
it 'the configuration file should be loaded' do
AeolusCli::Model::Base.site.to_s.should ==
'https://localhost/conductor/api'
end
end
end
6 changes: 0 additions & 6 deletions spec/provider_spec.rb

This file was deleted.

8 changes: 8 additions & 0 deletions spec/sample/aeolus-cli-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Sample aeolus-cli config file
:conductor:
:url: http://example.com:3013/api
:username: master
:password: ofuniverse
:logging:
:level: DEBUG
:log-file: STDERR

0 comments on commit c7ed3c6

Please sign in to comment.