lib/fog/rackspace/requests/identity/create_token.rb in fog-1.19.0 vs lib/fog/rackspace/requests/identity/create_token.rb in fog-1.20.0
- old
+ new
@@ -18,8 +18,200 @@
:method => 'POST',
:path => 'tokens'
)
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