mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 18:40:01 -03:30
Merge pull request #1018 from cchurch/redis-cache
Use Redis as cache backend.
This commit is contained in:
commit
146e724930
@ -4,6 +4,7 @@
|
||||
from rest_framework.exceptions import APIException
|
||||
|
||||
from awx.main.task_engine import TaskSerializer
|
||||
from awx.main.utils import memoize
|
||||
|
||||
|
||||
class LicenseForbids(APIException):
|
||||
@ -11,6 +12,7 @@ class LicenseForbids(APIException):
|
||||
default_detail = 'Your Tower license does not allow that.'
|
||||
|
||||
|
||||
@memoize()
|
||||
def get_license(show_key=False, bypass_database=False):
|
||||
"""Return a dictionary representing the license currently in
|
||||
place on this Tower instance.
|
||||
|
||||
@ -18,6 +18,7 @@ from collections import OrderedDict
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.cache import cache
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.models import Q, Count
|
||||
@ -263,6 +264,8 @@ class ApiV1ConfigView(APIView):
|
||||
if license_data['valid_key']:
|
||||
tower_settings.LICENSE = data_actual
|
||||
tower_settings.TOWER_URL_BASE = "{}://{}".format(request.scheme, request.get_host())
|
||||
# Clear cache when license is updated.
|
||||
cache.clear()
|
||||
return Response(license_data)
|
||||
|
||||
return Response({"error": "Invalid license"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
@ -282,6 +285,8 @@ class ApiV1ConfigView(APIView):
|
||||
break
|
||||
|
||||
TowerSettings.objects.filter(key="LICENSE").delete()
|
||||
# Clear cache when license is updated.
|
||||
cache.clear()
|
||||
|
||||
# Only stop mongod if license removal succeeded
|
||||
if has_error is None:
|
||||
|
||||
@ -24,6 +24,7 @@ import yaml
|
||||
import django.test
|
||||
from django.conf import settings, UserSettingsHolder
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.cache import cache
|
||||
from django.test.client import Client
|
||||
from django.test.utils import override_settings
|
||||
from django.utils.encoding import force_text
|
||||
@ -152,6 +153,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
|
||||
'LOCATION': 'unittests'
|
||||
}
|
||||
}
|
||||
cache.clear()
|
||||
self._start_time = time.time()
|
||||
|
||||
def tearDown(self):
|
||||
@ -195,6 +197,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
|
||||
writer.write_file(license_path)
|
||||
self._temp_paths.append(license_path)
|
||||
os.environ['AWX_LICENSE_FILE'] = license_path
|
||||
cache.clear()
|
||||
|
||||
def create_basic_license_file(self, instance_count=100, license_date=int(time.time() + 3600)):
|
||||
writer = LicenseWriter(
|
||||
@ -209,6 +212,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
|
||||
writer.write_file(license_path)
|
||||
self._temp_paths.append(license_path)
|
||||
os.environ['AWX_LICENSE_FILE'] = license_path
|
||||
cache.clear()
|
||||
|
||||
def create_expired_license_file(self, instance_count=1000, grace_period=False):
|
||||
license_date = time.time() - 1
|
||||
|
||||
@ -16,9 +16,13 @@ import threading
|
||||
import contextlib
|
||||
import tempfile
|
||||
|
||||
# Decorator
|
||||
from decorator import decorator
|
||||
|
||||
# Django REST Framework
|
||||
from rest_framework.exceptions import ParseError, PermissionDenied
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.text import slugify
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.apps import apps
|
||||
|
||||
@ -27,7 +31,7 @@ from Crypto.Cipher import AES
|
||||
|
||||
logger = logging.getLogger('awx.main.utils')
|
||||
|
||||
__all__ = ['get_object_or_400', 'get_object_or_403', 'camelcase_to_underscore',
|
||||
__all__ = ['get_object_or_400', 'get_object_or_403', 'camelcase_to_underscore', 'memoize',
|
||||
'get_ansible_version', 'get_ssh_version', 'get_awx_version', 'update_scm_url',
|
||||
'get_type_for_model', 'get_model_for_type', 'to_python_boolean',
|
||||
'ignore_inventory_computed_fields', 'ignore_inventory_group_removal',
|
||||
@ -93,6 +97,23 @@ class RequireDebugTrueOrTest(logging.Filter):
|
||||
return settings.DEBUG or 'test' in sys.argv
|
||||
|
||||
|
||||
def memoize(ttl=60):
|
||||
'''
|
||||
Decorator to wrap a function and cache its result.
|
||||
'''
|
||||
from django.core.cache import cache
|
||||
|
||||
def _memoizer(f, *args, **kwargs):
|
||||
key = slugify('%s %r %r' % (f.__name__, args, kwargs))
|
||||
value = cache.get(key)
|
||||
if value is None:
|
||||
value = f(*args, **kwargs)
|
||||
cache.set(key, value, ttl)
|
||||
return value
|
||||
return decorator(_memoizer)
|
||||
|
||||
|
||||
@memoize()
|
||||
def get_ansible_version():
|
||||
'''
|
||||
Return Ansible version installed.
|
||||
@ -101,11 +122,11 @@ def get_ansible_version():
|
||||
proc = subprocess.Popen(['ansible', '--version'],
|
||||
stdout=subprocess.PIPE)
|
||||
result = proc.communicate()[0]
|
||||
stripped_result = result.split('\n')[0].replace('ansible', '').strip()
|
||||
return stripped_result
|
||||
return result.split('\n')[0].replace('ansible', '').strip()
|
||||
except:
|
||||
return 'unknown'
|
||||
|
||||
@memoize()
|
||||
def get_ssh_version():
|
||||
'''
|
||||
Return SSH version installed.
|
||||
@ -444,6 +465,7 @@ def ignore_inventory_group_removal():
|
||||
finally:
|
||||
_inventory_updates.is_removing = previous_value
|
||||
|
||||
@memoize()
|
||||
def check_proot_installed():
|
||||
'''
|
||||
Check that proot is installed.
|
||||
|
||||
@ -351,6 +351,21 @@ CELERYBEAT_SCHEDULE = {
|
||||
},
|
||||
}
|
||||
|
||||
# Use Redis as cache backend (except when testing).
|
||||
if is_testing():
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
},
|
||||
}
|
||||
else:
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'redis_cache.RedisCache',
|
||||
'LOCATION': BROKER_URL,
|
||||
},
|
||||
}
|
||||
|
||||
# Social Auth configuration.
|
||||
SOCIAL_AUTH_STRATEGY = 'social.strategies.django_strategy.DjangoStrategy'
|
||||
SOCIAL_AUTH_STORAGE = 'social.apps.django_app.default.models.DjangoStorage'
|
||||
|
||||
@ -32,3 +32,7 @@ if not all([SOCIAL_AUTH_SAML_SP_ENTITY_ID, SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
||||
|
||||
if not AUTH_BASIC_ENABLED:
|
||||
REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = [x for x in REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] if x != 'rest_framework.authentication.BasicAuthentication']
|
||||
|
||||
# Update cache to use celery broker URL defined in configuration files.
|
||||
if CACHES['default']['BACKEND'] == 'redis_cache.RedisCache':
|
||||
CACHES['default']['LOCATION'] = BROKER_URL
|
||||
|
||||
24
docs/licenses/django-redis-cache.txt
Normal file
24
docs/licenses/django-redis-cache.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Copyright (c) 2015 Sean Bleier
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -21,6 +21,7 @@ django-extensions==1.5.9
|
||||
git+https://github.com/chrismeyersfsu/django-jsonbfield@fix-sqlite_serialization#egg=jsonbfield
|
||||
django-polymorphic==0.7.2
|
||||
django-radius==1.0.0
|
||||
django-redis-cache==1.6.5
|
||||
djangorestframework==3.3.2
|
||||
djangorestframework-yaml==1.0.2
|
||||
django-split-settings==0.1.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user