Merge remote-tracking branch 'upstream/develop' into development

This commit is contained in:
Alfonso Juan Dillera
2013-09-03 11:37:16 +08:00
14 changed files with 503 additions and 579 deletions

View File

@@ -3,7 +3,6 @@ require 'active_support/inflector'
require 'faraday'
require "aviator/version"
require "aviator/core/dsl"
require "aviator/core/request"
require "aviator/core/response"
require "aviator/core/service"

View File

@@ -1,37 +0,0 @@
module Aviator
class << self
def define_request(request_name, &block)
class_obj = Class.new(Request, &block)
build_or_get_request_class(
Aviator,
class_obj,
class_obj.provider,
class_obj.service,
class_obj.api_version,
class_obj.endpoint_type,
request_name
)
end
private
def build_or_get_request_class(base, obj, *hierarchy)
const_name = hierarchy.shift.to_s.camelize
const = if base.const_defined?(const_name)
base.const_get(const_name)
else
base.const_set(const_name, (hierarchy.empty? ? obj : Module.new))
end
hierarchy.empty? ? const : build_or_get_request_class(const, obj, *hierarchy)
end
end # class << self
end # module Aviator

View File

@@ -1,5 +1,40 @@
module Aviator
class << self
def define_request(request_name, &block)
class_obj = Class.new(Request, &block)
set_class_name(
Aviator,
class_obj,
class_obj.provider,
class_obj.service,
class_obj.api_version,
class_obj.endpoint_type,
request_name
)
end
private
def set_class_name(base, obj, *hierarchy)
const_name = hierarchy.shift.to_s.camelize
const = if base.const_defined?(const_name)
base.const_get(const_name)
else
base.const_set(const_name, (hierarchy.empty? ? obj : Module.new))
end
hierarchy.empty? ? const : set_class_name(const, obj, *hierarchy)
end
end # class << self
class Request
class ApiVersionNotDefinedError < StandardError
@@ -40,31 +75,16 @@ module Aviator
end
def api_version
self.class.api_version
end
def body?
self.class.body?
end
def endpoint_type
self.class.endpoint_type
end
def headers?
self.class.headers?
end
def http_method
self.class.http_method
end
def links
self.class.links
end
@@ -80,11 +100,6 @@ module Aviator
end
def querystring?
self.class.querystring?
end
def required_params
self.class.required_params
end
@@ -100,6 +115,11 @@ module Aviator
end
def querystring?
self.class.querystring?
end
def url?
self.class.url?
end
@@ -123,22 +143,8 @@ module Aviator
# within the class and because they don't change between instances anyway.
class << self
def anonymous
@anonymous = true
end
def anonymous?
@anonymous == true
end
def api_version(value=nil)
if value
@api_version = value
else
@api_version
end
respond_to?(:anonymous) && anonymous == true
end
@@ -147,33 +153,10 @@ module Aviator
end
def endpoint_type(value=nil)
if value
@endpoint_type = value
else
@endpoint_type
end
end
def headers?
instance_methods.include? :headers
end
def http_method(value=nil)
if value
@http_method = value
else
@http_method
end
end
def link_to(rel, href)
links << { rel: rel, href: href }
end
def links
@links ||= []
@@ -191,15 +174,6 @@ module Aviator
end
def provider(value=nil)
if value
@provider = value
else
@provider
end
end
def optional_params
@optional_params ||= []
end
@@ -208,20 +182,11 @@ module Aviator
def querystring?
instance_methods.include? :querystring
end
def required_params
@required_params ||= []
end
def service(value=nil)
if value
@service = value
else
@service
end
end
def url?
@@ -231,13 +196,27 @@ module Aviator
private
def required_param(param_name)
required_params << param_name unless required_params.include?(param_name)
def link(rel, href)
links << { rel: rel, href: href }
end
def optional_param(param_name)
optional_params << param_name unless optional_params.include?(param_name)
def meta(attr_name, attr_value)
define_singleton_method(attr_name) do
attr_value
end
define_method(attr_name) do
self.class.send(attr_name)
end
end
def param(param_name, opts={})
opts = opts.with_indifferent_access
list = (opts[:required] == false ? optional_params : required_params)
list << param_name unless optional_params.include?(param_name)
end
end

View File

@@ -1,47 +1,26 @@
Aviator.define_request :list_images do
provider :openstack
service :compute
api_version :v2
endpoint_type :public
http_method :get
meta :provider, :openstack
meta :service, :compute
meta :api_version, :v2
meta :endpoint_type, :public
link_to 'documentation',
'http://docs.openstack.org/api/openstack-compute/2/content/List_Images-d1e4435.html'
link 'documentation',
'http://docs.openstack.org/api/openstack-compute/2/content/List_Images-d1e4435.html'
optional_param :details
optional_param :server
optional_param :name
optional_param :status
optional_param 'changes-since'
optional_param :marker
optional_param :limit
optional_param :type
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'compute' }
str = "#{ service_spec[:endpoints][0][:publicURL] }/images"
str += "/detail" if params[:details]
filters = []
(optional_params + required_params - [:details]).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
param :details, required: false
param :server, required: false
param :name, required: false
param :status, required: false
param 'changes-since', required: false
param :marker, required: false
param :limit, required: false
param :type, required: false
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
end
@@ -49,4 +28,27 @@ Aviator.define_request :list_images do
h
end
def http_method
:get
end
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'compute' }
str = "#{ service_spec[:endpoints][0][:publicURL] }/images"
str += "/detail" if params[:details]
filters = []
(optional_params + required_params - [:details]).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
end

View File

@@ -1,45 +1,53 @@
Aviator.define_request :create_tenant do
module Aviator
provider :openstack
service :identity
api_version :v2
endpoint_type :admin
http_method :post
define_request :create_tenant do
link_to 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_addTenant_v2.0_tenants_.html'
meta :provider, :openstack
meta :service, :identity
meta :api_version, :v2
meta :endpoint_type, :admin
required_param :name
required_param :description
required_param :enabled
link 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/'
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
"#{ service_spec[:endpoints][0][:adminURL] }/tenants"
end
param :name, required: true
param :description, required: true
param :enabled, required: true
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
def body
{
tenant: {
name: params[:name],
description: params[:description],
enabled: params[:enabled]
}
}
end
h
end
def body
{
tenant: {
name: params[:name],
description: params[:description],
enabled: params[:enabled]
}
}
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
end
h
end
def http_method
:post
end
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
"#{ service_spec[:endpoints][0][:adminURL] }/tenants"
end
end
end
end

View File

@@ -1,46 +1,54 @@
Aviator.define_request :list_tenants do
module Aviator
provider :openstack
service :identity
api_version :v2
endpoint_type :admin
http_method :get
define_request :list_tenants do
link_to 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tenants_Tenant_Operations.html'
link_to 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1218601'
meta :provider, :openstack
meta :service, :identity
meta :api_version, :v2
meta :endpoint_type, :admin
optional_param :marker
optional_param :limit
link 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tenants_Tenant_Operations.html'
link 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1218601'
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
str = "#{ service_spec[:endpoints][0][:adminURL] }/tenants"
filters = []
(optional_params + required_params).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
param :marker, required: false
param :limit, required: false
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
end
h
end
def http_method
:get
end
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
str = "#{ service_spec[:endpoints][0][:adminURL] }/tenants"
filters = []
(optional_params + required_params).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
h
end
end
end

View File

@@ -1,64 +1,67 @@
Aviator.define_request :create_token do
module Aviator
anonymous
define_request :create_token do
provider :openstack
service :identity
api_version :v2
endpoint_type :public
http_method :post
meta :anonymous, true
meta :provider, :openstack
meta :service, :identity
meta :api_version, :v2
meta :endpoint_type, :public
link_to 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_.html'
link_to 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1208607'
link 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_.html'
link 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1208607'
optional_param :username
optional_param :password
optional_param :tokenId
optional_param :tenantName
optional_param :tenantId
param :username, required: false
param :password, required: false
param :tokenId, required: false
param :tenantName, required: false
param :tenantId, required: false
# TODO: Add logic for when session_data is actually an OpenStack
# authentication response body and not auth bootstrap information
def url
url = session_data[:auth_service][:host_uri]
url += '/v2.0' if (URI(url).path =~ /^\/?\w+/).nil?
url += "/tokens"
url
end
def body
p = if params[:tokenId]
{
auth: {
token: {
id: params[:tokenId]
def body
p = if params[:tokenId]
{
auth: {
token: {
id: params[:tokenId]
}
}
}
}
else
{
auth: {
passwordCredentials: {
username: params[:username],
password: params[:password]
else
{
auth: {
passwordCredentials: {
username: params[:username],
password: params[:password]
}
}
}
}
end
p[:auth][:tenantName] = params[:tenantName] if params[:tenantName]
p[:auth][:tenantId] = params[:tenantId] if params[:tenantId]
p
end
p[:auth][:tenantName] = params[:tenantName] if params[:tenantName]
p[:auth][:tenantId] = params[:tenantId] if params[:tenantId]
p
end
def http_method
:post
end
def url
url = session_data[:auth_service][:host_uri]
url += '/v2.0' if (URI(url).path =~ /^\/?\w+/).nil?
url += "/tokens"
url
end
end
end
end

View File

@@ -1,47 +1,54 @@
Aviator.define_request :list_tenants do
provider :openstack
service :identity
api_version :v2
endpoint_type :public
module Aviator
http_method :get
link_to 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tokens_tenants_.html'
link_to 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1218601'
optional_param :marker
optional_param :limit
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
str = "#{ service_spec[:endpoints][0][:publicURL] }/tenants"
filters = []
(optional_params + required_params).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
define_request :list_tenants do
meta :provider, :openstack
meta :service, :identity
meta :api_version, :v2
meta :endpoint_type, :public
def headers
h = {}
link 'documentation',
'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tokens_tenants_.html'
link 'documentation bug',
'https://bugs.launchpad.net/keystone/+bug/1218601'
param :marker, required: false
param :limit, required: false
def url
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' }
str = "#{ service_spec[:endpoints][0][:publicURL] }/tenants"
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
filters = []
(optional_params + required_params).each do |param_name|
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
end
str += "?#{ filters.join('&') }" unless filters.empty?
str
end
def headers
h = {}
unless self.anonymous?
h['X-Auth-Token'] = session_data[:access][:token][:id]
end
h
end
def http_method
:get
end
h
end
end

83
test.rb
View File

@@ -1,83 +0,0 @@
require 'pry'
require 'active_support/inflector'
module Aviator
class << self
def define_request(request_name, &block)
class_obj = Class.new(Object, &block)
build_or_get_request_class(
Aviator,
class_obj,
class_obj.provider,
class_obj.service,
class_obj.api_version,
class_obj.endpoint_type,
request_name
)
end
private
def build_or_get_request_class(base, obj, *hierarchy)
const_name = hierarchy.shift.to_s.classify
const = if base.const_defined?(const_name)
base.const_get(const_name)
else
base.const_set(const_name, (hierarchy.empty? ? obj : Module.new))
end
hierarchy.empty? ? const : build_or_get_request_class(const, obj, *hierarchy)
end
end # class << self
end # module Aviator
test1 = Aviator.define_request :test1 do
def self.provider
:openstack
end
def self.service
:identity
end
def self.api_version
:v2
end
def self.endpoint_type
:admin
end
end
test2 = Aviator.define_request :test2 do
def self.provider
:openstack
end
def self.service
:identity
end
def self.api_version
:v3
end
def self.endpoint_type
:admin
end
end
binding.pry

View File

@@ -8,13 +8,13 @@ class Aviator::Test
it 'raises an error when a required param is not provided' do
klass = Class.new(Aviator::Request) do
required_param :someparamname
param :someparamname, required: true
end
initializer = lambda { klass.new }
initializer.must_raise ArgumentError
the_method = lambda { klass.new }
the_method.must_raise ArgumentError
error = initializer.call rescue $!
error = the_method.call rescue $!
error.message.wont_be_nil
error.message.must_include "someparamname"
@@ -23,11 +23,9 @@ class Aviator::Test
it 'does not raise any error when the required param is provided' do
klass = Class.new(Aviator::Request) do
required_param :someparamname
param :someparamname, required: true
end
# obj = klass.new({ someparamname: 'someparamvalue' })
obj = klass.new do |params|
params.someparamname = 'something'
end
@@ -37,173 +35,160 @@ class Aviator::Test
describe '::anonymous?' do
it 'is false by default' do
klass = Class.new(Aviator::Request)
klass.anonymous?.must_equal false
end
it 'returns true if specified as such' do
klass = Class.new(Aviator::Request) do
anonymous
meta :anonymous, true
end
klass.anonymous?.must_equal true
end
end
describe '#anonymous?' do
it 'is false by default' do
klass = Class.new(Aviator::Request)
klass.new.anonymous?.must_equal false
end
it 'returns true if specified as such' do
klass = Class.new(Aviator::Request) do
anonymous
meta :anonymous, true
end
klass.new.anonymous?.must_equal true
end
end
describe '::api_version' do
it 'returns the api version' do
klass = Class.new(Aviator::Request) do
api_version :v2
meta :api_version, :v2
end
klass.api_version.must_equal :v2
end
end
describe '#api_version' do
it 'returns the api version' do
klass = Class.new(Aviator::Request) do
api_version :v2
meta :api_version, :v2
end
klass.new.api_version.must_equal :v2
end
end
describe '::body?' do
it 'returns false if the body method is not defined' do
klass = Class.new(Aviator::Request)
klass.body?.must_equal false
end
it 'returns true if the body method is defined' do
klass = Class.new(Aviator::Request) do
def body; end
end
klass.body?.must_equal true
end
end
describe '#body?' do
it 'returns false if the body method is not defined' do
klass = Class.new(Aviator::Request)
klass.new.body?.must_equal false
end
it 'returns true if the body method is defined' do
klass = Class.new(Aviator::Request) do
def body; end
end
klass.new.body?.must_equal true
end
end
describe '::endpoint_type' do
it 'returns the endpoint type' do
klass = Class.new(Aviator::Request) do
endpoint_type :public
meta :endpoint_type, :public
end
klass.endpoint_type.must_equal :public
end
end
describe '#endpoint_type' do
it 'returns the endpoint type' do
klass = Class.new(Aviator::Request) do
endpoint_type :public
meta :endpoint_type, :whatever
end
klass.new.endpoint_type.must_equal :public
klass.new.endpoint_type.must_equal :whatever
end
end
describe '::http_method' do
it 'returns the http method if it is defined' do
klass = Class.new(Aviator::Request) do
http_method :post
end
klass.http_method.must_equal :post
end
end
describe '#http_method' do
it 'returns the http method if it is defined' do
klass = Class.new(Aviator::Request) do
http_method :post
def http_method; :post; end
end
klass.new.http_method.must_equal :post
end
end
describe '::link_to' do
describe '::link' do
it 'adds a link to Request::links' do
rel = 'documentation'
href = 'http://x.y.z'
klass = Class.new(Aviator::Request) do
link_to rel, href
link rel, href
end
expected = [
{ rel: rel, href: href }
]
@@ -211,129 +196,119 @@ class Aviator::Test
klass.links.must_equal expected
klass.new.links.must_equal expected
end
end
describe '::optional_param' do
describe '::param' do
it 'is a private class method' do
private_method = lambda { Aviator::Request.optional_param }
private_method = lambda { Aviator::Request.param }
private_method.must_raise NoMethodError
error = private_method.call rescue $!
error.message.wont_be_nil
error.message.must_include "private method"
end
end
describe '::optional_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
optional_param :whatever
param :whatever, required: false
end
klass.optional_params.must_equal [:whatever]
end
end
describe '#optional_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
optional_param :whatever
end
klass.new.optional_params.must_equal [:whatever]
end
end
describe '::required_param' do
it 'is a private class method' do
private_method = lambda { Aviator::Request.required_param }
private_method.must_raise NoMethodError
error = private_method.call rescue $!
error.message.wont_be_nil
error.message.must_include "private method"
end
end
describe '::required_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
required_param :whatever
end
klass.required_params.must_equal [:whatever]
end
end
describe '#required_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
required_param :whatever
end
klass.required_params.must_equal [:whatever]
end
end
describe '#optional_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
param :whatever, required: false
end
klass.new.optional_params.must_equal [:whatever]
end
end
describe '::required_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
param :whatever, required: true
end
klass.required_params.must_equal [:whatever]
end
end
describe '#required_params' do
it 'returns an array' do
klass = Class.new(Aviator::Request) do
param :whatever, required: true
end
request = klass.new do |params|
params[:whatever] = 'something'
end
request.required_params.must_equal [:whatever]
end
end
describe '::url?' do
it 'returns false if the path method is not defined' do
it 'returns false if the url method is not defined' do
klass = Class.new(Aviator::Request)
klass.url?.must_equal false
end
it 'returns true if the path method is defined' do
it 'returns true if the url method is defined' do
klass = Class.new(Aviator::Request) do
def url; end
end
klass.url?.must_equal true
end
end
describe '#path?' do
it 'returns false if the path method is not defined' do
describe '#url?' do
it 'returns false if the url method is not defined' do
klass = Class.new(Aviator::Request)
klass.new.url?.must_equal false
end
it 'returns true if the path method is defined' do
it 'returns true if the url method is defined' do
klass = Class.new(Aviator::Request) do
def url; end
end
klass.new.url?.must_equal true
end
end

View File

@@ -69,7 +69,7 @@ class Aviator::Test
validate :http_method do
klass.http_method.must_equal :get
create_request.http_method.must_equal :get
end

View File

@@ -86,7 +86,7 @@ class Aviator::Test
validate :http_method do
klass.http_method.must_equal :post
create_request.http_method.must_equal :post
end

View File

@@ -57,7 +57,7 @@ class Aviator::Test
validate :http_method do
klass.http_method.must_equal :post
create_request.http_method.must_equal :post
end

View File

@@ -0,0 +1,63 @@
---
http_interactions:
- request:
method: post
uri: <HOST_URI>:5000/v2.0/tokens
body:
encoding: UTF-8
string: ! '{"auth":{"passwordCredentials":{"username":"admin","password":"<PASSWORD>"},"tenantName":"admin"}}'
headers:
Content-Type:
- application/json
User-Agent:
- Faraday v0.8.8
response:
status:
code: 200
message:
headers:
vary:
- X-Auth-Token
content-type:
- application/json
content-length:
- '2648'
date:
- Wed, 04 Sep 2013 12:55:30 GMT
connection:
- close
body:
encoding: US-ASCII
string: ! '{"access": {"token": {"issued_at": "2013-09-04T12:55:30.584559",
"expires": "2013-09-05T12:55:30Z", "id": "1cd6ba534d94447f9420b372869447ac",
"tenant": {"description": null, "enabled": true, "id": "3cab25130620477b8b03f1bfa8741603",
"name": "admin"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://192.168.56.11:8774/v2/3cab25130620477b8b03f1bfa8741603",
"region": "RegionOne", "internalURL": "http://192.168.56.11:8774/v2/3cab25130620477b8b03f1bfa8741603",
"id": "3b72a66bf2f0491bb8dba827cade0d48", "publicURL": "http://192.168.56.11:8774/v2/3cab25130620477b8b03f1bfa8741603"}],
"endpoints_links": [], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL":
"http://192.168.56.11:3333", "region": "RegionOne", "internalURL": "http://192.168.56.11:3333",
"id": "482f749b370c40eab8788d6d0bc47f48", "publicURL": "http://192.168.56.11:3333"}],
"endpoints_links": [], "type": "s3", "name": "s3"}, {"endpoints": [{"adminURL":
"http://192.168.56.11:9292", "region": "RegionOne", "internalURL": "http://192.168.56.11:9292",
"id": "0cd5d5d5a0c24721a0392b47c89e3640", "publicURL": "http://192.168.56.11:9292"}],
"endpoints_links": [], "type": "image", "name": "glance"}, {"endpoints": [{"adminURL":
"http://192.168.56.11:8777", "region": "RegionOne", "internalURL": "http://192.168.56.11:8777",
"id": "4eb4edec1d2647bfb8ba4f9a5757169d", "publicURL": "http://192.168.56.11:8777"}],
"endpoints_links": [], "type": "metering", "name": "ceilometer"}, {"endpoints":
[{"adminURL": "http://192.168.56.11:8776/v1/3cab25130620477b8b03f1bfa8741603",
"region": "RegionOne", "internalURL": "http://192.168.56.11:8776/v1/3cab25130620477b8b03f1bfa8741603",
"id": "009e8a41953d439f845b2a0c0dc28b73", "publicURL": "http://192.168.56.11:8776/v1/3cab25130620477b8b03f1bfa8741603"}],
"endpoints_links": [], "type": "volume", "name": "cinder"}, {"endpoints":
[{"adminURL": "http://192.168.56.11:8773/services/Admin", "region": "RegionOne",
"internalURL": "http://192.168.56.11:8773/services/Cloud", "id": "6820836ec6834548bf7b54da0271dded",
"publicURL": "http://192.168.56.11:8773/services/Cloud"}], "endpoints_links":
[], "type": "ec2", "name": "ec2"}, {"endpoints": [{"adminURL": "http://192.168.56.11:35357/v2.0",
"region": "RegionOne", "internalURL": "http://192.168.56.11:5000/v2.0", "id":
"24a95f51f67949e784971e97463ee4d8", "publicURL": "http://192.168.56.11:5000/v2.0"}],
"endpoints_links": [], "type": "identity", "name": "keystone"}], "user": {"username":
"admin", "roles_links": [], "id": "cbbcc4f7aef6435fa2da7e5f0b2f1e97", "roles":
[{"name": "admin"}], "name": "admin"}, "metadata": {"is_admin": 0, "roles":
["01a81f2dbb3441f1aaa8fe68a7c6f546"]}}}'
http_version:
recorded_at: Mon, 02 Sep 2013 08:56:17 GMT
recorded_with: VCR 2.5.0