class Aviator::Session
Manages a provider (e.g. OpenStack) session and serves as the entry point for a consumer class/object. See ::new for notes on usage.
Public Class Methods
Creates a new Session object from a previous session's dump. See #dump for more information.
If you want the newly deserialized session to log its output, add a
:log_file
option.
Aviator::Session.load(session_dump_str, :log_file => 'path/to/aviator.log')
# File lib/aviator/core/session.rb, line 304 def self.load(session_dump, opts={}) opts[:session_dump] = session_dump new(opts) end
Create a new Session instance.
Initialize with a config file
Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production)
In the above example, the config file must have the following form:
production: provider: openstack auth_service: name: identity host_uri: 'http://my.openstackenv.org:5000' request: create_token validator: list_tenants api_version: v2 auth_credentials: username: myusername password: mypassword tenant_name: myproject
SIDENOTE: For more information about the
validator
member, see #validate.
Once the session has been instantiated, you may authenticate against the provider as follows:
session.authenticate
The members you put under auth_credentials
will depend on the
request class you declare under auth_service:request
and what
parameters it accepts. To know more about a request class and its
parameters, you can use the CLI tool aviator describe
or view
the request definition file directly.
If writing the auth_credentials
in the config file is not
acceptable, you may omit it and just supply the credentials at runtime. For
example:
session.authenticate do |params| params.username = ARGV[0] params.password = ARGV[1] params.tenant_name = ARGV[2] end
See #authenticate for more info.
Note that while the example config file above only has one environment
(production), you can declare an arbitrary number of environments in your
config file. Shifting between environments is as simple as changing the
:environment
to refer to that.
Initialize with an in-memory hash
You can create an in-memory hash with a structure similar to the config file but without the environment name. For example:
configuration = { :provider => 'openstack', :auth_service => { :name => 'identity', :host_uri => 'http://devstack:5000/v2.0', :request => 'create_token', :validator => 'list_tenants' } }
Supply this to the initializer using the :config
option. For
example:
Aviator::Session.new(:config => configuration)
Initialize with a session dump
You can create a new Session instance using a dump from another instance. For example:
session_dump = session1.dump session2 = Aviator::Session.new(:session_dump => session_dump)
However, #load is cleaner and recommended over this method.
Optionally supply a log file
In all forms above, you may optionally add a :log_file
option
to make Aviator write all HTTP calls to the
given path. For example:
Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production, :log_file => 'path/to/log')
# File lib/aviator/core/session.rb, line 142 def initialize(opts={}) if opts.has_key? :session_dump initialize_with_dump(opts[:session_dump]) elsif opts.has_key? :config_file initialize_with_config(opts[:config_file], opts[:environment]) elsif opts.has_key? :config initialize_with_hash(opts[:config]) else raise InitializationError.new end @log_file = opts[:log_file] end
Public Instance Methods
Authenticates against the backend provider using the auth_service request class declared in the session's configuration. Please see ::new for more information on declaring the request class to use for authentication.
Request params block
If the auth_service request class accepts parameters, you may supply that as a block and it will be directly passed to the request. For example:
session = Aviator::Session.new(:config => config) session.authenticate do |params| params.username = username params.password = password params.tenant_name = project end
If your configuration happens to have an auth_credentials
in
it, those will be overridden by this block.
Treat parameters as a hash
You can also treat the params struct like a hash with the attribute names as the keys. For example, we can rewrite the above as:
session = Aviator::Session.new(:config => config) session.authenticate do |params| params[:username] = username params[:password] = password params[:tenant_name] = project end
Keys can be symbols or strings.
Use a hash argument instead of a block
You may also provide request params as an argument instead of a block. This is especially useful if you want to mock Aviator as it's easier to specify ordinary argument expectations over blocks. Further rewriting the example above, we end up with:
session = Aviator::Session.new(:config => config) session.authenticate :params => { :username => username, :password => password, :tenant_name => project }
If both :params
and a block are provided, the
:params
values will be used and the block ignored.
Success requirements
Expects an HTTP status 200 or 201 response from the backend. Any other status is treated as a failure.
# File lib/aviator/core/session.rb, line 212 def authenticate(opts={}, &block) block ||= lambda do |params| config[:auth_credentials].each do |key, value| begin params[key] = value rescue NameError => e raise NameError.new("Unknown param name '#{key}'") end end end response = auth_service.request(config[:auth_service][:request].to_sym, opts, &block) if [200, 201].include? response.status @auth_response = Hashish.new({ :headers => response.headers, :body => response.body }) update_services_session_data else raise AuthenticationError.new(response.body) end self end
Returns true if the session has been authenticated. Note that this relies on cached response from a previous run of #authenticate if one was made. If you want to check against the backend provider if the session is still valid, use #validate instead.
# File lib/aviator/core/session.rb, line 243 def authenticated? !auth_response.nil? end
Returns its configuration.
# File lib/aviator/core/session.rb, line 250 def config @config end
Returns a JSON string of its configuration and auth_data. This string can be streamed or stored and later re-loaded in another Session instance. For example:
session = Aviator::Session.new(:config => configuration) str = session.dump # time passes... session = Aviator::Session.load(str)
# File lib/aviator/core/session.rb, line 265 def dump JSON.generate({ :config => config, :auth_response => auth_response }) end
Returns the log file path. May be nil if none was provided during initialization.
# File lib/aviator/core/session.rb, line 314 def log_file @log_file end
Calls the given request of the given service. An example call might look like:
session.request :compute_service, :create_server do |p| p.name = "My Server" p.image_ref = "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29" p.flavor_ref = "fa283da1-59a5-4245-8569-b6eadf69f10b" end
Note that you can also treat the block's argument like a hash with the attribute names as the keys. For example, we can rewrite the above as:
session.request :compute_service, :create_server do |p| p[:name] = "My Server" p[:image_ref] = "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29" p[:flavor_ref] = "fa283da1-59a5-4245-8569-b6eadf69f10b" end
Keys can be symbols or strings.
You may also provide parameters as an argument instead of a block. This is especially useful when mocking Aviator as it's easier to specify ordinary argument expectations over blocks. Further rewriting the example above, we end up with:
session.request :compute_service, :create_server, :params => { :name => "My Server", :image_ref => "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29", :flavor_ref => "fa283da1-59a5-4245-8569-b6eadf69f10b" }
If both :params
and a block are provided, the values in
:params
will be used and the block ignored.
Return Value
The return value will be an instance of Hashish, a lightweight replacement for activesupport's HashWithIndifferentAccess, with the following structure:
{ :status => 200, :headers => { 'X-Auth-Token' => 'd9186f45ce5446eaa0adc9def1c46f5f', 'Content-Type' => 'application/json' }, :body => { :some_key => :some_value } }
Note that the members in :headers
and :body
will
vary depending on the provider and the request that was made.
Request Options
You can further customize how the method behaves by providing one or more
options to the call. For example, assuming you are using the
openstack
provider, the following will call the
:create_server
request of the v1 API of
:compute_service
.
session.request :compute_service, :create_server, :api_version => v1, :params => params
The available options vary depending on the provider. See the documentation on the provider's Provider class for more information (e.g. Aviator::Openstack::Provider)
# File lib/aviator/core/session.rb, line 386 def request(service_name, request_name, opts={}, &block) service = send("#{service_name.to_s}_service") response = service.request(request_name, opts, &block) response.to_hash end
Returns true if the session is still valid in the underlying provider. This
method calls the validator
request class declared under
auth_service
in the configuration. The validator can be any
request class as long as:
-
The request class exists!
-
Is not an anonymous request. Otherwise it will always return true.
-
Does not require any parameters
-
It returns an HTTP status 200 or 203 to indicate auth info validity.
-
It returns any other HTTP status to indicate that the auth info is invalid.
See ::new for an example on how to specify the request class to use for session validation.
Note that this method requires the session to be previously authenticated otherwise a NotAuthenticatedError will be raised. If you just want to check if the session was previously authenticated, use #authenticated? instead.
# File lib/aviator/core/session.rb, line 410 def validate raise NotAuthenticatedError.new unless authenticated? raise ValidatorNotDefinedError.new unless config[:auth_service][:validator] auth_with_bootstrap = auth_response.merge({ :auth_service => config[:auth_service] }) response = auth_service.request config[:auth_service][:validator].to_sym, :session_data => auth_with_bootstrap response.status == 200 || response.status == 203 end