lib/fog/rackspace.rb in fog-maestrodev-1.8.0.20130114204828 vs lib/fog/rackspace.rb in fog-maestrodev-1.14.0.20130806165225

- old
+ new

@@ -1,42 +1,70 @@ require 'fog/core' +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 + attr_reader :response_data, :status_code, :transaction_id def to_s - status_code ? "[HTTP #{status_code}] #{super}" : super + status = status_code ? "HTTP #{status_code}" : "HTTP <Unknown>" + "[#{status} | #{transaction_id}] #{super}" end def self.slurp(error) data = nil message = nil status_code = nil - + if error.response - status_code = error.response.status + status_code = error.response.status unless error.response.body.empty? - data = Fog::JSON.decode(error.response.body) - message = data.values.first ? data.values.first['message'] : data['message'] + 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.instance_variable_set(:@status_code, status_code) + new_error.set_transaction_id(error, service) new_error end + + private + + 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 NotFound < ServiceError; end class ServiceUnavailable < ServiceError; end class BadRequest < ServiceError #TODO - Need to find a better way to print out these validation errors when they are thrown attr_reader :validation_errors @@ -44,11 +72,13 @@ def self.slurp(error) 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 - new_error + + new_error.instance_variable_set(:@status_code, status_code) + new_error.set_transaction_id(error, service) end end end service(:block_storage, 'rackspace/block_storage', 'BlockStorage') @@ -58,13 +88,15 @@ service(:dns, 'rackspace/dns', 'DNS') service(:storage, 'rackspace/storage', 'Storage') service(:load_balancers, 'rackspace/load_balancers', 'LoadBalancers') service(:identity, 'rackspace/identity', 'Identity') service(:databases, 'rackspace/databases', 'Databases') + service(:monitoring, 'rackspace/monitoring', 'Monitoring') def self.authenticate(options, connection_options = {}) - rackspace_auth_url = options[:rackspace_auth_url] || "auth.api.rackspacecloud.com" + 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::Connection.new(url, false, connection_options) @rackspace_api_key = options[:rackspace_api_key] @@ -80,9 +112,21 @@ :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.headers['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 = '') str.gsub(/([^a-zA-Z0-9_.-#{extra_exclude_chars}]+)/) do