diff --git a/.zuul.yaml b/.zuul.yaml index 044e493..0ab006a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -3,5 +3,4 @@ - publish-openstack-docs-pti - build-release-notes-jobs-python3 - openstack-cover-jobs - - openstack-python-jobs - openstack-python3-ussuri-jobs diff --git a/adjutant/actions/migrations/0001_initial.py b/adjutant/actions/migrations/0001_initial.py index 650c1dc..d737692 100644 --- a/adjutant/actions/migrations/0001_initial.py +++ b/adjutant/actions/migrations/0001_initial.py @@ -25,7 +25,7 @@ class Migration(migrations.Migration): ('need_token', models.BooleanField(default=False)), ('order', models.IntegerField()), ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('task', models.ForeignKey(to='api.Task')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task')), ], ), ] diff --git a/adjutant/actions/models.py b/adjutant/actions/models.py index c0c3e98..036b601 100644 --- a/adjutant/actions/models.py +++ b/adjutant/actions/models.py @@ -30,7 +30,7 @@ class Action(models.Model): state = models.CharField(max_length=200, default="default") valid = models.BooleanField(default=False) need_token = models.BooleanField(default=False) - task = models.ForeignKey('tasks.Task') + task = models.ForeignKey('tasks.Task', on_delete=models.CASCADE) # NOTE(amelia): Auto approve is technically a ternary operator # If all in a task are None it will not auto approve # However if at least one action has it set to True it diff --git a/adjutant/api/migrations/0001_initial.py b/adjutant/api/migrations/0001_initial.py index 49784d4..9b5679d 100644 --- a/adjutant/api/migrations/0001_initial.py +++ b/adjutant/api/migrations/0001_initial.py @@ -47,12 +47,12 @@ class Migration(migrations.Migration): ('token', models.CharField(max_length=32, serialize=False, primary_key=True)), ('created_on', models.DateTimeField(default=django.utils.timezone.now)), ('expires', models.DateTimeField(db_index=True)), - ('task', models.ForeignKey(to='api.Task')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task')), ], ), migrations.AddField( model_name='notification', name='task', - field=models.ForeignKey(to='api.Task'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task'), ), ] diff --git a/adjutant/api/migrations/0005_auto_20190610_0209.py b/adjutant/api/migrations/0005_auto_20190610_0209.py index a654ce6..9f7568b 100644 --- a/adjutant/api/migrations/0005_auto_20190610_0209.py +++ b/adjutant/api/migrations/0005_auto_20190610_0209.py @@ -7,6 +7,8 @@ from django.db import migrations class Migration(migrations.Migration): + atomic = False + dependencies = [ ('api', '0004_auto_20160929_0317'), ] diff --git a/adjutant/api/models.py b/adjutant/api/models.py index b13d8fc..db79e95 100644 --- a/adjutant/api/models.py +++ b/adjutant/api/models.py @@ -29,7 +29,7 @@ class Token(models.Model): UUID token object bound to a task. """ - task = models.ForeignKey(Task) + task = models.ForeignKey(Task, on_delete=models.CASCADE) token = models.CharField(max_length=32, primary_key=True) created_on = models.DateTimeField(default=timezone.now) expires = models.DateTimeField(db_index=True) @@ -56,7 +56,7 @@ class Notification(models.Model): uuid = models.CharField(max_length=32, default=hex_uuid, primary_key=True) notes = JSONField(default={}) - task = models.ForeignKey(Task) + task = models.ForeignKey(Task, on_delete=models.CASCADE) error = models.BooleanField(default=False, db_index=True) created_on = models.DateTimeField(default=timezone.now) acknowledged = models.BooleanField(default=False, db_index=True) diff --git a/adjutant/middleware.py b/adjutant/middleware.py index 92f9c65..25fe16e 100644 --- a/adjutant/middleware.py +++ b/adjutant/middleware.py @@ -17,12 +17,15 @@ from logging import getLogger from django.utils import timezone -class KeystoneHeaderUnwrapper(object): +class KeystoneHeaderUnwrapper: """ Middleware to build an easy to use dict of important data from what the keystone wsgi middleware gives us. """ - def process_request(self, request): + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): try: token_data = { 'project_domain_id': request.META['HTTP_X_PROJECT_DOMAIN_ID'], @@ -38,12 +41,18 @@ class KeystoneHeaderUnwrapper(object): token_data = {} request.keystone_user = token_data + response = self.get_response(request) + return response -class TestingHeaderUnwrapper(object): + +class TestingHeaderUnwrapper: """ Replacement for the KeystoneHeaderUnwrapper for testing purposes. """ - def process_request(self, request): + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): try: token_data = { # TODO(adriant): follow up patch to update all the test @@ -65,17 +74,21 @@ class TestingHeaderUnwrapper(object): token_data = {} request.keystone_user = token_data + response = self.get_response(request) + return response -class RequestLoggingMiddleware(object): + +class RequestLoggingMiddleware: """ Middleware to log the requests and responses. Will time the duration of a request and log that. """ - def __init__(self): + def __init__(self, get_response): + self.get_response = get_response self.logger = getLogger('adjutant') - def process_request(self, request): + def __call__(self, request): self.logger.info( '(%s) - <%s> %s [%s]', timezone.now(), @@ -85,7 +98,8 @@ class RequestLoggingMiddleware(object): ) request.timer = time() - def process_response(self, request, response): + response = self.get_response(request) + if hasattr(request, 'timer'): time_delta = time() - request.timer else: diff --git a/adjutant/settings.py b/adjutant/settings.py index d18d87f..51f8042 100644 --- a/adjutant/settings.py +++ b/adjutant/settings.py @@ -33,7 +33,6 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # Application definition INSTALLED_APPS = ( - 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -50,23 +49,17 @@ INSTALLED_APPS = ( 'adjutant.startup', ) -MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', +MIDDLEWARE = ( 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'adjutant.middleware.KeystoneHeaderUnwrapper', 'adjutant.middleware.RequestLoggingMiddleware' ) if 'test' in sys.argv: - # modify MIDDLEWARE_CLASSES - MIDDLEWARE_CLASSES = list(MIDDLEWARE_CLASSES) - MIDDLEWARE_CLASSES.remove('adjutant.middleware.KeystoneHeaderUnwrapper') - MIDDLEWARE_CLASSES.append('adjutant.middleware.TestingHeaderUnwrapper') + # modify MIDDLEWARE + MIDDLEWARE = list(MIDDLEWARE) + MIDDLEWARE.remove('adjutant.middleware.KeystoneHeaderUnwrapper') + MIDDLEWARE.append('adjutant.middleware.TestingHeaderUnwrapper') ROOT_URLCONF = 'adjutant.urls' @@ -98,6 +91,8 @@ TEMPLATES = [ }, ] +AUTHENTICATION_BACKENDS = [] + REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'adjutant.api.exception_handler.exception_handler', 'DEFAULT_RENDERER_CLASSES': [ diff --git a/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml b/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml new file mode 100644 index 0000000..a10edfc --- /dev/null +++ b/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml @@ -0,0 +1,12 @@ +--- +upgrade: + - | + Adjutant will now officially only support Python3.6 onwards, and will + start introducing features only applicable to that version onwards. +deprecations: + - | + Python2 support has been officially deprecated. The code may still be + compatible for a bit longer, but we are also switching to Django 2.2, + and python2 can no longer be tested. Support for Python less than 3.6 + has also been deprecated, but may still work for older python3 versions + for a little longer, although not officially. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 04ea756..cfc10da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ pbr>=5.2.0 +Django>=2.2,<2.3 Babel>=2.6.0 decorator>=4.4.0 django-rest-swagger>=2.2.0 @@ -15,8 +16,4 @@ python-octaviaclient>=1.8.0 PyYAML>=5.1 six>=1.12.0 confspirator>=0.1.6 - -# Address soon: -Django>=1.11,<1.12 -# was pinned because of django 1.11 -mysqlclient>=1.3.10,<1.4 +mysqlclient>=1.4.6 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 2b309a9..5cd7ca0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,8 +16,7 @@ classifier = Intended Audience :: Developers Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License - Framework :: Django :: 1.11 - Programming Language :: Python :: 2.7 + Framework :: Django :: 2.2 Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 diff --git a/tox.ini b/tox.ini index b1344b1..51275a9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py3,py27,pep8,cover_report +envlist = py3,pep8,cover_report skipsdist = True [testenv]