1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/rackspace/core.rb
Paul Thornthwaite 0e1daf3ddd [GH-2711] Replace Fog::Connection with XML shim
Unlike last attempt this replaces Fog::Connection with
Fog::XML::Connection which should be directly compatible.

Fog::Connection is there for old PRs but should be removed real soon.

Providers using JSON should be able to replace "XML" with "Core" within
their code to cut down on the dependency.

If I get the time I may attempt to clean up some but testing with Mock
will mean that is mostly educated guesswork.
2014-02-27 00:54:17 +00:00

146 lines
5.3 KiB
Ruby

require 'fog/core'
require 'fog/json'
require 'fog/rackspace/mock_data'
require 'fog/rackspace/service'
require 'fog/rackspace/errors'
module Fog
module Rackspace
extend Fog::Provider
US_AUTH_ENDPOINT = 'https://identity.api.rackspacecloud.com/v2.0' unless defined? US_AUTH_ENDPOINT
UK_AUTH_ENDPOINT = 'https://lon.identity.api.rackspacecloud.com/v2.0' unless defined? UK_AUTH_ENDPOINT
module Errors
class ServiceError < Fog::Errors::Error
attr_reader :response_data, :status_code, :transaction_id
def to_s
status = status_code ? "HTTP #{status_code}" : "HTTP <Unknown>"
"[#{status} | #{transaction_id}] #{super}"
end
def self.slurp(error, service=nil)
data = nil
message = nil
status_code = nil
if error.response
status_code = error.response.status
unless error.response.body.empty?
begin
data = Fog::JSON.decode(error.response.body)
message = extract_message(data)
rescue => e
Fog::Logger.warning("Received exception '#{e}' while decoding>> #{error.response.body}")
message = error.response.body
data = error.response.body
end
end
end
new_error = super(error, message)
new_error.instance_variable_set(:@response_data, data)
new_error.instance_variable_set(:@status_code, status_code)
new_error.set_transaction_id(error, service)
new_error
end
def set_transaction_id(error, service)
return unless service && service.respond_to?(:request_id_header) && error.response
@transaction_id = error.response.headers[service.request_id_header]
end
def self.extract_message(data)
if data.is_a?(Hash)
message = data.values.first['message'] if data.values.first.is_a?(Hash)
message ||= data['message']
end
message || data.inspect
end
end
class InternalServerError < ServiceError; end
class Conflict < ServiceError; end
class ServiceUnavailable < ServiceError; end
class MethodNotAllowed < ServiceError; end
class BadRequest < ServiceError
attr_reader :validation_errors
def to_s
"#{super} - #{validation_errors}"
end
def self.slurp(error, service=nil)
new_error = super(error)
unless new_error.response_data.nil? or new_error.response_data['badRequest'].nil?
new_error.instance_variable_set(:@validation_errors, new_error.response_data['badRequest']['validationErrors'])
end
status_code = error.response ? error.response.status : nil
new_error.instance_variable_set(:@status_code, status_code)
new_error.set_transaction_id(error, service)
new_error
end
end
end
service(:auto_scale, 'AutoScale')
service(:block_storage, 'BlockStorage')
service(:cdn, 'CDN')
service(:compute, 'Compute')
service(:compute_v2, 'Compute v2')
service(:dns, 'DNS')
service(:storage, 'Storage')
service(:load_balancers, 'LoadBalancers')
service(:identity, 'Identity')
service(:databases, 'Databases')
service(:monitoring, 'Monitoring')
service(:queues, 'Queues')
def self.authenticate(options, connection_options = {})
rackspace_auth_url = options[:rackspace_auth_url]
rackspace_auth_url ||= options[:rackspace_endpoint] == Fog::Compute::RackspaceV2::LON_ENDPOINT ? "lon.auth.api.rackspacecloud.com" : "auth.api.rackspacecloud.com"
url = rackspace_auth_url.match(/^https?:/) ? \
rackspace_auth_url : 'https://' + rackspace_auth_url
uri = URI.parse(url)
connection = Fog::XML::Connection.new(url, false, connection_options)
@rackspace_api_key = options[:rackspace_api_key]
@rackspace_username = options[:rackspace_username]
response = connection.request({
:expects => [200, 204],
:headers => {
'X-Auth-Key' => @rackspace_api_key,
'X-Auth-User' => @rackspace_username
},
:method => 'GET',
:path => (uri.path and not uri.path.empty?) ? uri.path : 'v1.0'
})
response.headers.reject do |key, value|
!['X-Server-Management-Url', 'X-Storage-Url', 'X-CDN-Management-Url', 'X-Auth-Token'].include?(key)
end
end
def self.json_response?(response)
return false unless response && response.headers
response.get_header('Content-Type') =~ %r{application/json}i ? true : false
end
def self.normalize_url(endpoint)
return nil unless endpoint
str = endpoint.chomp " "
str = str.chomp "/"
str.downcase
end
# CGI.escape, but without special treatment on spaces
def self.escape(str,extra_exclude_chars = '')
# '-' is a special character inside a regex class so it must be first or last.
# Add extra excludes before the final '-' so it always remains trailing, otherwise
# an unwanted range is created by mistake.
str.gsub(/([^a-zA-Z0-9_.#{extra_exclude_chars}-]+)/) do
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
end
end
end
end