mirror of
https://github.com/ansible/awx.git
synced 2026-03-13 23:17:32 -02:30
Move named url init out of Middleware init
* Middleware classes can be instantiated multiple times in testing. To make this a non-issue, move the init code for named urls out of the middleware init and into the app init. * This makes it easier to use other testing facilities, like LiveServerTestCase, without having to mock the named url middleware init.
This commit is contained in:
committed by
Chris Meyers
parent
09f0a366bf
commit
61ec03e540
@@ -1,7 +1,40 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from awx.main.utils.named_url_graph import _customize_graph, generate_graph
|
||||||
|
from awx.conf import register, fields
|
||||||
|
|
||||||
|
|
||||||
class MainConfig(AppConfig):
|
class MainConfig(AppConfig):
|
||||||
name = 'awx.main'
|
name = 'awx.main'
|
||||||
verbose_name = _('Main')
|
verbose_name = _('Main')
|
||||||
|
|
||||||
|
def load_named_url_feature(self):
|
||||||
|
models = [m for m in self.get_models() if hasattr(m, 'get_absolute_url')]
|
||||||
|
generate_graph(models)
|
||||||
|
_customize_graph()
|
||||||
|
register(
|
||||||
|
'NAMED_URL_FORMATS',
|
||||||
|
field_class=fields.DictField,
|
||||||
|
read_only=True,
|
||||||
|
label=_('Formats of all available named urls'),
|
||||||
|
help_text=_('Read-only list of key-value pairs that shows the standard format of all available named URLs.'),
|
||||||
|
category=_('Named URL'),
|
||||||
|
category_slug='named-url',
|
||||||
|
)
|
||||||
|
register(
|
||||||
|
'NAMED_URL_GRAPH_NODES',
|
||||||
|
field_class=fields.DictField,
|
||||||
|
read_only=True,
|
||||||
|
label=_('List of all named url graph nodes.'),
|
||||||
|
help_text=_(
|
||||||
|
'Read-only list of key-value pairs that exposes named URL graph topology.'
|
||||||
|
' Use this list to programmatically generate named URLs for resources'
|
||||||
|
),
|
||||||
|
category=_('Named URL'),
|
||||||
|
category_slug='named-url',
|
||||||
|
)
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
super().ready()
|
||||||
|
|
||||||
|
self.load_named_url_feature()
|
||||||
|
|||||||
@@ -9,18 +9,13 @@ from pathlib import Path
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db.migrations.recorder import MigrationRecorder
|
from django.db.migrations.recorder import MigrationRecorder
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.apps import apps
|
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from django.urls import reverse, resolve
|
from django.urls import reverse, resolve
|
||||||
|
|
||||||
from awx.main import migrations
|
from awx.main import migrations
|
||||||
from awx.main.utils.named_url_graph import generate_graph, GraphNode
|
|
||||||
from awx.conf import fields, register
|
|
||||||
from awx.main.utils.profiling import AWXProfiler
|
from awx.main.utils.profiling import AWXProfiler
|
||||||
from awx.main.utils.common import memoize
|
from awx.main.utils.common import memoize
|
||||||
|
|
||||||
@@ -100,49 +95,7 @@ class DisableLocalAuthMiddleware(MiddlewareMixin):
|
|||||||
logout(request)
|
logout(request)
|
||||||
|
|
||||||
|
|
||||||
def _customize_graph():
|
|
||||||
from awx.main.models import Instance, Schedule, UnifiedJobTemplate
|
|
||||||
|
|
||||||
for model in [Schedule, UnifiedJobTemplate]:
|
|
||||||
if model in settings.NAMED_URL_GRAPH:
|
|
||||||
settings.NAMED_URL_GRAPH[model].remove_bindings()
|
|
||||||
settings.NAMED_URL_GRAPH.pop(model)
|
|
||||||
if User not in settings.NAMED_URL_GRAPH:
|
|
||||||
settings.NAMED_URL_GRAPH[User] = GraphNode(User, ['username'], [])
|
|
||||||
settings.NAMED_URL_GRAPH[User].add_bindings()
|
|
||||||
if Instance not in settings.NAMED_URL_GRAPH:
|
|
||||||
settings.NAMED_URL_GRAPH[Instance] = GraphNode(Instance, ['hostname'], [])
|
|
||||||
settings.NAMED_URL_GRAPH[Instance].add_bindings()
|
|
||||||
|
|
||||||
|
|
||||||
class URLModificationMiddleware(MiddlewareMixin):
|
class URLModificationMiddleware(MiddlewareMixin):
|
||||||
def __init__(self, get_response):
|
|
||||||
models = [m for m in apps.get_app_config('main').get_models() if hasattr(m, 'get_absolute_url')]
|
|
||||||
generate_graph(models)
|
|
||||||
_customize_graph()
|
|
||||||
register(
|
|
||||||
'NAMED_URL_FORMATS',
|
|
||||||
field_class=fields.DictField,
|
|
||||||
read_only=True,
|
|
||||||
label=_('Formats of all available named urls'),
|
|
||||||
help_text=_('Read-only list of key-value pairs that shows the standard format of all available named URLs.'),
|
|
||||||
category=_('Named URL'),
|
|
||||||
category_slug='named-url',
|
|
||||||
)
|
|
||||||
register(
|
|
||||||
'NAMED_URL_GRAPH_NODES',
|
|
||||||
field_class=fields.DictField,
|
|
||||||
read_only=True,
|
|
||||||
label=_('List of all named url graph nodes.'),
|
|
||||||
help_text=_(
|
|
||||||
'Read-only list of key-value pairs that exposes named URL graph topology.'
|
|
||||||
' Use this list to programmatically generate named URLs for resources'
|
|
||||||
),
|
|
||||||
category=_('Named URL'),
|
|
||||||
category_slug='named-url',
|
|
||||||
)
|
|
||||||
super().__init__(get_response)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hijack_for_old_jt_name(node, kwargs, named_url):
|
def _hijack_for_old_jt_name(node, kwargs, named_url):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
@@ -23,25 +20,6 @@ from awx.main.models import ( # noqa
|
|||||||
User,
|
User,
|
||||||
WorkflowJobTemplate,
|
WorkflowJobTemplate,
|
||||||
)
|
)
|
||||||
from awx.conf import settings_registry
|
|
||||||
|
|
||||||
|
|
||||||
def setup_module(module):
|
|
||||||
# In real-world scenario, named url graph structure is populated by __init__
|
|
||||||
# of URLModificationMiddleware. The way Django bootstraps ensures the initialization
|
|
||||||
# will happen *once and only once*, while the number of initialization is uncontrollable
|
|
||||||
# in unit test environment. So it is wrapped by try-except block to mute any
|
|
||||||
# unwanted exceptions.
|
|
||||||
try:
|
|
||||||
URLModificationMiddleware(mock.Mock())
|
|
||||||
except ImproperlyConfigured:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def teardown_module(module):
|
|
||||||
# settings_registry will be persistent states unless we explicitly clean them up.
|
|
||||||
settings_registry.unregister('NAMED_URL_FORMATS')
|
|
||||||
settings_registry.unregister('NAMED_URL_GRAPH_NODES')
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from collections import deque
|
|||||||
# Django
|
# Django
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
|
|
||||||
|
|
||||||
NAMED_URL_RES_DILIMITER = "++"
|
NAMED_URL_RES_DILIMITER = "++"
|
||||||
@@ -245,6 +244,8 @@ def _generate_configurations(nodes):
|
|||||||
|
|
||||||
|
|
||||||
def _dfs(configuration, model, graph, dead_ends, new_deadends, parents):
|
def _dfs(configuration, model, graph, dead_ends, new_deadends, parents):
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
parents.add(model)
|
parents.add(model)
|
||||||
fields, fk_names = configuration[model][0][:], configuration[model][1][:]
|
fields, fk_names = configuration[model][0][:], configuration[model][1][:]
|
||||||
adj_list = []
|
adj_list = []
|
||||||
@@ -306,3 +307,19 @@ def generate_graph(models):
|
|||||||
def reset_counters():
|
def reset_counters():
|
||||||
for node in settings.NAMED_URL_GRAPH.values():
|
for node in settings.NAMED_URL_GRAPH.values():
|
||||||
node.counter = 0
|
node.counter = 0
|
||||||
|
|
||||||
|
|
||||||
|
def _customize_graph():
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from awx.main.models import Instance, Schedule, UnifiedJobTemplate
|
||||||
|
|
||||||
|
for model in [Schedule, UnifiedJobTemplate]:
|
||||||
|
if model in settings.NAMED_URL_GRAPH:
|
||||||
|
settings.NAMED_URL_GRAPH[model].remove_bindings()
|
||||||
|
settings.NAMED_URL_GRAPH.pop(model)
|
||||||
|
if User not in settings.NAMED_URL_GRAPH:
|
||||||
|
settings.NAMED_URL_GRAPH[User] = GraphNode(User, ['username'], [])
|
||||||
|
settings.NAMED_URL_GRAPH[User].add_bindings()
|
||||||
|
if Instance not in settings.NAMED_URL_GRAPH:
|
||||||
|
settings.NAMED_URL_GRAPH[Instance] = GraphNode(Instance, ['hostname'], [])
|
||||||
|
settings.NAMED_URL_GRAPH[Instance].add_bindings()
|
||||||
|
|||||||
Reference in New Issue
Block a user