diff --git a/lib/fog/rackspace/cdn.rb b/lib/fog/rackspace/cdn.rb index 3fb2e3fc7d..e41e8381bf 100644 --- a/lib/fog/rackspace/cdn.rb +++ b/lib/fog/rackspace/cdn.rb @@ -23,6 +23,17 @@ module Base "X-Cdn-Ssl-Uri" => :ssl_uri }.freeze + def apply_options(options) + # api_key and username missing from instance variable sets + @rackspace_api_key = options[:rackspace_api_key] + @rackspace_username = options[:rackspace_username] + + @connection_options = options[:connection_options] || {} + @rackspace_auth_url = options[:rackspace_auth_url] + @rackspace_cdn_url = options[:rackspace_cdn_url] + @rackspace_region = options[:rackspace_region] || :dfw + end + def service_name :cloudFilesCDN end @@ -35,6 +46,12 @@ def request_id_header "X-Trans-Id" end + # Returns true if CDN service is enabled + # @return [Boolean] + def enabled? + @enabled + end + def endpoint_uri(service_endpoint_url=nil) @uri = super(@rackspace_cdn_url || service_endpoint_url, :rackspace_cdn_url) end @@ -97,7 +114,9 @@ def self.reset end def initialize(options={}) - @rackspace_username = options[:rackspace_username] + apply_options(options) + authenticate(options) + @enabled = !! endpoint_uri end def data @@ -119,14 +138,7 @@ class Real < Fog::Rackspace::Service include Base def initialize(options={}) - # api_key and username missing from instance variable sets - @rackspace_api_key = options[:rackspace_api_key] - @rackspace_username = options[:rackspace_username] - - @connection_options = options[:connection_options] || {} - @rackspace_auth_url = options[:rackspace_auth_url] - @rackspace_cdn_url = options[:rackspace_cdn_url] - @rackspace_region = options[:rackspace_region] || :dfw + apply_options(options) authenticate(options) @enabled = false @persistent = options[:persistent] || false @@ -137,12 +149,6 @@ def initialize(options={}) end end - # Returns true if CDN service is enabled - # @return [Boolean] - def enabled? - @enabled - end - # Resets CDN connection def reload @cdn_connection.reset diff --git a/lib/fog/rackspace/identity.rb b/lib/fog/rackspace/identity.rb index d1048a893b..ce59b5dab1 100644 --- a/lib/fog/rackspace/identity.rb +++ b/lib/fog/rackspace/identity.rb @@ -34,18 +34,16 @@ class Identity < Fog::Service request :update_user request :delete_user - class Mock < Fog::Rackspace::Service - attr_reader :service_catalog - - def request - Fog::Mock.not_implemented + module Common + attr_reader :service_catalog, :auth_token + + def authenticate(options={}) + data = self.create_token(@rackspace_username, @rackspace_api_key).body + @service_catalog = ServiceCatalog.from_response(self, data) + @auth_token = data['access']['token']['id'] end - end - class Real < Fog::Rackspace::Service - attr_reader :service_catalog, :auth_token - - def initialize(options={}) + def apply_options(options) @rackspace_username = options[:rackspace_username] @rackspace_api_key = options[:rackspace_api_key] @rackspace_region = options[:rackspace_region] @@ -58,15 +56,27 @@ def initialize(options={}) @scheme = @uri.scheme @persistent = options[:persistent] || false @connection_options = options[:connection_options] || {} - @connection = Fog::Connection.new(@uri.to_s, @persistent, @connection_options) + end + end + + class Mock < Fog::Rackspace::Service + include Common + + def initialize(options={}) + apply_options(options) authenticate end + end + + class Real < Fog::Rackspace::Service + include Common - def authenticate(options={}) - data = self.create_token(@rackspace_username, @rackspace_api_key).body - @service_catalog = ServiceCatalog.from_response(self, data) - @auth_token = data['access']['token']['id'] + def initialize(options={}) + apply_options(options) + @connection = Fog::Connection.new(@uri.to_s, @persistent, @connection_options) + + authenticate end end end diff --git a/lib/fog/rackspace/models/storage/directory.rb b/lib/fog/rackspace/models/storage/directory.rb index a4e8602904..05546dd741 100644 --- a/lib/fog/rackspace/models/storage/directory.rb +++ b/lib/fog/rackspace/models/storage/directory.rb @@ -166,8 +166,11 @@ def streaming_url def save requires :key create_or_update_container - raise Fog::Storage::Rackspace::Error.new("Directory can not be set as :public without a CDN provided") if public? && !cdn_enabled? - @urls = service.cdn.publish_container(self, public?) + if cdn_enabled? + @urls = service.cdn.publish_container(self, public?) + else + raise Fog::Storage::Rackspace::Error.new("Directory can not be set as :public without a CDN provided") if public? + end true end diff --git a/lib/fog/rackspace/requests/identity/create_token.rb b/lib/fog/rackspace/requests/identity/create_token.rb index 8a1111724d..607d05699a 100644 --- a/lib/fog/rackspace/requests/identity/create_token.rb +++ b/lib/fog/rackspace/requests/identity/create_token.rb @@ -20,6 +20,198 @@ def create_token(username, api_key) ) end end + + class Mock + def create_token(username, api_key) + unless username == 'baduser' || api_key == 'bad_key' + compute_tenant = Fog::Mock.random_numbers(6) + object_tenant = generate_object_tenant + + response = Excon::Response.new + response.status = 200 + response.body = { + "access" => { + "token"=> { + "id" => Fog::Mock.random_hex(32), + "expires" => (Time.now.utc + 86400).strftime("%Y-%m-%dT%H:%M:%S.%LZ"), + "tenant" => { "id" => compute_tenant, "name" => compute_tenant } + }, + "user" => { + "id" => Fog::Mock.random_numbers(6), + "name" => username, + "roles" => [ + { + "id" => Fog::Mock.random_numbers(1), + "description" => "Fake Role for an object store", + "name" => "object-store:default" + }, + { + "id" => Fog::Mock.random_numbers(1), + "description" => "Fake Role for a compute cluster", + "name" => "compute:default" + } + ] + }, + "serviceCatalog" => build_service_catalog(compute_tenant, object_tenant), + } + } + response + else + response = Excon::Response.new + response.status = 401 + response.body = { + "unauthorized" => { + "code" => 401, + "message" => "Username or API key is invalid." + } + } + raise Excon::Errors::Unauthorized.new('Unauthorized', nil, response) + end + end + + # Generate a realistic-looking object tenant ID. + def generate_object_tenant + uuid = [8, 4, 4, 4, 12].map { |n| Fog::Mock.random_hex(n) }.join('_') + "FogMockFS_#{uuid}" + end + + # Construct a full, fake service catalog. + # + # @param compute_tenant [String] Tenant ID to be used in entries for + # compute-based services (most of them). + # @param object_tenant [String] Tenant ID to be used in object-store + # related entries. + # + # @return [Hash] A fully-populated, valid service catalog. + def build_service_catalog(compute_tenant, object_tenant) + [ + service_catalog_entry("cloudFilesCDN", "rax:object-cdn", object_tenant, + :public_url => lambda do |r| + "https://cdn#{Fog::Mock.random_numbers(1)}.clouddrive.com/v1/#{object_tenant}" + end), + + service_catalog_entry("cloudFiles", "object-store", object_tenant, + :internal_url_snet => true, + :public_url => lambda do |r| + "https://storage101.#{r}#{Fog::Mock.random_numbers(1)}.clouddrive.com/v1/#{object_tenant}" + end), + + service_catalog_entry("cloudMonitoring", "rax:monitor", compute_tenant, + :single_endpoint => true, :rackspace_api_name => 'monitoring'), + + service_catalog_entry("cloudServersOpenStack", "compute", compute_tenant, + :version_base_url => lambda { |r| "https://#{r}.servers.api.rackspacecloud.com" }, + :version_id => "2"), + + service_catalog_entry("cloudBlockStorage", "volume", compute_tenant, + :rackspace_api_name => 'blockstorage', :rackspace_api_version => '1'), + + service_catalog_entry("cloudDatabases", "rax:database", compute_tenant, + :rackspace_api_name => 'databases'), + + service_catalog_entry("cloudLoadBalancers", "rax:load-balander", compute_tenant, + :rackspace_api_name => 'loadbalancers'), + + service_catalog_entry("cloudDNS", "rax:dns", compute_tenant, + :single_endpoint => true, :rackspace_api_name => 'dns'), + + service_catalog_entry("cloudOrchestration", "orchestration", compute_tenant, + :rackspace_api_name => 'orchestration', :rackspace_api_version => '1'), + + service_catalog_entry("cloudQueues", "rax:queues", compute_tenant, + :internal_url_snet => true, + :rackspace_api_name => 'queues', :rackspace_api_version => '1'), + + service_catalog_entry("cloudBackup", "rax:backup", compute_tenant, + :rackspace_api_name => 'backup'), + + service_catalog_entry("cloudImages", "image", compute_tenant, + :rackspace_api_name => 'images', :rackspace_api_version => '2'), + + service_catalog_entry("autoscale", "rax:autoscale", compute_tenant, + :rackspace_api_name => 'autoscale'), + + service_catalog_entry("cloudServers", "compute", compute_tenant, + :single_endpoint => true, + :version_base_url => lambda { |r| "https://servers.api.rackspacecloud.com" }, + :version_id => '1.0') + ] + end + + # Generate an individual service catalog entry for a fake service + # catalog. Understands common patterns used within Rackspace + # service catalogs. + # + # @param name [String] The required "name" attribute of the + # service catalog entry. + # @param type [String] The required "type" attribute. + # @param tenant_id [String] Tenant ID to be used for this service. + # + # @param options [Hash] Control the contents of the generated entry. + # @option options [Proc] :public_url Callable invoked with each region + # (or `nil`) to generate a `publicURL` for that region. + # @option options [Boolean] :single_endpoint If `true`, only a single + # endpoint entry will be generated, rather than an endpoint for each + # region. + # @option options [Boolean] :internal_url_snet If `true`, an internalURL + # entry will be generated by prepending "snet-" to the publicURL. + # @option options [String] :rackspace_api_name If specified, will generate + # publicURL as a Rackspace API URL. + # @option options [String] :rackspace_api_version (`"1.0"`) Specify the + # version of the Rackspace API URL. + # + # @return [Hash] A valid service catalog entry. + def service_catalog_entry(name, type, tenant_id, options) + if options[:rackspace_api_name] + api_name = options[:rackspace_api_name] + api_version = options[:rackspace_api_version] || "1.0" + options[:public_url] = lambda do |r| + prefix = r ? "#{r}." : "" + "https://#{prefix}#{api_name}.api.rackspacecloud.com/v#{api_version}/#{tenant_id}" + end + end + + entry = { "name" => name, "type" => type } + if options[:single_endpoint] + entry["endpoints"] = [endpoint_entry(tenant_id, nil, options)] + else + entry["endpoints"] = %w{ORD DFW SYD IAD HKG}.map do |region| + endpoint_entry(tenant_id, region, options) + end + end + entry + end + + # Helper method that generates a single endpoint hash within a service + # catalog entry. + # + # @param tenant_id [String] The tenant ID used for this endpoint. + # @param region [String, nil] The region to include in this endpoint, if any. + # @param options [Hash] Options inherited from {#service_catalog_entry}. + # + # @return [Hash] A well-formed endpoint hash. + def endpoint_entry(tenant_id, region, options) + endpoint = { "tenantId" => tenant_id } + endpoint["region"] = region if region + r = region.downcase if region + endpoint["publicURL"] = options[:public_url].call(r) if options[:public_url] + + if options[:internal_url_snet] + endpoint["internalURL"] = endpoint["publicURL"].gsub(%r{^https://}, "https://snet-") + end + + endpoint["internalURL"] = options[:internal_url].call(r) if options[:internal_url] + if options[:version_base_url] && options[:version_id] + base = options[:version_base_url].call(r) + version = options[:version_id] + endpoint["publicURL"] = "#{base}/v#{version}/#{tenant_id}" + endpoint["versionInfo"] = "#{base}/v#{version}" + endpoint["versionList"] = base + endpoint["versionId"] = version + end + endpoint + end + end end end end diff --git a/lib/fog/rackspace/requests/identity/list_tenants.rb b/lib/fog/rackspace/requests/identity/list_tenants.rb index 04102a48da..718ef35d6b 100644 --- a/lib/fog/rackspace/requests/identity/list_tenants.rb +++ b/lib/fog/rackspace/requests/identity/list_tenants.rb @@ -17,6 +17,29 @@ def list_tenants() response end end + + class Mock + def list_tenants + response = Excon::Response.new + response.status = [200, 203][rand(1)] + response.body = { + "tenants" => [ + { + "id" => Fog::Mock.random_numbers(6), + "name" => "Enabled tenant", + "enabled" => true + }, + { + "id" => Fog::Mock.random_numbers(6), + "name" => "Disabled tenant", + "enabled" => false + }, + ], + "tenants_links" => [] + } + response + end + end end end end diff --git a/lib/fog/rackspace/requests/storage/delete_container.rb b/lib/fog/rackspace/requests/storage/delete_container.rb index d809b4a795..a7f12d4190 100644 --- a/lib/fog/rackspace/requests/storage/delete_container.rb +++ b/lib/fog/rackspace/requests/storage/delete_container.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Delete an existing container @@ -20,6 +21,20 @@ def delete_container(name) end end + + class Mock + def delete_container(name) + c = mock_container! name + + raise Excon::Errors::Conflict.new 'Conflict' unless c.empty? + remove_container name + + response = Excon::Response.new + response.status = 204 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/delete_multiple_objects.rb b/lib/fog/rackspace/requests/storage/delete_multiple_objects.rb index daf646aa90..3d3ac1dc30 100644 --- a/lib/fog/rackspace/requests/storage/delete_multiple_objects.rb +++ b/lib/fog/rackspace/requests/storage/delete_multiple_objects.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Deletes multiple objects or containers with a single request. @@ -70,6 +71,62 @@ def delete_multiple_objects(container, object_names, options = {}) end end + + class Mock + def delete_multiple_objects(container, object_names, options = {}) + results = { + "Number Not Found" => 0, + "Response Status" => "200 OK", + "Response Body" => "", + "Errors" => [], + "Number Deleted" => 0 + } + + object_names.each do |name| + if container + cname, oname = container, name + else + cname, oname = name.split('/', 2) + end + + c = mock_container cname + if c.nil? + # Container not found + results["Number Not Found"] += 1 + next + end + + if oname.nil? + # No object name specified; delete the container if it's nonempty + unless c.empty? + results["Response Status"] = "400 Bad Request" + results["Errors"] << [cname, "409 Conflict"] + next + end + + remove_container cname + results["Number Deleted"] += 1 + next + end + + o = c.mock_object oname + if o.nil? + # Object not found. + results["Number Not Found"] += 1 + next + end + + c.remove_object oname + results["Number Deleted"] += 1 + end + + response = Excon::Response.new + response.status = 200 + response.body = results + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/delete_object.rb b/lib/fog/rackspace/requests/storage/delete_object.rb index c10377658f..c4bc60f262 100644 --- a/lib/fog/rackspace/requests/storage/delete_object.rb +++ b/lib/fog/rackspace/requests/storage/delete_object.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Delete an existing object @@ -21,6 +22,19 @@ def delete_object(container, object) end end + + class Mock + def delete_object(container, object) + c = mock_container! container + c.mock_object! object + c.remove_object object + + response = Excon::Response.new + response.status = 204 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/delete_static_large_object.rb b/lib/fog/rackspace/requests/storage/delete_static_large_object.rb index 8c556d27c1..6314a12933 100644 --- a/lib/fog/rackspace/requests/storage/delete_static_large_object.rb +++ b/lib/fog/rackspace/requests/storage/delete_static_large_object.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Delete a static large object. @@ -44,6 +45,38 @@ def delete_static_large_object(container, object, options = {}) end end + + class Mock + def delete_static_large_object(container, object, options = {}) + c = mock_container container + return not_found(container) unless c + + o = c.mock_object object + return not_found(object) unless o + + # What happens if o isn't a static large object? + raise Fog::Storage::Rackspace::BadRequest.new unless o.static_manifest? + + segments = Fog::JSON.decode(o.body) + paths = segments.map { |s| s['path'] } + paths << "#{container}/#{object}" + delete_multiple_objects(nil, paths) + end + + def not_found(path) + response = Excon::Response.new + response.status = 200 + response.body = { + "Number Not Found" => 1, + "Response Status" => "200 OK", + "Response Body" => "", + "Errors" => [[path, "404 Not Found"]], + "Number Deleted" => 0 + } + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/get_container.rb b/lib/fog/rackspace/requests/storage/get_container.rb index 292dbbd437..fe09724c51 100644 --- a/lib/fog/rackspace/requests/storage/get_container.rb +++ b/lib/fog/rackspace/requests/storage/get_container.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Get details for container and total bytes stored @@ -43,6 +44,30 @@ def get_container(container, options = {}) end end + + class Mock + def get_container(container, options = {}) + c = mock_container! container + + results = [] + c.objects.each do |key, mock_file| + results << { + "hash" => mock_file.hash, + "last_modified" => mock_file.last_modified.strftime('%Y-%m-%dT%H:%M:%S.%L'), + "bytes" => mock_file.bytes_used, + "name" => key, + "content_type" => mock_file.content_type + } + end + + response = Excon::Response.new + response.status = 200 + response.headers = c.to_headers + response.body = results + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/get_containers.rb b/lib/fog/rackspace/requests/storage/get_containers.rb index 2305006959..0ea7a28b14 100644 --- a/lib/fog/rackspace/requests/storage/get_containers.rb +++ b/lib/fog/rackspace/requests/storage/get_containers.rb @@ -32,6 +32,23 @@ def get_containers(options = {}) end end + + class Mock + def get_containers(options = {}) + results = data.map do |name, container| + { + "name" => name, + "count" => container.objects.size, + "bytes" => container.bytes_used + } + end + response = Excon::Response.new + response.status = 200 + response.body = results + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/get_object.rb b/lib/fog/rackspace/requests/storage/get_object.rb index 232d011e9d..0490a13e41 100644 --- a/lib/fog/rackspace/requests/storage/get_object.rb +++ b/lib/fog/rackspace/requests/storage/get_object.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Get details for object @@ -27,6 +28,31 @@ def get_object(container, object, &block) end end + + class Mock + def get_object(container, object, &block) + c = mock_container! container + o = c.mock_object! object + + body, size = "", 0 + + o.each_part do |part| + body << part.body + size += part.bytes_used + end + + if block_given? + # Just send it all in one chunk. + block.call(body, 0, size) + end + + response = Excon::Response.new + response.body = body + response.headers = o.to_headers + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/get_object_http_url.rb b/lib/fog/rackspace/requests/storage/get_object_http_url.rb index 73c8281950..2bf419f5bd 100644 --- a/lib/fog/rackspace/requests/storage/get_object_http_url.rb +++ b/lib/fog/rackspace/requests/storage/get_object_http_url.rb @@ -2,8 +2,7 @@ module Fog module Storage class Rackspace - class Real - + module Common # Get an expiring object http url from Cloud Files # # ==== Parameters @@ -25,6 +24,14 @@ def get_object_http_url(container, object, expires, options = {}) end end + class Real + include Common + end + + class Mock + include Common + end + end end end \ No newline at end of file diff --git a/lib/fog/rackspace/requests/storage/get_object_https_url.rb b/lib/fog/rackspace/requests/storage/get_object_https_url.rb index 208407bd5b..c81c7f575d 100644 --- a/lib/fog/rackspace/requests/storage/get_object_https_url.rb +++ b/lib/fog/rackspace/requests/storage/get_object_https_url.rb @@ -2,7 +2,7 @@ module Fog module Storage class Rackspace - class Real + module Common # Get an expiring object https url from Cloud Files # @@ -47,7 +47,14 @@ def sig_to_hex(str) h.size == 1 ? "0#{h}" : h }.join end + end + class Mock + include Common + end + + class Real + include Common end end diff --git a/lib/fog/rackspace/requests/storage/head_container.rb b/lib/fog/rackspace/requests/storage/head_container.rb index feca53e381..860a59d113 100644 --- a/lib/fog/rackspace/requests/storage/head_container.rb +++ b/lib/fog/rackspace/requests/storage/head_container.rb @@ -27,6 +27,18 @@ def head_container(container) end end + + class Mock + def head_container(container) + c = mock_container! container + + response = Excon::Response.new + response.status = 204 + response.headers = c.to_headers + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/head_containers.rb b/lib/fog/rackspace/requests/storage/head_containers.rb index e29f73e705..22f1752335 100644 --- a/lib/fog/rackspace/requests/storage/head_containers.rb +++ b/lib/fog/rackspace/requests/storage/head_containers.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # List number of containers and total bytes stored @@ -24,6 +25,24 @@ def head_containers end end + + class Mock + def head_containers + bytes_used = data.values.map { |c| c.bytes_used }.inject(0) { |a, b| a + b } + container_count = data.size + object_count = data.values.map { |c| c.objects.size }.inject(0) { |a, b| a + b } + + response = Excon::Response.new + response.status = 204 + response.headers = { + 'X-Account-Bytes-Used' => bytes_used, + 'X-Account-Container-Count' => container_count, + 'X-Account-Object-Count' => object_count + }.merge(account_meta) + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/head_object.rb b/lib/fog/rackspace/requests/storage/head_object.rb index fdf4a92958..87b834cdd9 100644 --- a/lib/fog/rackspace/requests/storage/head_object.rb +++ b/lib/fog/rackspace/requests/storage/head_object.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Get headers for object @@ -21,6 +22,31 @@ def head_object(container, object) end end + + class Mock + def head_object(container, object) + c = mock_container! container + o = c.mock_object! object + + headers = o.to_headers + + hashes, length = [], 0 + o.each_part do |part| + hashes << part.hash + length += part.bytes_used + end + + headers['Etag'] = "\"#{Digest::MD5.hexdigest(hashes.join)}\"" + headers['Content-Length'] = length.to_s + headers['X-Static-Large-Object'] = "True" if o.static_manifest? + + response = Excon::Response.new + response.status = 200 + response.headers = headers + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/post_set_meta_temp_url_key.rb b/lib/fog/rackspace/requests/storage/post_set_meta_temp_url_key.rb index e6192a17e9..8a6eb02346 100644 --- a/lib/fog/rackspace/requests/storage/post_set_meta_temp_url_key.rb +++ b/lib/fog/rackspace/requests/storage/post_set_meta_temp_url_key.rb @@ -35,6 +35,16 @@ def post_set_meta_temp_url_key(key) end + class Mock + def post_set_meta_temp_url_key(key) + account_meta['X-Account-Meta-Temp-Url-Key'] = key + + response = Excon::Response.new + response.status = 204 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/put_container.rb b/lib/fog/rackspace/requests/storage/put_container.rb index b7b1c94db9..7d2b4674af 100644 --- a/lib/fog/rackspace/requests/storage/put_container.rb +++ b/lib/fog/rackspace/requests/storage/put_container.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Create a new container @@ -21,6 +22,21 @@ def put_container(name, options={}) end end + + class Mock + def put_container(name, options={}) + existed = ! mock_container(name).nil? + container = add_container(name) + options.keys.each do |k| + container.meta[k] = options[k].to_s if k =~ /^X-Container-Meta/ + end + + response = Excon::Response.new + response.status = existed ? 202 : 201 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/put_dynamic_obj_manifest.rb b/lib/fog/rackspace/requests/storage/put_dynamic_obj_manifest.rb index 58dd15ec06..7d5ad2c8e8 100644 --- a/lib/fog/rackspace/requests/storage/put_dynamic_obj_manifest.rb +++ b/lib/fog/rackspace/requests/storage/put_dynamic_obj_manifest.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Create a new dynamic large object manifest @@ -39,6 +40,28 @@ def put_dynamic_obj_manifest(container, object, options = {}) end end + + class Mock + def put_dynamic_obj_manifest(container, object, options = {}) + path = "#{Fog::Rackspace.escape(container)}/#{Fog::Rackspace.escape(object)}" + + # Escape the X-Object-Manifest header to match. + explicit_manifest = options['X-Object-Manifest'] + if explicit_manifest + parts = explicit_manifest.split('/', 2) + explicit_manifest = parts.map { |p| Fog::Rackspace.escape p }.join('/') + end + + c = mock_container! container + o = c.add_object object, '' + o.meta['X-Object-Manifest'] = explicit_manifest || path + + response = Excon::Response.new + response.status = 201 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/put_object.rb b/lib/fog/rackspace/requests/storage/put_object.rb index 394ddc0def..8c1c18950a 100644 --- a/lib/fog/rackspace/requests/storage/put_object.rb +++ b/lib/fog/rackspace/requests/storage/put_object.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Create a new object @@ -36,6 +37,44 @@ def put_object(container, object, data, options = {}, &block) request(params) end end + + class Mock + HeaderOptions = %w{ + Content-Type Access-Control-Allow-Origin Origin Content-Disposition + Etag Content-Encoding + }.freeze + + def put_object(container, object, data, options = {}, &block) + c = mock_container! container + + if block_given? + data = "" + loop do + chunk = yield + break if chunk.empty? + data << chunk + end + end + + o = c.add_object object, data + options.keys.each do |k| + o.meta[k] = options[k].to_s if k =~ /^X-Object-Meta/ + o.meta[k] = options[k] if HeaderOptions.include? k + end + + # Validate the provided Etag + etag = o.meta['Etag'] + if etag && etag != o.hash + c.remove_object object + raise Fog::Storage::Rackspace::ServiceError.new + end + + response = Excon::Response.new + response.status = 201 + response + end + end + end end end diff --git a/lib/fog/rackspace/requests/storage/put_object_manifest.rb b/lib/fog/rackspace/requests/storage/put_object_manifest.rb index 9fe419f098..6ed5448ac6 100644 --- a/lib/fog/rackspace/requests/storage/put_object_manifest.rb +++ b/lib/fog/rackspace/requests/storage/put_object_manifest.rb @@ -1,16 +1,24 @@ module Fog module Storage class Rackspace - class Real + module Common # Create a new dynamic large object manifest # # This is an alias for {#put_dynamic_obj_manifest} for backward compatibility. def put_object_manifest(container, object, options = {}) put_dynamic_obj_manifest(container, object, options) end + end + + class Real + include Common + end + class Mock + include Common end + end end end diff --git a/lib/fog/rackspace/requests/storage/put_static_obj_manifest.rb b/lib/fog/rackspace/requests/storage/put_static_obj_manifest.rb index 1b9df0f3cc..12cb5b1fcf 100644 --- a/lib/fog/rackspace/requests/storage/put_static_obj_manifest.rb +++ b/lib/fog/rackspace/requests/storage/put_static_obj_manifest.rb @@ -1,6 +1,7 @@ module Fog module Storage class Rackspace + class Real # Create a new static large object manifest. @@ -53,6 +54,53 @@ def put_static_obj_manifest(container, object, segments, options = {}) end end + + class Mock + def put_static_obj_manifest(container, object, segments, options = {}) + c = mock_container! container + + # Verify paths. + errors = [] + segments.each do |segment| + cname, oname = segment[:path].split('/', 2) + target_container = mock_container(cname) + + raise Fog::Storage::Rackspace::NotFound.new unless target_container + + target_object = target_container.mock_object oname + unless target_object + errors << [segment[:path], '404 Not Found'] + next + end + + unless target_object.hash == segment[:etag] + errors << [segment[:path], 'Etag Mismatch'] + end + + unless target_object.bytes_used == segment[:size_bytes] + errors << [segment[:path], 'Size Mismatch'] + end + end + + unless errors.empty? + response = Excon::Response.new + response.status = 400 + response.body = Fog::JSON.encode({ 'Errors' => errors }) + + error = Excon::Errors.status_error({}, response) + raise Fog::Storage::Rackspace::BadRequest.slurp(error) + end + + data = Fog::JSON.encode(segments) + o = c.add_object object, data + o.static_manifest = true + + response = Excon::Response.new + response.status = 201 + response + end + end + end end end diff --git a/lib/fog/rackspace/storage.rb b/lib/fog/rackspace/storage.rb index 8ad05ac858..9ecf130794 100644 --- a/lib/fog/rackspace/storage.rb +++ b/lib/fog/rackspace/storage.rb @@ -42,7 +42,21 @@ class BadRequest < Fog::Rackspace::Errors::BadRequest; end request :put_static_obj_manifest request :post_set_meta_temp_url_key - module Utils + module Common + def apply_options(options) + @rackspace_api_key = options[:rackspace_api_key] + @rackspace_username = options[:rackspace_username] + @rackspace_cdn_ssl = options[:rackspace_cdn_ssl] + @rackspace_auth_url = options[:rackspace_auth_url] + @rackspace_servicenet = options[:rackspace_servicenet] + @rackspace_auth_token = options[:rackspace_auth_token] + @rackspace_storage_url = options[:rackspace_storage_url] + @rackspace_cdn_url = options[:rackspace_cdn_url] + @rackspace_region = options[:rackspace_region] || :dfw + @rackspace_temp_url_key = options[:rackspace_temp_url_key] + @rackspace_must_reauthenticate = false + @connection_options = options[:connection_options] || {} + end def cdn @cdn ||= Fog::CDN.new( @@ -59,10 +73,249 @@ def cdn end end + def service_net? + @rackspace_servicenet == true + end + + def authenticate + if @rackspace_must_reauthenticate || @rackspace_auth_token.nil? + options = { + :rackspace_api_key => @rackspace_api_key, + :rackspace_username => @rackspace_username, + :rackspace_auth_url => @rackspace_auth_url, + :connection_options => @connection_options + } + super(options) + else + @auth_token = @rackspace_auth_token + @uri = URI.parse(@rackspace_storage_url) + end + end + + def service_name + :cloudFiles + end + + def request_id_header + "X-Trans-Id" + end + + def region + @rackspace_region + end + + def endpoint_uri(service_endpoint_url=nil) + return @uri if @uri + super(@rackspace_storage_url || service_endpoint_url, :rackspace_storage_url) + end + + # Return Account Details + # @return [Fog::Storage::Rackspace::Account] account details object + def account + account = Fog::Storage::Rackspace::Account.new(:service => self) + account.reload + end end class Mock < Fog::Rackspace::Service - include Utils + include Common + + # An in-memory container for use with Rackspace storage mocks. Includes + # many `objects` mapped by (escaped) object name. Tracks container + # metadata. + class MockContainer + attr_reader :objects, :meta, :service + + # Create a new container. Generally, you should call + # {Fog::Rackspace::Storage#add_container} instead. + def initialize(service) + @service = service + @objects, @meta = {}, {} + end + + # Determine if this container contains any MockObjects or not. + # + # @return [Boolean] + def empty? + @objects.empty? + end + + # Total sizes of all objects added to this container. + # + # @return [Integer] The number of bytes occupied by each contained + # object. + def bytes_used + @objects.values.map { |o| o.bytes_used }.inject(0) { |a, b| a + b } + end + + # Render the HTTP headers that would be associated with this + # container. + # + # @return [Hash] Any metadata supplied to this + # container, plus additional headers indicating the container's + # size. + def to_headers + @meta.merge({ + 'X-Container-Object-Count' => @objects.size, + 'X-Container-Bytes-Used' => bytes_used + }) + end + + # Access a MockObject within this container by (unescaped) name. + # + # @return [MockObject, nil] Return the MockObject at this name if + # one exists; otherwise, `nil`. + def mock_object(name) + @objects[Fog::Rackspace.escape(name)] + end + + # Access a MockObject with a specific name, raising a + # `Fog::Storage::Rackspace::NotFound` exception if none are present. + # + # @param name [String] (Unescaped) object name. + # @return [MockObject] The object within this container with the + # specified name. + def mock_object!(name) + mock_object(name) or raise Fog::Storage::Rackspace::NotFound.new + end + + # Add a new MockObject to this container. An existing object with + # the same name will be overwritten. + # + # @param name [String] The object's name, unescaped. + # @param data [String, #read] The contents of the object. + def add_object(name, data) + @objects[Fog::Rackspace.escape(name)] = MockObject.new(data, service) + end + + # Remove a MockObject from the container by name. No effect if the + # object is not present beforehand. + # + # @param name [String] The (unescaped) object name to remove. + def remove_object(name) + @objects.delete Fog::Rackspace.escape(name) + end + end + + # An in-memory Swift object. + class MockObject + attr_reader :hash, :bytes_used, :content_type, :last_modified + attr_reader :body, :meta, :service + attr_accessor :static_manifest + + # Construct a new object. Generally, you should call + # {MockContainer#add_object} instead of instantiating these directly. + def initialize(data, service) + data = Fog::Storage.parse_data(data) + @service = service + + @bytes_used = data[:headers]['Content-Length'] + @content_type = data[:headers]['Content-Type'] + if data[:body].respond_to? :read + @body = data[:body].read + else + @body = data[:body] + end + @last_modified = Time.now.utc + @hash = Digest::MD5.hexdigest(@body) + @meta = {} + @static_manifest = false + end + + # Determine if this object was created as a static large object + # manifest. + # + # @return [Boolean] + def static_manifest? + @static_manifest + end + + # Determine if this object has the metadata header that marks it as a + # dynamic large object manifest. + # + # @return [Boolean] + def dynamic_manifest? + ! large_object_prefix.nil? + end + + # Iterate through each MockObject that contains a part of the data for + # this logical object. In the normal case, this will only yield the + # receiver directly. For dynamic and static large object manifests, + # however, this call will yield each MockObject that contains a part + # of the whole, in sequence. + # + # Manifests that refer to containers or objects that don't exist will + # skip those sections and log a warning, instead. + # + # @yield [MockObject] Each object that holds a part of this logical + # object. + def each_part + case + when dynamic_manifest? + # Concatenate the contents and sizes of each matching object. + # Note that cname and oprefix are already escaped. + cname, oprefix = large_object_prefix.split('/', 2) + + target_container = service.data[cname] + if target_container + all = target_container.objects.keys + matching = all.select { |name| name.start_with? oprefix } + keys = matching.sort + + keys.each do |name| + yield target_container.objects[name] + end + else + Fog::Logger.warning "Invalid container in dynamic object manifest: #{cname}" + yield self + end + when static_manifest? + Fog::JSON.decode(body).each do |segment| + cname, oname = segment['path'].split('/', 2) + + cont = service.mock_container cname + unless cont + Fog::Logger.warning "Invalid container in static object manifest: #{cname}" + next + end + + obj = cont.mock_object oname + unless obj + Fog::Logger.warning "Invalid object in static object manifest: #{oname}" + next + end + + yield obj + end + else + yield self + end + end + + # Access the object name prefix that controls which other objects + # comprise a dynamic large object. + # + # @return [String, nil] The object name prefix, or `nil` if none is + # present. + def large_object_prefix + @meta['X-Object-Manifest'] + end + + # Construct the fake HTTP headers that should be returned on requests + # targetting this object. Includes computed `Content-Type`, + # `Content-Length`, `Last-Modified` and `ETag` headers in addition to + # whatever metadata has been associated with this object manually. + # + # @return [Hash] Header values stored in a Hash. + def to_headers + { + 'Content-Type' => @content_type, + 'Content-Length' => @bytes_used, + 'Last-Modified' => @last_modified.strftime('%a, %b %d %Y %H:%M:%S %Z'), + 'ETag' => @hash + }.merge(@meta) + end + end def self.data @data ||= Hash.new do |hash, key| @@ -70,56 +323,98 @@ def self.data end end + # Access or create account-wide metadata. + # + # @return [Hash] A metadata hash pre-populated with + # a (fake) temp URL key. + def self.account_meta + @account_meta ||= Hash.new do |hash, key| + hash[key] = { + 'X-Account-Meta-Temp-Url-Key' => Fog::Mock.random_hex(32) + } + end + end + def self.reset @data = nil + @account_meta = nil end def initialize(options={}) - @rackspace_api_key = options[:rackspace_api_key] - @rackspace_username = options[:rackspace_username] - @rackspace_cdn_ssl = options[:rackspace_cdn_ssl] + apply_options(options) + authenticate + endpoint_uri end def data self.class.data[@rackspace_username] end + def account_meta + self.class.account_meta[@rackspace_username] + end + def reset_data self.class.data.delete(@rackspace_username) end - def service_name - :cloudFiles + # Access a MockContainer with the specified name, if one exists. + # + # @param cname [String] The (unescaped) container name. + # @return [MockContainer, nil] The named MockContainer, or `nil` if + # none exist. + def mock_container(cname) + data[Fog::Rackspace.escape(cname)] end - def region - @rackspace_region + # Access a MockContainer with the specified name, raising a + # {Fog::Storage::Rackspace::NotFound} exception if none exist. + # + # @param cname [String] The (unescaped) container name. + # @throws [Fog::Storage::Rackspace::NotFound] If no container with the + # given name exists. + # @return [MockContainer] The existing MockContainer. + def mock_container!(cname) + mock_container(cname) or raise Fog::Storage::Rackspace::NotFound.new + end + + # Create and add a new, empty MockContainer with the given name. An + # existing container with the same name will be replaced. + # + # @param cname [String] The (unescaped) container name. + # @return [MockContainer] The container that was added. + def add_container(cname) + data[Fog::Rackspace.escape(cname)] = MockContainer.new(self) + end + + # Remove a MockContainer with the specified name. No-op if the + # container does not exist. + # + # @param cname [String] The (unescaped) container name. + def remove_container(cname) + data.delete Fog::Rackspace.escape(cname) end def ssl? !!@rackspace_cdn_ssl end + private + + def authenticate_v1(options) + uuid = Fog::Rackspace::MockData.uuid + endpoint_uri "https://storage101.#{region}1.clouddrive.com/v1/MockCloudFS_#{uuid}" + @auth_token = Fog::Mock.random_hex(32) + end end class Real < Fog::Rackspace::Service - include Utils + include Common attr_reader :rackspace_cdn_ssl def initialize(options={}) - @rackspace_api_key = options[:rackspace_api_key] - @rackspace_username = options[:rackspace_username] - @rackspace_cdn_ssl = options[:rackspace_cdn_ssl] - @rackspace_auth_url = options[:rackspace_auth_url] - @rackspace_servicenet = options[:rackspace_servicenet] - @rackspace_auth_token = options[:rackspace_auth_token] - @rackspace_storage_url = options[:rackspace_storage_url] - @rackspace_cdn_url = options[:rackspace_cdn_url] - @rackspace_region = options[:rackspace_region] || :dfw - @rackspace_temp_url_key = options[:rackspace_temp_url_key] - @rackspace_must_reauthenticate = false - @connection_options = options[:connection_options] || {} + apply_options(options) authenticate @persistent = options[:persistent] || false @@ -127,13 +422,6 @@ def initialize(options={}) @connection = Fog::Connection.new(endpoint_uri.to_s, @persistent, @connection_options) end - # Return Account Details - # @return [Fog::Storage::Rackspace::Account] account details object - def account - account = Fog::Storage::Rackspace::Account.new(:service => self) - account.reload - end - # Using SSL? # @return [Boolean] return true if service is returning SSL-Secured URLs in public_url methods # @see Directory#public_url @@ -158,42 +446,6 @@ def request(params, parse_json = true) raise ServiceError.slurp(error, self) end - def service_net? - @rackspace_servicenet == true - end - - def authenticate - if @rackspace_must_reauthenticate || @rackspace_auth_token.nil? - options = { - :rackspace_api_key => @rackspace_api_key, - :rackspace_username => @rackspace_username, - :rackspace_auth_url => @rackspace_auth_url, - :connection_options => @connection_options - } - super(options) - else - @auth_token = @rackspace_auth_token - @uri = URI.parse(@rackspace_storage_url) - end - end - - def service_name - :cloudFiles - end - - def request_id_header - "X-Trans-Id" - end - - def region - @rackspace_region - end - - def endpoint_uri(service_endpoint_url=nil) - return @uri if @uri - super(@rackspace_storage_url || service_endpoint_url, :rackspace_storage_url) - end - private def authenticate_v1(options) @@ -201,8 +453,8 @@ def authenticate_v1(options) endpoint_uri credentials['X-Storage-Url'] @auth_token = credentials['X-Auth-Token'] end - end + end end end diff --git a/tests/rackspace/identity_tests.rb b/tests/rackspace/identity_tests.rb index 28171825b8..68b6ad77fc 100644 --- a/tests/rackspace/identity_tests.rb +++ b/tests/rackspace/identity_tests.rb @@ -1,8 +1,6 @@ Shindo.tests('Fog::Rackspace::Identity', ['rackspace']) do tests('current authentication') do - pending if Fog.mocking? - tests('variables populated').returns(200) do @service = Fog::Rackspace::Identity.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0', :connection_options => {:ssl_verify_peer => true} returns(true, "auth token populated") { !@service.auth_token.nil? } @@ -14,8 +12,6 @@ end tests('reauthentication') do - pending if Fog.mocking? - tests('should reauth with valid credentials') do @service = Fog::Rackspace::Identity.new :rackspace_region => :ord returns(true, "auth token populated") { !@service.auth_token.nil? } diff --git a/tests/rackspace/models/storage/account_tests.rb b/tests/rackspace/models/storage/account_tests.rb index 02d0e2a9dc..fcc9fa7f82 100644 --- a/tests/rackspace/models/storage/account_tests.rb +++ b/tests/rackspace/models/storage/account_tests.rb @@ -1,7 +1,5 @@ Shindo.tests('Fog::Rackspace::Storage | account', ['rackspace']) do - pending if Fog.mocking? - @account = Fog::Storage[:rackspace].account tests('load') do diff --git a/tests/rackspace/models/storage/directories_tests.rb b/tests/rackspace/models/storage/directories_tests.rb index b1f94dec04..85eca32de2 100644 --- a/tests/rackspace/models/storage/directories_tests.rb +++ b/tests/rackspace/models/storage/directories_tests.rb @@ -1,10 +1,7 @@ Shindo.tests('Fog::Rackspace::Storage | directories', ['rackspace']) do - pending if Fog.mocking? - @service = Fog::Storage[:rackspace] - begin @name = "fog-directories-test-#{Time.now.to_i.to_s}" @filename = 'lorem.txt' diff --git a/tests/rackspace/models/storage/directory_tests.rb b/tests/rackspace/models/storage/directory_tests.rb index 6d881762cc..c4494e7978 100644 --- a/tests/rackspace/models/storage/directory_tests.rb +++ b/tests/rackspace/models/storage/directory_tests.rb @@ -1,7 +1,5 @@ Shindo.tests('Fog::Rackspace::Storage | directory', ['rackspace']) do - pending if Fog.mocking? - @service = Fog::Storage[:rackspace] def container_meta_attributes @@ -92,9 +90,8 @@ def container_meta_attributes directory_attributes[:metadata] = {:draft => 'true'} - tests('metadata') do - pending if Fog.mocking? - + tests('metadata') do + model_tests(@service.directories, directory_attributes, Fog.mocking?) do tests('sets metadata on create').returns('true') do @instance.metadata.data diff --git a/tests/rackspace/models/storage/file_tests.rb b/tests/rackspace/models/storage/file_tests.rb index 4a399b1ce9..9b942d4fdf 100644 --- a/tests/rackspace/models/storage/file_tests.rb +++ b/tests/rackspace/models/storage/file_tests.rb @@ -30,8 +30,6 @@ end end - pending if Fog.mocking? - def object_attributes(file=@instance) @instance.service.head_object(@directory.key, file.key).headers end diff --git a/tests/rackspace/models/storage/files_tests.rb b/tests/rackspace/models/storage/files_tests.rb index 288ead3347..0124bbf4d0 100644 --- a/tests/rackspace/models/storage/files_tests.rb +++ b/tests/rackspace/models/storage/files_tests.rb @@ -12,8 +12,7 @@ tests('success') do - pending if Fog.mocking? - collection_tests(Fog::Storage[:rackspace].directories.create(directory_attributes).files, file_attributes, false) + collection_tests(Fog::Storage[:rackspace].directories.create(directory_attributes).files, file_attributes, Fog.mocking?) @service = Fog::Storage.new :provider => 'rackspace', :rackspace_temp_url_key => "my_secret" @@ -25,13 +24,11 @@ end tests("#get_http_url('#{@directory.key}')").succeeds do - pending if Fog.mocking? expire_time = Time.now + 3600 @directory.files.get_http_url(@file.key, expire_time) end tests("#get_https_url('#{@directory.key}', '#{@file.key}')").succeeds do - pending if Fog.mocking? expire_time = Time.now + 3600 @directory.files.get_https_url(@file.key, expire_time) end diff --git a/tests/rackspace/requests/identity/token_tests.rb b/tests/rackspace/requests/identity/token_tests.rb index 8b4ee6419b..29a4c2bdba 100644 --- a/tests/rackspace/requests/identity/token_tests.rb +++ b/tests/rackspace/requests/identity/token_tests.rb @@ -1,7 +1,4 @@ Shindo.tests('Fog::Rackspace::Identity | tokens', ['rackspace']) do - - pending if Fog.mock? - ROLE_FORMAT = { 'id' => String, 'name' => String, @@ -55,6 +52,7 @@ end tests('uses connection options').returns(true) do + pending if Fog.mocking? identity_service = Fog::Rackspace::Identity.new(:connection_options => { :ssl_verify_peer => true }) connection = identity_service.instance_variable_get("@connection") diff --git a/tests/rackspace/requests/storage/account_tests.rb b/tests/rackspace/requests/storage/account_tests.rb index da69e7f6e2..3925107bcc 100644 --- a/tests/rackspace/requests/storage/account_tests.rb +++ b/tests/rackspace/requests/storage/account_tests.rb @@ -3,7 +3,6 @@ tests('success') do tests("#post_set_meta_temp_url_key('super_secret_key')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].post_set_meta_temp_url_key('super_secret_key') end diff --git a/tests/rackspace/requests/storage/container_tests.rb b/tests/rackspace/requests/storage/container_tests.rb index 1b46bde715..1429d2aaed 100644 --- a/tests/rackspace/requests/storage/container_tests.rb +++ b/tests/rackspace/requests/storage/container_tests.rb @@ -1,6 +1,12 @@ Shindo.tests('Fog::Storage[:rackspace] | container requests', ["rackspace"]) do - @container_format = [String] + @container_format = [{ + 'hash' => String, + 'last_modified' => String, + 'bytes' => Integer, + 'name' => String, + 'content_type' => String + }] @containers_format = [{ 'bytes' => Integer, @@ -11,39 +17,32 @@ tests('success') do tests("#put_container('fogcontainertests', {})").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].put_container('fogcontainertests') end tests("#put_container('fogcontainertests', 'X-Container-Meta-Color'=>'green')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].put_container('fogcontainertests', 'X-Container-Meta-Color'=>'green') response = Fog::Storage[:rackspace].head_container('fogcontainertests') returns('green') { response.headers['X-Container-Meta-Color'] } end tests("#get_container('fogcontainertests')").formats(@container_format) do - pending if Fog.mocking? Fog::Storage[:rackspace].get_container('fogcontainertests').body end tests("#get_containers").formats(@containers_format) do - pending if Fog.mocking? Fog::Storage[:rackspace].get_containers.body end tests("#head_container('fogcontainertests')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].head_container('fogcontainertests') end tests("#head_containers").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].head_containers end tests("#delete_container('fogcontainertests')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].delete_container('fogcontainertests') end @@ -52,17 +51,14 @@ tests('failure') do tests("#get_container('fognoncontainer')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].get_container('fognoncontainer') end tests("#head_container('fognoncontainer')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].head_container('fognoncontainer') end tests("#delete_container('fognoncontainer')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].delete_container('fognoncontainer') end diff --git a/tests/rackspace/requests/storage/large_object_tests.rb b/tests/rackspace/requests/storage/large_object_tests.rb index aa122b0494..99630c0a89 100644 --- a/tests/rackspace/requests/storage/large_object_tests.rb +++ b/tests/rackspace/requests/storage/large_object_tests.rb @@ -1,52 +1,47 @@ Shindo.tests('Fog::Storage[:rackspace] | large object requests', ['rackspace']) do - unless Fog.mocking? - @directory = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests') - @directory2 = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests2') - @segments = { - :a => { - :container => @directory.identity, - :name => 'fog_large_object/a', - :data => 'a' * (1024**2 + 10), - :size => 1024**2 + 10, - :etag => 'c2e97007d59f0c19b850debdcb80cca5' - }, - :b => { - :container => @directory.identity, - :name => 'fog_large_object/b', - :data => 'b' * (1024**2 + 20), - :size => 1024**2 + 20, - :etag => 'd35f50622a1259daad75ff7d5512c7ef' - }, - :c => { - :container => @directory.identity, - :name => 'fog_large_object2/a', - :data => 'c' * (1024**2 + 30), - :size => 1024**2 + 30, - :etag => '901d3531a87d188041d4d5b43cb464c1' - }, - :d => { - :container => @directory2.identity, - :name => 'fog_large_object2/b', - :data => 'd' * (1024**2 + 40), - :size => 1024**2 + 40, - :etag => '350c0e00525198813920a157df185c8d' - } + @directory = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests') + @directory2 = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests2') + @segments = { + :a => { + :container => @directory.identity, + :name => 'fog_large_object/a', + :data => 'a' * (1024**2 + 10), + :size => 1024**2 + 10, + :etag => 'c2e97007d59f0c19b850debdcb80cca5' + }, + :b => { + :container => @directory.identity, + :name => 'fog_large_object/b', + :data => 'b' * (1024**2 + 20), + :size => 1024**2 + 20, + :etag => 'd35f50622a1259daad75ff7d5512c7ef' + }, + :c => { + :container => @directory.identity, + :name => 'fog_large_object2/a', + :data => 'c' * (1024**2 + 30), + :size => 1024**2 + 30, + :etag => '901d3531a87d188041d4d5b43cb464c1' + }, + :d => { + :container => @directory2.identity, + :name => 'fog_large_object2/b', + :data => 'd' * (1024**2 + 40), + :size => 1024**2 + 40, + :etag => '350c0e00525198813920a157df185c8d' } - end + } tests('success') do tests('upload test segments').succeeds do - pending if Fog.mocking? - @segments.each_value do |segment| Fog::Storage[:rackspace].put_object(segment[:container], segment[:name], segment[:data]) end end tests('dynamic large object requests') do - pending if Fog.mocking? tests('#put_object_manifest alias').succeeds do Fog::Storage[:rackspace].put_object_manifest(@directory.identity, 'fog_large_object') @@ -110,7 +105,6 @@ end tests('static large object requests') do - pending if Fog.mocking? tests('single container') do @@ -209,7 +203,6 @@ tests('failure') do tests('dynamic large object requests') do - pending if Fog.mocking? tests('#put_dynamic_obj_manifest with missing container').raises(Fog::Storage::Rackspace::NotFound) do Fog::Storage[:rackspace].put_dynamic_obj_manifest('fognoncontainer', 'fog_large_object') @@ -218,7 +211,6 @@ end tests('static large object requests') do - pending if Fog.mocking? tests('upload test segments').succeeds do Fog::Storage[:rackspace].put_object(@segments[:a][:container], @segments[:a][:name], @segments[:a][:data]) @@ -358,8 +350,6 @@ end - unless Fog.mocking? - @directory.destroy - @directory2.destroy - end + @directory.destroy + @directory2.destroy end diff --git a/tests/rackspace/requests/storage/object_tests.rb b/tests/rackspace/requests/storage/object_tests.rb index 252c61ea09..fdfee07517 100644 --- a/tests/rackspace/requests/storage/object_tests.rb +++ b/tests/rackspace/requests/storage/object_tests.rb @@ -1,8 +1,6 @@ Shindo.tests('Fog::Storage[:rackspace] | object requests', ["rackspace"]) do - unless Fog.mocking? - @directory = Fog::Storage[:rackspace].directories.create(:key => 'fogobjecttests') - end + @directory = Fog::Storage[:rackspace].directories.create(:key => 'fogobjecttests') module RackspaceStorageHelpers def override_path(path) @@ -13,17 +11,14 @@ def override_path(path) tests('success') do tests("#put_object('fogobjecttests', 'fog_object')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].put_object('fogobjecttests', 'fog_object', lorem_file) end tests("#get_object('fogobjectests', 'fog_object')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].get_object('fogobjecttests', 'fog_object').body == lorem_file.read end tests("#get_object('fogobjecttests', 'fog_object', &block)").succeeds do - pending if Fog.mocking? data = '' Fog::Storage[:rackspace].get_object('fogobjecttests', 'fog_object') do |chunk, remaining_bytes, total_bytes| data << chunk @@ -32,18 +27,15 @@ def override_path(path) end tests("#head_object('fogobjectests', 'fog_object')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].head_object('fogobjecttests', 'fog_object') end tests("#delete_object('fogobjecttests', 'fog_object')").succeeds do - pending if Fog.mocking? Fog::Storage[:rackspace].delete_object('fogobjecttests', 'fog_object') end # an object key with no special characters tests("#get_object_http_url('fogobjecttests', 'fog_object','expiration timestamp')").succeeds do - pending if Fog.mocking? expires_at = 1344149532 # 2012-08-05 16:52:12 +1000 storage = Fog::Storage::Rackspace.new(:rackspace_temp_url_key => "super_secret") storage.extend RackspaceStorageHelpers @@ -54,7 +46,6 @@ def override_path(path) # an object key with no special characters tests("#get_object_https_url('fogobjecttests', 'fog_object','expiration timestamp')").succeeds do - pending if Fog.mocking? expires_at = 1344149532 # 2012-08-05 16:52:12 +1000 storage = Fog::Storage::Rackspace.new(:rackspace_temp_url_key => "super_secret") storage.extend RackspaceStorageHelpers @@ -65,7 +56,6 @@ def override_path(path) # an object key nested under a / tests("#get_object_https_url('fogobjecttests', 'fog/object','expiration timestamp')").succeeds do - pending if Fog.mocking? expires_at = 1344149532 # 2012-08-05 16:52:12 +1000 storage = Fog::Storage::Rackspace.new(:rackspace_temp_url_key => "super_secret") storage.extend RackspaceStorageHelpers @@ -76,7 +66,6 @@ def override_path(path) # an object key containing a - tests("#get_object_https_url('fogobjecttests', 'fog-object','expiration timestamp')").succeeds do - pending if Fog.mocking? expires_at = 1344149532 # 2012-08-05 16:52:12 +1000 storage = Fog::Storage::Rackspace.new(:rackspace_temp_url_key => "super_secret") storage.extend RackspaceStorageHelpers @@ -86,8 +75,6 @@ def override_path(path) end tests("put_object with block") do - pending if Fog.mocking? - tests("#put_object('fogobjecttests', 'fog_object', &block)").succeeds do begin file = lorem_file @@ -110,8 +97,6 @@ def override_path(path) end tests('#delete_multiple_objects') do - pending if Fog.mocking? - Fog::Storage[:rackspace].put_object('fogobjecttests', 'fog_object', lorem_file) Fog::Storage[:rackspace].put_object('fogobjecttests', 'fog_object2', lorem_file) Fog::Storage[:rackspace].directories.create(:key => 'fogobjecttests2') @@ -139,38 +124,30 @@ def override_path(path) tests('failure') do tests("#get_object('fogobjecttests', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].get_object('fogobjecttests', 'fog_non_object') end tests("#get_object('fognoncontainer', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].get_object('fognoncontainer', 'fog_non_object') end tests("#head_object('fogobjecttests', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].head_object('fogobjecttests', 'fog_non_object') end tests("#head_object('fognoncontainer', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].head_object('fognoncontainer', 'fog_non_object') end tests("#delete_object('fogobjecttests', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].delete_object('fogobjecttests', 'fog_non_object') end tests("#delete_object('fognoncontainer', 'fog_non_object')").raises(Fog::Storage::Rackspace::NotFound) do - pending if Fog.mocking? Fog::Storage[:rackspace].delete_object('fognoncontainer', 'fog_non_object') end tests('#delete_multiple_objects') do - pending if Fog.mocking? - expected = { "Number Not Found" => 2, "Response Status" => "200 OK", @@ -206,8 +183,6 @@ def override_path(path) end - unless Fog.mocking? - @directory.destroy - end + @directory.destroy end diff --git a/tests/rackspace/storage_tests.rb b/tests/rackspace/storage_tests.rb index 964dcece68..1618335cfb 100644 --- a/tests/rackspace/storage_tests.rb +++ b/tests/rackspace/storage_tests.rb @@ -7,23 +7,21 @@ def assert_method(url, method) tests('#authentication_method') do @service = Fog::Storage::Rackspace.new - + assert_method nil, :authenticate_v2 assert_method 'https://identity.api.rackspacecloud.com', :authenticate_v1 assert_method 'https://identity.api.rackspacecloud.com/v1', :authenticate_v1 - assert_method 'https://identity.api.rackspacecloud.com/v1.1', :authenticate_v1 + assert_method 'https://identity.api.rackspacecloud.com/v1.1', :authenticate_v1 assert_method 'https://identity.api.rackspacecloud.com/v2.0', :authenticate_v2 - - assert_method 'https://lon.identity.api.rackspacecloud.com', :authenticate_v1 + + assert_method 'https://lon.identity.api.rackspacecloud.com', :authenticate_v1 assert_method 'https://lon.identity.api.rackspacecloud.com/v1', :authenticate_v1 assert_method 'https://lon.identity.api.rackspacecloud.com/v1.1', :authenticate_v1 assert_method 'https://lon.identity.api.rackspacecloud.com/v2.0', :authenticate_v2 end - - tests('authentication v1') do - pending if Fog.mocking? + tests('authentication v1') do tests('variables populated').succeeds do @service = Fog::Storage::Rackspace.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v1.0' returns(true, "auth token populated") { !@service.send(:auth_token).nil? } @@ -32,7 +30,7 @@ def assert_method(url, method) @service.head_containers end tests('custom endpoint') do - @service = Fog::Storage::Rackspace.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v1.0', + @service = Fog::Storage::Rackspace.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v1.0', :rackspace_storage_url => 'https://my-custom-endpoint.com' returns(false, "auth token populated") { @service.send(:auth_token).nil? } returns(true, "uses custom endpoint") { (@service.instance_variable_get("@uri").host =~ /my-custom-endpoint\.com/) != nil } @@ -40,7 +38,6 @@ def assert_method(url, method) end tests('authentation v2') do - pending if Fog.mocking? tests('variables populated').succeeds do @service = Fog::Storage::Rackspace.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0', :connection_options => { :ssl_verify_peer => true } @@ -71,10 +68,9 @@ def assert_method(url, method) returns(true, "uses custom endpoint") { (@service.instance_variable_get("@uri").host =~ /my-custom-endpoint\.com/) != nil } end end - + tests('default auth') do - pending if Fog.mocking? - + tests('no params').succeeds do @service = Fog::Storage::Rackspace.new :rackspace_region => nil returns(true, "auth token populated") { !@service.send(:auth_token).nil? } @@ -100,7 +96,6 @@ def assert_method(url, method) end tests('reauthentication') do - pending if Fog.mocking? tests('should reauth with valid credentials') do @service = Fog::Storage::Rackspace.new @@ -114,8 +109,7 @@ def assert_method(url, method) end tests('account').succeeds do - pending if Fog.mocking? - Fog::Storage[:rackspace].account + Fog::Storage[:rackspace].account end tests('ssl') do