lib/nightcrawler_swift/connection.rb
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