Class: Aviator::Session
- Defined in:
- lib/puppet/feature/aviator/core/session.rb
Overview
Manages a provider (e.g. OpenStack) session and serves as the entry point for a consumer class/object. See Session::new for notes on usage.
Defined Under Namespace
Classes: AuthenticationError, EnvironmentNotDefinedError, InitializationError, InvalidConfigFilePathError, NotAuthenticatedError, ValidatorNotDefinedError
Class Method Summary collapse
-
.load(session_dump, opts = {}) ⇒ Object
Creates a new Session object from a previous session’s dump.
Instance Method Summary collapse
-
#authenticate(opts = {}, &block) ⇒ Object
Authenticates against the backend provider using the auth_service request class declared in the session’s configuration.
-
#authenticated? ⇒ Boolean
Returns true if the session has been authenticated.
-
#config ⇒ Object
Returns its configuration.
-
#dump ⇒ Object
Returns a JSON string of its configuration and auth_data.
-
#initialize(opts = {}) ⇒ Session
constructor
Create a new Session instance.
-
#load(session_dump) ⇒ Object
Same as Session::load but re-uses the Session instance this method is called on instead of creating a new one.
-
#log_file ⇒ Object
Returns the log file path.
-
#method_missing(name, *args, &block) ⇒ Object
:nodoc:.
-
#request(service_name, request_name, opts = {}, &block) ⇒ Object
Calls the given request of the given service.
-
#validate ⇒ Object
Returns true if the session is still valid in the underlying provider.
Constructor Details
#initialize(opts = {}) ⇒ Session
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 Session#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 Session#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, Session.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')
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/puppet/feature/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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
:nodoc:
284 285 286 287 288 289 290 291 292 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 284 def method_missing(name, *args, &block) # :nodoc: service_name_parts = name.to_s.match(/^(\w+)_service$/) if service_name_parts get_service_obj(service_name_parts[1]) else super name, *args, &block end end |
Class Method Details
.load(session_dump, opts = {}) ⇒ Object
304 305 306 307 308 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 304 def self.load(session_dump, opts={}) opts[:session_dump] = session_dump new(opts) end |
Instance Method Details
#authenticate(opts = {}, &block) ⇒ Object
Authenticates against the backend provider using the auth_service request class declared in the session’s configuration. Please see Session.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.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/puppet/feature/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 |
#authenticated? ⇒ Boolean
Returns true if the session has been authenticated. Note that this relies on cached response from a previous run of Session#authenticate if one was made. If you want to check against the backend provider if the session is still valid, use Session#validate instead.
243 244 245 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 243 def authenticated? !auth_response.nil? end |
#config ⇒ Object
Returns its configuration.
250 251 252 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 250 def config @config end |
#dump ⇒ Object
265 266 267 268 269 270 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 265 def dump JSON.generate({ :config => config, :auth_response => auth_response }) end |
#load(session_dump) ⇒ Object
Same as Session::load but re-uses the Session instance this method is called on instead of creating a new one.
277 278 279 280 281 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 277 def load(session_dump) initialize_with_dump(session_dump) update_services_session_data self end |
#log_file ⇒ Object
Returns the log file path. May be nil if none was provided during initialization.
314 315 316 |
# File 'lib/puppet/feature/aviator/core/session.rb', line 314 def log_file @log_file end |
#request(service_name, request_name, opts = {}, &block) ⇒ Object
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)
386 387 388 389 390 |
# File 'lib/puppet/feature/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 |
#validate ⇒ Object
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 Session::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 Session#authenticated? instead.
410 411 412 413 414 415 416 417 418 |
# File 'lib/puppet/feature/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 |