lib/stacker_bee/client.rb
require 'forwardable'
require 'stacker_bee/builder'
require 'stacker_bee/configuration'
require 'stacker_bee/api'
require 'stacker_bee/connection'
require 'stacker_bee/middleware/environment'
require 'stacker_bee/middleware/base'
require 'stacker_bee/middleware/adapter'
require 'stacker_bee/middleware/endpoint_normalizer'
require 'stacker_bee/middleware/remove_empty_strings'
require 'stacker_bee/middleware/cloud_stack_api'
require 'stacker_bee/middleware/dictionary_flattener'
require 'stacker_bee/middleware/remove_nils'
require 'stacker_bee/middleware/format_keys'
require 'stacker_bee/middleware/format_values'
require 'stacker_bee/middleware/json_body'
require 'stacker_bee/middleware/de_namespace'
require 'stacker_bee/middleware/rashify_response'
require 'stacker_bee/middleware/clean_response'
require 'stacker_bee/middleware/raise_on_http_error'
require 'stacker_bee/middleware/http_status'
require 'stacker_bee/middleware/console_access'
require 'stacker_bee/middleware/error_message'
require 'stacker_bee/middleware/log_response'
# rubocop:disable ClassLength
module StackerBee
class Client
DEFAULT_API_PATH = File.join(
File.dirname(__FILE__), '../../config/4.2.json'
)
# rubocop:disable MethodLength
# rubocop:disable Metrics/AbcSize
def middlewares
# request
builder.use Middleware::ConsoleAccess,
console_path: configuration.console_path
builder.use Middleware::EndpointNormalizer, api: self.class.api
builder.use Middleware::RemoveEmptyStrings
builder.use Middleware::CloudStackAPI,
api_path: configuration.api_path,
api_key: configuration.api_key
configuration.middlewares.call builder
builder.use Middleware::DictionaryFlattener
builder.use Middleware::RemoveNils
builder.use Middleware::FormatKeys
builder.use Middleware::FormatValues
# response
builder.use Middleware::RaiseOnHTTPError
builder.use Middleware::ErrorMessage
builder.use Middleware::LogResponse
builder.use Middleware::HTTPStatus
builder.use Middleware::CleanResponse
builder.use Middleware::RashifyResponse
builder.use Middleware::DeNamespace
builder.use Middleware::JSONBody
builder.use Middleware::Adapter, connection: connection
builder.build
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable MethodLength
def builder
@builder ||= Builder.new
end
class << self
def reset!
self.api, self.api_path, self.configuration = nil
end
def configuration
self.configuration = nil unless @configuration
@configuration
end
def configuration=(config_hash = {})
@configuration = Configuration.new(config_hash)
end
def api_path
@api_path ||= DEFAULT_API_PATH
end
def api_path=(new_api_path)
return @api_path if @api_path == new_api_path
@api = nil
@api_path = new_api_path
end
attr_writer :api
def api
@api ||= API.new(api_path: api_path)
end
end
def initialize(config = {})
self.configuration = config
end
def configuration=(config)
@configuration = self.class.configuration.merge(config)
end
def configuration
self.configuration = {} unless @configuration
@configuration
end
def request(endpoint_name, params = {})
env = Middleware::Environment.new(
endpoint_name: endpoint_name,
api_key: configuration.api_key,
params: params,
logger: configuration.logger
)
middleware_app.call(env)
env.response.body
end
def middleware_app
@app ||= begin
middleware_stack = middlewares
last_middleware = nil
middleware_stack.reverse.each do |middleware|
middleware.app = last_middleware
last_middleware = middleware
end
middleware_stack.first
end
end
def method_missing(method_name, *args, &block)
if respond_to_via_delegation?(method_name)
request(method_name, *args, &block)
else
super
end
end
def respond_to?(method_name, include_private = false)
super || respond_to_via_delegation?(method_name)
end
def respond_to_via_delegation?(method_name)
!!middleware_app.endpoint_name_for(method_name)
end
protected
def connection
@connection ||= Connection.new(configuration)
end
end
end