class Nucleus::AdapterResolver

The {AdapterResolver} can be used within Ruby applications to retrieve a Nucleus adapter. Returned adapters are patched so that each call enforces authentication and retries a call when a token was expired.

Public Class Methods

new(requested_version) click to toggle source
# File lib/nucleus/adapter_resolver.rb, line 7
def initialize(requested_version)
  raise 'No such version supported' unless Nucleus::VersionDetector.api_versions.include?(requested_version)
  @api_version = requested_version
end

Public Instance Methods

adapters() click to toggle source

Get a list of all adapters that are currently supported. @return [Hash<String, Hash<String, Nucleus::Adapters::BaseAdapter>>] currently supported adapters

# File lib/nucleus/adapter_resolver.rb, line 14
def adapters
  setup
  @adapters
end
load(vendor, username, password, options = {}) click to toggle source

Load the adapter to interact with the platform of the vendor that is offered at the endpoint_url. @param [String] vendor The vendor / adapter name that shall be used to communicate with the endpoint.

Must be provided, otherwise a +StandardError+ will be thrown.

@param [String] username The username that shall be used for authentication @param [String] password The password that shall be used for authentication @param [Hash<Symbol,?>] options Further options to apply when creating the adapter instance.

If available, the default configuration of the vendor configuration is applied as default.

@option options [String] :app_domain The domain where applications of the platform will be made available at.

This option must be set for custom deployments of platforms like Cloud Foundry or Openshift.
For IBM Bluemix this value would be: +eu-gb.mybluemix.net+ or +ng.mybluemix.net+, depending on the endpoint.

@option options [String] :check_ssl Set to false if SSL certificates shall not be verified (trust self-signed) @option options [String] :api_url URL of the endpoint’s API that shall be used.

Must be specified if there are multiple endpoints available and will be forced to https://

@raise [StandardError] if the vendor is unknown / not supported or no unique API endpoint could be identified @return [Nucleus::Adapters::BaseAdapter] loaded adapter implementation

# File lib/nucleus/adapter_resolver.rb, line 34
def load(vendor, username, password, options = {})
  setup
  raise StandardError, "Could not find adapter for vendor '#{vendor}'" unless @adapters.key?(vendor)

  # load the endpoint's HTTPS enabled API URL
  endpoint_url = load_endpoint(vendor, options)

  # load default configuration if available
  if @configurations[vendor].key?(endpoint_url)
    default_configuration = @configurations[vendor][endpoint_url]
    options = default_configuration.merge(options)
  end

  check_ssl = options.key?(:check_ssl) ? options[:check_ssl] : true
  adapter = @adapters[vendor].new(endpoint_url, options[:app_domain], check_ssl)

  fake_env = { 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack('m*').delete("\n") }
  # patch the adapter so that calls are wrapped and expect valid authentication
  AdapterAuthenticationInductor.patch(adapter, fake_env)

  cache_key = adapter.cache_key(username, password)
  # no auth object available, perform authentication first
  auth_object = adapter.auth_client
  # throws an error if the authentication failed
  auth_object.authenticate(username, password)
  # cache the auth object so it does not have to be retrieved per request
  adapter.cache(cache_key, auth_object)

  # return patched and initially authenticated adapter
  adapter
end

Private Instance Methods

load_endpoint(vendor, options) click to toggle source
# File lib/nucleus/adapter_resolver.rb, line 68
def load_endpoint(vendor, options)
  if options.key?(:api_url)
    # use chosen url endpoint
    endpoint_url = options[:api_url]
  elsif @configurations[vendor].length == 1
    # use default endpoint
    endpoint_url = @configurations[vendor].keys.first
  else
    raise StandardError, "Could not identify an API endpoint for the vendor '#{vendor}'. "\
      "Please specify the API URL to use with the ':api_url' option."
  end

  # make sure url uses https
  secure_url(endpoint_url)
end
setup() click to toggle source
# File lib/nucleus/adapter_resolver.rb, line 84
def setup
  # perform the setup only once
  return if @adapters

  # Initialize the application (import adapters, load DAOs, ...)
  require 'nucleus/scripts/initialize'
  # load the configuration values
  require 'nucleus/scripts/initialize_config_defaults'
  # Once invoked the configuration is locked
  require 'nucleus/scripts/finalize'

  @adapters = {}
  @configurations = {}
  Nucleus::Adapters.configuration_files.each do |adapter_config|
    vendor = Nucleus::VendorParser.parse(adapter_config)
    next unless vendor
    adapter_clazz = Nucleus::Adapters.adapter_clazz(adapter_config, @api_version)
    next unless adapter_clazz
    @adapters[vendor.id] = adapter_clazz
    @configurations[vendor.id] = {}

    # now load the default configurations for this vendor
    vendor.providers.each do |provider|
      provider.endpoints.each do |endpoint|
        @configurations[vendor.id][secure_url(endpoint.url)] = { check_ssl: !endpoint.trust,
                                                                 app_domain: endpoint.app_domain }
      end
    end
  end
end