From 542aaa6ffeba88208e1b9b4bc1462a09925b0aab Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Mon, 11 Aug 2014 12:19:34 -0400 Subject: [PATCH] Use JSON instead of pickles for compatibility. --- bin/ansible-playbook | 2 +- lib/ansible/cache/file.py | 70 -------------------------------------- lib/ansible/cache/redis.py | 36 +++++--------------- lib/ansible/constants.py | 2 +- 4 files changed, 11 insertions(+), 99 deletions(-) delete mode 100644 lib/ansible/cache/file.py diff --git a/bin/ansible-playbook b/bin/ansible-playbook index 3a5e399b23b..a8c98f39931 100755 --- a/bin/ansible-playbook +++ b/bin/ansible-playbook @@ -84,7 +84,7 @@ def main(args): parser.add_option('--force-handlers', dest='force_handlers', action='store_true', help="run handlers even if a task fails") parser.add_option('--flush-cache', dest='flush_cache', action='store_true', - help="flush to fact cache") + help="clear the fact cache") options, args = parser.parse_args(args) diff --git a/lib/ansible/cache/file.py b/lib/ansible/cache/file.py deleted file mode 100644 index 677c2f887b9..00000000000 --- a/lib/ansible/cache/file.py +++ /dev/null @@ -1,70 +0,0 @@ -# (c) 2014, Brian Coca, Josh Drake, et al -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -from __future__ import absolute_import - -import collections -import json -import os -import shutil -import sys -import tempfile -from datetime import datetime - -from ansible import constants as C -from ansible.cache.memory import CacheModule as MemoryCacheModule - - -class CacheModule(MemoryCacheModule): - def __init__(self): - super(CacheModule, self).__init__() - self._timeout = int(C.CACHE_PLUGIN_TIMEOUT) - self._filename = '/tmp/ansible_facts.json' - - if os.access(self._filename, os.R_OK): - mtime = datetime.fromtimestamp(os.path.getmtime(self._filename)) - if self._timeout == 0 or (datetime.now() - mtime).total_seconds() < self._timeout: - with open(self._filename, 'rb') as f: - # we could make assumptions about the MemoryCacheModule here if we wanted - # to be more efficient, but performance isn't the priority with this module - data = json.load(f) - if isinstance(data, collections.Mapping): - for k, v in data.items(): - super(CacheModule, self).set(k, v) - - def set(self, *args, **kwargs): - super(CacheModule, self).set(*args, **kwargs) - self.fsync() - - def delete(self, *args, **kwargs): - super(CacheModule, self).delete(*args, **kwargs) - self.fsync() - - def fsync(self): - temp = tempfile.TemporaryFile('r+b') - - try: - json.dump(self._cache, temp, separators=(',', ':')) - temp.seek(0) - with open(self._filename, 'w+b') as f: - shutil.copyfileobj(temp, f) - finally: - temp.close() - - def flush(self): - super(CacheModule, self).flush() - self.fsync() diff --git a/lib/ansible/cache/redis.py b/lib/ansible/cache/redis.py index 98db2215b34..9b0cfaaecbb 100644 --- a/lib/ansible/cache/redis.py +++ b/lib/ansible/cache/redis.py @@ -18,9 +18,9 @@ from __future__ import absolute_import import collections # FIXME: can we store these as something else before we ship it? -import cPickle import sys import time +import json from ansible import constants as C from ansible.cache.base import BaseCacheModule @@ -28,28 +28,9 @@ from ansible.cache.base import BaseCacheModule try: from redis import StrictRedis except ImportError: - print "The 'redis' Python module is required for the redis fact cache" + print "The 'redis' python module is required, 'pip install redis'" sys.exit(1) - -class PickledRedis(StrictRedis): - """ - A subclass of StrictRedis that uses the pickle module to store and load - representations of the provided values. - """ - def get(self, name): - pickled_value = super(PickledRedis, self).get(name) - if pickled_value is None: - return None - return cPickle.loads(pickled_value) - - def set(self, name, value, *args, **kwargs): - return super(PickledRedis, self).set(name, cPickle.dumps(value), *args, **kwargs) - - def setex(self, name, time, value): - return super(PickledRedis, self).setex(name, time, cPickle.dumps(value)) - - class CacheModule(BaseCacheModule): """ A caching module backed by redis. @@ -65,13 +46,13 @@ class CacheModule(BaseCacheModule): else: connection = [] - self._timeout = C.CACHE_PLUGIN_TIMEOUT + self._timeout = float(C.CACHE_PLUGIN_TIMEOUT) self._prefix = C.CACHE_PLUGIN_PREFIX - self._cache = PickledRedis(*connection) + self._cache = StrictRedis(*connection) self._keys_set = 'ansible_cache_keys' def _make_key(self, key): - return "{}{}".format(self._prefix, key) + return self._prefix + key def get(self, key): value = self._cache.get(self._make_key(key)) @@ -81,13 +62,14 @@ class CacheModule(BaseCacheModule): if value is None: self.delete(key) raise KeyError - return value + return json.loads(value) def set(self, key, value): + value2 = json.dumps(value) if self._timeout > 0: # a timeout of 0 is handled as meaning 'never expire' - self._cache.setex(self._make_key(key), self._timeout, value) + self._cache.setex(self._make_key(key), int(self._timeout), value2) else: - self._cache.set(self._make_key(key), value) + self._cache.set(self._make_key(key), value2) self._cache.zadd(self._keys_set, time.time(), key) diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py index 9b183568a30..214fcb872ca 100644 --- a/lib/ansible/constants.py +++ b/lib/ansible/constants.py @@ -151,7 +151,7 @@ DEFAULT_LOG_PATH = shell_expand_path(get_config(p, DEFAULTS, 'log_ CACHE_PLUGIN = get_config(p, DEFAULTS, 'fact_caching', 'ANSIBLE_CACHE_PLUGIN', 'memory') CACHE_PLUGIN_CONNECTION = get_config(p, DEFAULTS, 'cache_plugin_connection', 'ANSIBLE_CACHE_PLUGIN_CONNECTION', None) CACHE_PLUGIN_PREFIX = get_config(p, DEFAULTS, 'cache_plugin_prefix', 'ANSIBLE_CACHE_PLUGIN_PREFIX', 'ansible_facts') -CACHE_PLUGIN_TIMEOUT = get_config(p, DEFAULTS, 'cache_plugin_timeout', 'ANSIBLE_CACHE_PLUGIN_TIMEOUT', (60 * 60 * 24), integer=True) +CACHE_PLUGIN_TIMEOUT = get_config(p, DEFAULTS, 'cache_plugin_timeout', 'ANSIBLE_CACHE_PLUGIN_TIMEOUT', 24 * 60 * 60, integer=True) ANSIBLE_FORCE_COLOR = get_config(p, DEFAULTS, 'force_color', 'ANSIBLE_FORCE_COLOR', None, boolean=True) ANSIBLE_NOCOLOR = get_config(p, DEFAULTS, 'nocolor', 'ANSIBLE_NOCOLOR', None, boolean=True)