tulios/nightcrawler_swift

View on GitHub
lib/nightcrawler_swift/connection.rb

Summary

Maintainability
A
1 hr
Test Coverage
module NightcrawlerSwift
  class Connection
    def self.connected_attr_reader(*args)
      args.each do |arg|
        define_method(arg.to_sym) do
          connect! unless connected?
          instance_variable_get("@#{arg}")
        end
      end
    end

    private_class_method :connected_attr_reader

    attr_writer :auth_response
    attr_reader :token_id, :expires_at
    connected_attr_reader :catalog, :admin_url, :upload_url, :public_url, :internal_url

    def auth_response
      @auth_response ||= nil
      authenticate! if @auth_response.nil?
      @auth_response
    end

    def connect!
      authenticate!
      configure

      NightcrawlerSwift.logger.debug "[NightcrawlerSwift] Connected, token_id: #{token_id}"
      self
    end

    def connected?
      !self.token_id.nil? and self.expires_at > Time.now
    end

    def configure
      select_token
      select_catalog
      select_endpoints
      configure_urls
    end

    private
    def opts
      NightcrawlerSwift.options
    end

    def authenticate!
      url = opts.auth_url
      headers = {content_type: :json, accept: :json}
      response = Gateway.new(url).request {|r| r.post(auth_options.to_json, headers)}

      @auth_response = OpenStruct.new(headers: response.headers, body: JSON.parse(response.body))
    rescue StandardError => e
      raise Exceptions::ConnectionError.new(e)
    end

    def auth_options
      {
        auth: {
          identity: {
              methods: [
                  "password"
              ],
              password: {
                  user: {
                      domain: {
                          id: "default"
                      },
                      name: opts.username,
                      password: opts.password
                  }
              }
          },
          scope: {
              project: {
                  domain: {
                      id: "default"
                  },
                  name: opts.tenant_name
              }
          }
        }
      }
    end

    def select_token
      @token_id = auth_response.headers[:x_subject_token]
      @expires_at = auth_response.body["token"]["expires_at"]
      @expires_at = DateTime.parse(@expires_at).to_time
    end

    def select_catalog
      catalogs = auth_response["body"]["token"]["catalog"]
      @catalog = catalogs.find {|catalog| catalog["type"] == "object-store"}
    end

    def select_endpoints
      raise Exceptions::ConfigurationError.new "No catalog of type 'object-store' found" if @catalog.nil?
      @endpoints = @catalog["endpoints"]
    end

    def configure_urls
      @admin_url = opts.admin_url || @endpoints.find {|e| e["interface"] == "admin"}["url"]
      @public_url = opts.public_url || @endpoints.find {|e| e["interface"] == "public"}["url"]
      @internal_url = opts.internal_url || @endpoints.find {|e| e["interface"] == "internal"}["url"]
      @upload_url = "#{@admin_url}/#{opts.bucket}"
    end
  end
end