Skip to content

Commit

Permalink
Aviator 0.2.1
Browse files Browse the repository at this point in the history
  - Update to Aviator 0.2.1
  - Update example is README
  • Loading branch information
Aimon Bustardo authored and Aimon Bustardo committed Dec 15, 2014
1 parent d308a26 commit 9a3b74b
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 69 deletions.
2 changes: 1 addition & 1 deletion Modulefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name 'aimonb-aviator'
version '0.5.0'
version '0.5.1'
source 'https://github.com/aimonb/puppet_aviator'
author 'aimonb'
license 'MIT License'
Expand Down
15 changes: 6 additions & 9 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ Example Usage:
}
}

session = Aviator::Session.new(
:config => configuration,
:log_file => '/var/log/aviator.log'
)

session.authenticate
keystone = session.identity_service
response = keystone.request(:list_tenants, :endpoint_type =>
'admin')
openstack = Aviator::Session.new(:config => configuration)

openstack.authenticate
response = openstack.request :identity_service, :list_tenants, :endpoint_type => 'admin'

puts response[:body]
4 changes: 2 additions & 2 deletions lib/puppet/feature/aviator/core/cli/describer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def self.describe_request(provider_name, service_name, api_version, endpoint_typ
request_class = "Aviator::#{ provider_name.camelize }::#{ service_name.camelize }::Requests::"\
"#{ api_version.camelize }::#{ endpoint_type.camelize }::#{ request_name.camelize }".constantize

display = ":Request => #{ request_name }\n"
display = "Request: #{ request_name }\n"


# Build the parameters
Expand Down Expand Up @@ -83,7 +83,7 @@ def self.describe_request(provider_name, service_name, api_version, endpoint_typ
# Build the sample code
display << "\nSample Code:\n"

display << " session.#{ service_name }_service.request(:#{ request_name })"
display << " session.request(:#{ service_name }_service, :#{ request_name })"

if params && params.length > 0
display << " do |params|\n"
Expand Down
14 changes: 11 additions & 3 deletions lib/puppet/feature/aviator/core/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize(response, request)


def body
if raw_body.length > 0
@body ||= if raw_body.length > 0
if Aviator::Compatibility::RUBY_1_8_MODE
clean_body = raw_body.gsub(/\\ /, ' ')
else
Expand All @@ -29,14 +29,22 @@ def body


def headers
Hashish.new(@response.headers)
@headers ||= Hashish.new(@response.headers)
end


def to_hash
Hashish.new({
:status => status,
:headers => headers,
:body => body
})
end

private

def raw_body
@response.body
@raw_body ||= @response.body
end

end
Expand Down
21 changes: 19 additions & 2 deletions lib/puppet/feature/aviator/core/service.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module Aviator

#
# Manages a service
#
class Service

class AccessDetailsNotDefinedError < StandardError
Expand Down Expand Up @@ -35,7 +38,6 @@ def initialize(service_name, request_name)
end
end


class UnknownRequestError < StandardError
def initialize(request_name, options)
super "Unknown request #{ request_name } #{ options }."
Expand Down Expand Up @@ -75,7 +77,9 @@ def initialize(opts={})
load_requests
end


#
# No longer recommended for public use. Use Aviator::Session#request instead
#
def request(request_name, options={}, &params)
if options[:api_version].nil? && @default_options[:api_version]
options[:api_version] = @default_options[:api_version]
Expand All @@ -93,6 +97,19 @@ def request(request_name, options={}, &params)

raise UnknownRequestError.new(request_name, options) unless request_class

# Always use :params over &params if provided
if options[:params]
params = lambda do |params|
options[:params].each do |key, value|
begin
params[key] = value
rescue NameError => e
raise NameError.new("Unknown param name '#{key}'")
end
end
end
end

request = request_class.new(session_data, &params)

response = http_connection.send(request.http_method) do |r|
Expand Down
149 changes: 112 additions & 37 deletions lib/puppet/feature/aviator/core/session.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#
# Author:: Mark Maglana ([email protected])
# Copyright:: Copyright (c) 2014 Mark Maglana
# License:: Distributed under the MIT license
# Homepage:: http://aviator.github.io/www/
#
module Aviator

#
# Manages a provider (e.g. OpenStack) session.
#
# Author:: Mark Maglana ([email protected])
# Copyright:: Copyright (c) 2014 Mark Maglana
# License:: Distributed under the MIT license
# Homepage:: http://aviator.github.io/www/
# 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.
#
class Session

Expand Down Expand Up @@ -51,8 +53,7 @@ def initialize
end

#
# Create a new Session instance with options provided in <tt>opts</tt> which can
# have many forms discussed below.
# Create a new Session instance.
#
# <b>Initialize with a config file</b>
#
Expand All @@ -73,25 +74,28 @@ def initialize
# password: mypassword
# tenant_name: myproject
#
# <b>SIDENOTE:</b> For more information about the <tt>validator</tt> member, see Session#validate.
#
# Once the session has been instantiated, you may authenticate against the
# provider as follows:
#
# session.authenticate
#
# Note that the required items under <tt>auth_credentials</tt> in the config
# file depends on the required parameters of the request class declared under
# <tt>auth_service</tt>. If writing the <tt>auth_credentials</tt> in the config
# file is not acceptable, you may omit it and just supply the credentials at
# runtime. For instance, assume that the <tt>auth_credentials</tt> section in the
# config file above is missing. You would then authenticate as follows:
# The members you put under <tt>auth_credentials</tt> will depend on the request
# class you declare under <tt>auth_service:request</tt> and what parameters it
# accepts. To know more about a request class and its parameters, you can use
# the CLI tool <tt>aviator describe</tt> or view the request definition file directly.
#
# If writing the <tt>auth_credentials</tt> 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
#
# Please see Session#authenticate for more info.
# 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
Expand All @@ -100,8 +104,8 @@ def initialize
#
# <b>Initialize with an in-memory hash</b>
#
# You can create an in-memory hash which is similar in structure to the config file except
# that you don't need to specify an environment name. For example:
# 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',
Expand Down Expand Up @@ -150,12 +154,14 @@ def initialize(opts={})
end

#
# Authenticates against the auth_service request class declared in the session's
# configuration during initialization. Please see Session.new for more information
# 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.
#
# If the auth_service request class accepts a parameter block, you may also supply that
# when calling this method and it will be directly passed to the request. For example:
# <b>Request params block</b>
#
# 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|
Expand All @@ -164,9 +170,12 @@ def initialize(opts={})
# params.tenant_name = project
# end
#
# Expects an HTTP status 200 or 201. Any other status is treated as a failure.
# If your configuration happens to have an <tt>auth_credentials</tt> in it, those
# will be overridden by this block.
#
# Note that you can also treat the block's argument like a hash with the attribute
# <b>Treat parameters as a hash</b>
#
# 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)
Expand All @@ -178,7 +187,29 @@ def initialize(opts={})
#
# Keys can be symbols or strings.
#
def authenticate(&block)
# <b>Use a hash argument instead of a block</b>
#
# 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 <tt>:params</tt> and a block are provided, the <tt>:params</tt>
# values will be used and the block ignored.
#
# <b>Success requirements</b>
#
# Expects an HTTP status 200 or 201 response from the backend. Any other
# status is treated as a failure.
#
def authenticate(opts={}, &block)
block ||= lambda do |params|
config[:auth_credentials].each do |key, value|
begin
Expand All @@ -189,7 +220,7 @@ def authenticate(&block)
end
end

response = auth_service.request config[:auth_service][:request].to_sym, &block
response = auth_service.request(config[:auth_service][:request].to_sym, opts, &block)

if [200, 201].include? response.status
@auth_response = Hashish.new({
Expand All @@ -204,7 +235,10 @@ def authenticate(&block)
end

#
# Returns true if the session has been authenticated.
# 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.
#
def authenticated?
!auth_response.nil?
Expand Down Expand Up @@ -247,7 +281,7 @@ def load(session_dump)
end


def method_missing(name, *args, &block)
def method_missing(name, *args, &block) # :nodoc:
service_name_parts = name.to_s.match(/^(\w+)_service$/)

if service_name_parts
Expand All @@ -262,7 +296,8 @@ def method_missing(name, *args, &block)
# Creates a new Session object from a previous session's dump. See Session#dump for
# more information.
#
# If you want the newly deserialized session to log its output, make sure to indicate it on load
# If you want the newly deserialized session to log its output, add a <tt>:log_file</tt>
# option.
#
# Aviator::Session.load(session_dump_str, :log_file => 'path/to/aviator.log')
#
Expand Down Expand Up @@ -301,37 +336,77 @@ def log_file
#
# 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 <tt>:params</tt> and a block are provided, the values in <tt>:params</tt>
# will be used and the block ignored.
#
# <b>Return Value</b>
#
# 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 <tt>:headers</tt> and <tt>:body</tt> will vary depending
# on the provider and the request that was made.
#
# ---
#
# <b>Request Options</b>
#
# You can further customize how the request is fulfilled by providing one or more
# options to the method call. For example, the following ensures that the request
# will call the :create_server request for the v1 API.
# You can further customize how the method behaves by providing one or more
# options to the call. For example, assuming you are using the <tt>openstack</tt>
# provider, the following will call the <tt>:create_server</tt> request of the
# v1 API of <tt>:compute_service</tt>.
#
# session.request :compute_service, :create_server, :api_version => v1
# 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)
# on the provider's Provider class for more information (e.g. Aviator::Openstack::Provider)
#
def request(service_name, request_name, opts={}, &params)
def request(service_name, request_name, opts={}, &block)
service = send("#{service_name.to_s}_service")
service.request(request_name, opts, &params)
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 does this
# by calling the validator request class declared declared under <tt>auth_service</tt> in the
# Returns true if the session is still valid in the underlying provider. This method calls
# the <tt>validator</tt> request class declared under <tt>auth_service</tt> 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.
#
def validate
raise NotAuthenticatedError.new unless authenticated?
raise ValidatorNotDefinedError.new unless config[:auth_service][:validator]
Expand Down
Loading

0 comments on commit 9a3b74b

Please sign in to comment.