From 64c8a5e68268d32b7ba53345fddfc3f7f188f6de Mon Sep 17 00:00:00 2001 From: Darren Hague Date: Wed, 28 Oct 2015 15:05:26 +0000 Subject: [PATCH] [openstack] Basic caching support for auth tokens, domains & projects --- lib/fog/openstack/core.rb | 21 +++++++++-------- .../openstack/models/identity_v3/domain.rb | 6 +++++ .../openstack/models/identity_v3/domains.rb | 23 +++++++++++++++---- .../openstack/models/identity_v3/project.rb | 10 ++++++++ .../openstack/models/identity_v3/projects.rb | 19 ++++++++++++--- .../openstack/models/identity_v3/tokens.rb | 1 + 6 files changed, 64 insertions(+), 16 deletions(-) diff --git a/lib/fog/openstack/core.rb b/lib/fog/openstack/core.rb index 6f942df67..7dd079239 100644 --- a/lib/fog/openstack/core.rb +++ b/lib/fog/openstack/core.rb @@ -504,17 +504,20 @@ module Fog end request_body[:auth][:scope] = scope unless scope.empty? - puts "request_body: #{request_body}" if user_domain=='Default2' + path = (uri.path and not uri.path.empty?) ? uri.path : 'v3' - response = connection.request({ - :expects => [201], - :headers => {'Content-Type' => 'application/json'}, - :body => Fog::JSON.encode(request_body), - :method => 'POST', - :path => (uri.path and not uri.path.empty?) ? uri.path : 'v2.0' - }) + @@token_cache ||= {} + response, expires = @@token_cache[{body: request_body, path: path}] - puts "response.body: #{response.body}" if user_domain=='Default2' + unless response && expires > Time.now + response = connection.request({ :expects => [201], + :headers => {'Content-Type' => 'application/json'}, + :body => Fog::JSON.encode(request_body), + :method => 'POST', + :path => (uri.path and not uri.path.empty?) ? uri.path : 'v3' + }) + @@token_cache[{body: request_body, path: path}] = response, Time.now + 30 # 30-second TTL, enough for most requests + end [response.headers["X-Subject-Token"], Fog::JSON.decode(response.body)] end diff --git a/lib/fog/openstack/models/identity_v3/domain.rb b/lib/fog/openstack/models/identity_v3/domain.rb index 7675890de..c4ddf7c21 100644 --- a/lib/fog/openstack/models/identity_v3/domain.rb +++ b/lib/fog/openstack/models/identity_v3/domain.rb @@ -17,12 +17,14 @@ module Fog end def destroy + @@cache.clear if @@cache requires :id service.delete_domain(self.id) true end def update(attr = nil) + @@cache.clear if @@cache requires :id, :name merge_attributes( service.update_domain(self.id, attr || attributes).body['domain']) @@ -30,12 +32,16 @@ module Fog end def create + @@cache.clear if @@cache requires :name merge_attributes( service.create_domain(attributes).body['domain']) self end + def self.use_cache(cache) + @@cache = cache + end end end end diff --git a/lib/fog/openstack/models/identity_v3/domains.rb b/lib/fog/openstack/models/identity_v3/domains.rb index 486c80bcf..67e2870b9 100644 --- a/lib/fog/openstack/models/identity_v3/domains.rb +++ b/lib/fog/openstack/models/identity_v3/domains.rb @@ -8,8 +8,20 @@ module Fog class Domains < Fog::OpenStack::Collection model Fog::Identity::OpenStack::V3::Domain + @@cache = {} + Fog::Identity::OpenStack::V3::Domain.use_cache(@@cache) + def all(options = {}) - load_response(service.list_domains(options), 'domains') + cached_domain, expires = @@cache[{token: service.auth_token, options: options}] + return cached_domain if cached_domain && expires > Time.now + domain_to_cache = load_response(service.list_domains(options), 'domains') + @@cache[{token: service.auth_token, options: options}] = domain_to_cache, Time.now + 30 # 30-second TTL + return domain_to_cache + end + + def create(attributes) + @@cache.clear if @@cache + super(attributes) end def auth_domains(options = {}) @@ -17,14 +29,17 @@ module Fog end def find_by_id(id) - cached_domain = self.find { |domain| domain.id == id } - return cached_domain if cached_domain + cached_domain, expires = @@cache[{token: service.auth_token, id: id}] + return cached_domain if cached_domain && expires > Time.now domain_hash = service.get_domain(id).body['domain'] - Fog::Identity::OpenStack::V3::Domain.new( + domain_to_cache = Fog::Identity::OpenStack::V3::Domain.new( domain_hash.merge(:service => service)) + @@cache[{token: service.auth_token, id: id}] = domain_to_cache, Time.now + 30 # 30-second TTL + return domain_to_cache end def destroy(id) + @@cache.clear if @@cache domain = self.find_by_id(id) domain.destroy end diff --git a/lib/fog/openstack/models/identity_v3/project.rb b/lib/fog/openstack/models/identity_v3/project.rb index f1f2c7e23..4e758acf0 100644 --- a/lib/fog/openstack/models/identity_v3/project.rb +++ b/lib/fog/openstack/models/identity_v3/project.rb @@ -21,12 +21,14 @@ module Fog end def destroy + @@cache.clear if @@cache requires :id service.delete_project(self.id) true end def update(attr = nil) + @@cache.clear if @@cache requires :id merge_attributes( service.update_project(self.id, attr || attributes).body['project']) @@ -34,6 +36,7 @@ module Fog end def create + @@cache.clear if @@cache merge_attributes( service.create_project(attributes).body['project']) self @@ -45,6 +48,7 @@ module Fog end def grant_role_to_user(role_id, user_id) + @@cache.clear if @@cache requires :id service.grant_project_user_role(self.id, user_id, role_id) end @@ -60,6 +64,7 @@ module Fog end def revoke_role_from_user(role_id, user_id) + @@cache.clear if @@cache requires :id service.revoke_project_user_role(self.id, user_id, role_id) end @@ -70,6 +75,7 @@ module Fog end def grant_role_to_group(role_id, group_id) + @@cache.clear if @@cache requires :id service.grant_project_group_role(self.id, group_id, role_id) end @@ -85,10 +91,14 @@ module Fog end def revoke_role_from_group(role_id, group_id) + @@cache.clear if @@cache requires :id service.revoke_project_group_role(self.id, group_id, role_id) end + def self.use_cache(cache) + @@cache = cache + end end end end diff --git a/lib/fog/openstack/models/identity_v3/projects.rb b/lib/fog/openstack/models/identity_v3/projects.rb index c486988e5..35aad4cbc 100644 --- a/lib/fog/openstack/models/identity_v3/projects.rb +++ b/lib/fog/openstack/models/identity_v3/projects.rb @@ -8,8 +8,20 @@ module Fog class Projects < Fog::OpenStack::Collection model Fog::Identity::OpenStack::V3::Project + @@cache = {} + Fog::Identity::OpenStack::V3::Project.use_cache(@@cache) + def all(options = {}) - load_response(service.list_projects(options), 'projects') + cached_project, expires = @@cache[{token: service.auth_token, options: options}] + return cached_project if cached_project && expires > Time.now + project_to_cache = load_response(service.list_projects(options), 'projects') + @@cache[{token: service.auth_token, options: options}] = project_to_cache, Time.now + 30 # 30-second TTL + return project_to_cache + end + + def create(attributes) + @@cache.clear if @@cache + super(attributes) end def auth_projects(options = {}) @@ -20,8 +32,8 @@ module Fog if options.is_a? Symbol # Deal with a single option being passed on its own options = [options] end - cached_project = self.find { |project| project.id == id } if options.empty? - return cached_project if cached_project + cached_project, expires = @@cache[{token: service.auth_token, id: id, options: options}] + return cached_project if cached_project && expires > Time.now project_hash = service.get_project(id, options).body['project'] top_project = project_from_hash(project_hash, service) if options.include? :subtree_as_list @@ -30,6 +42,7 @@ module Fog if options.include? :parents_as_list top_project.parents.map! {|proj_hash| project_from_hash(proj_hash['project'], service)} end + @@cache[{token: service.auth_token, id: id, options: options}] = top_project, Time.now + 30 # 30-second TTL return top_project end diff --git a/lib/fog/openstack/models/identity_v3/tokens.rb b/lib/fog/openstack/models/identity_v3/tokens.rb index 7b1ffed6f..efa00301f 100644 --- a/lib/fog/openstack/models/identity_v3/tokens.rb +++ b/lib/fog/openstack/models/identity_v3/tokens.rb @@ -10,6 +10,7 @@ module Fog def authenticate(auth) + @@cache ||= {} response = service.token_authenticate(auth) token_hash = response.body['token'] Fog::Identity::OpenStack::V3::Token.new(