5 class AccessDetailsNotDefinedError < StandardError
7 super ":access_details is not defined."
11 class ProviderNotDefinedError < StandardError
13 super ":provider is not defined."
17 class ServiceNameNotDefinedError < StandardError
19 super ":service is not defined."
23 class SessionDataNotProvidedError < StandardError
25 super "default_session_data is not initialized and no session data was "\
26 "provided in the method call."
31 class UnknownRequestError < StandardError
32 def initialize(request_name)
33 super "Unknown request #{ request_name }."
38 class MissingServiceEndpointError < StandardError
39 def initialize(service_name, request_name)
40 request_name = request_name.to_s.split('::').last.underscore
41 super "The session's service catalog does not have an entry for the #{ service_name } "\
42 "service. Therefore, I don't know to which base URL the request should be sent. "\
43 "This may be because you are using a default or unscoped token. If this is not your "\
44 "intention, please authenticate with a scoped token. If using a default token is your "\
45 "intention, make sure to provide a base url when you call the request. For :example => \n\n"\
46 "session.#{ service_name }_service.request :#{ request_name }, :base_url => 'http://myenv.com:9999/v2.0' do |params|\n"\
47 " params[:example1] = 'example1'\n"\
48 " params[:example2] = 'example2'\n"\
53 attr_accessor :default_session_data
59 def initialize(opts={})
60 @provider = opts[:provider] || (raise ProviderNotDefinedError.new)
61 @service = opts[:service] || (raise ServiceNameNotDefinedError.new)
62 @log_file = opts[:log_file]
64 @default_session_data = opts[:default_session_data]
70 def request(request_name, options={}, ¶ms)
71 session_data = options[:session_data] || default_session_data
73 raise SessionDataNotProvidedError.new unless session_data
75 [:base_url].each do |k|
76 session_data[k] = options[k] if options[k]
79 request_class = find_request(request_name, session_data, options[:endpoint_type])
81 raise UnknownRequestError.new(request_name) unless request_class
83 request = request_class.new(session_data, ¶ms)
85 response = http_connection.send(request.http_method) do |r|
87 r.headers.merge!(request.headers) if request.headers?
88 r.query = request.querystring if request.querystring?
89 r.body = JSON.generate(request.body) if request.body?
92 Aviator::Response.send(:new, response, request)
105 @http_connection ||= Faraday.new do |conn|
106 conn.use Logger.configure(log_file) if log_file
107 conn.adapter Faraday.default_adapter
109 conn.headers['Content-Type'] = 'application/json'
114 # Candidate for extraction to aviator/openstack
115 def find_request(name, session_data, endpoint_type=nil)
116 endpoint_types = if endpoint_type
117 [endpoint_type.to_s.camelize]
122 namespace = Aviator.const_get(provider.camelize) \
123 .const_get(service.camelize)
125 version = infer_version(session_data, name).to_s.camelize
127 return nil unless version && namespace.const_defined?(version)
129 namespace = namespace.const_get(version, name)
131 endpoint_types.each do |endpoint_type|
132 name = name.to_s.camelize
134 next unless namespace.const_defined?(endpoint_type)
135 next unless namespace.const_get(endpoint_type).const_defined?(name)
137 return namespace.const_get(endpoint_type).const_get(name)
144 # Candidate for extraction to aviator/openstack
145 def infer_version(session_data, request_name='sample_request')
146 if session_data.has_key?(:auth_service) && session_data[:auth_service][:api_version]
147 session_data[:auth_service][:api_version].to_sym
149 elsif session_data.has_key?(:auth_service) && session_data[:auth_service][:host_uri]
150 m = session_data[:auth_service][:host_uri].match(/(v\d+)\.?\d*/)
151 return m[1].to_sym unless m.nil?
153 elsif session_data.has_key? :base_url
154 m = session_data[:base_url].match(/(v\d+)\.?\d*/)
155 return m[1].to_sym unless m.nil?
157 elsif session_data.has_key? :access
158 service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == service }
159 raise MissingServiceEndpointError.new(service.to_s, request_name) unless service_spec
160 version = service_spec[:endpoints][0][:publicURL].match(/(v\d+)\.?\d*/)
161 version ? version[1].to_sym : :v1
167 # :TODO => This should be determined by a provider-specific module.
168 # e.g. Aviator::OpenStack::requests_base_dir
169 request_file_paths = Dir.glob(Pathname.new(__FILE__).join(
179 request_file_paths.each{ |path| require path }
181 constant_parts = request_file_paths \
182 .map{|rf| rf.to_s.match(/#{provider}\/#{service}\/([\w\/]+)\.rb$/) } \
183 .map{|rf| rf[1].split('/').map{|c| c.camelize }.join('::') }
185 @request_classes = constant_parts.map do |cp|
186 "Aviator::#{provider.camelize}::#{service.camelize}::#{cp}".constantize