Move ConfigRevision model & write migrations

This commit is contained in:
Jeremy Stretch 2023-11-22 12:25:03 -05:00
parent 18422e1d26
commit c4d87efdeb
14 changed files with 133 additions and 67 deletions

View File

@ -1,7 +1,7 @@
from django.core.cache import cache from django.core.cache import cache
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from extras.models import ConfigRevision from core.models import ConfigRevision
class Command(BaseCommand): class Command(BaseCommand):

View File

@ -0,0 +1,31 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0008_contenttype_proxy'),
]
operations = [
migrations.SeparateDatabaseAndState(
state_operations=[
migrations.CreateModel(
name='ConfigRevision',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('comment', models.CharField(blank=True, max_length=200)),
('data', models.JSONField(blank=True, null=True)),
],
options={
'verbose_name': 'config revision',
'verbose_name_plural': 'config revisions',
'ordering': ['-created'],
},
),
],
# Table has been renamed from extras_configrevision
database_operations=[],
),
]

View File

@ -1,3 +1,4 @@
from .config import *
from .contenttypes import * from .contenttypes import *
from .data import * from .data import *
from .files import * from .files import *

View File

@ -0,0 +1,66 @@
from django.core.cache import cache
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext, gettext_lazy as _
from utilities.querysets import RestrictedQuerySet
__all__ = (
'ConfigRevision',
)
class ConfigRevision(models.Model):
"""
An atomic revision of NetBox's configuration.
"""
created = models.DateTimeField(
verbose_name=_('created'),
auto_now_add=True
)
comment = models.CharField(
verbose_name=_('comment'),
max_length=200,
blank=True
)
data = models.JSONField(
blank=True,
null=True,
verbose_name=_('configuration data')
)
objects = RestrictedQuerySet.as_manager()
class Meta:
ordering = ['-created']
verbose_name = _('config revision')
verbose_name_plural = _('config revisions')
def __str__(self):
if not self.pk:
return gettext('Default configuration')
if self.is_active:
return gettext('Current configuration')
return gettext('Config revision #{id}').format(id=self.pk)
def __getattr__(self, item):
if item in self.data:
return self.data[item]
return super().__getattribute__(item)
def get_absolute_url(self):
if not self.pk:
return reverse('core:config') # Default config view
return reverse('extras:configrevision', args=[self.pk])
def activate(self):
"""
Cache the configuration data.
"""
cache.set('config', self.data, None)
cache.set('config_version', self.pk, None)
activate.alters_data = True
@property
def is_active(self):
return cache.get('config_version') == self.pk

View File

@ -1,7 +1,7 @@
from django.contrib import messages from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from extras.models import ConfigRevision from core.models import ConfigRevision
from netbox.config import get_config from netbox.config import get_config
from netbox.views import generic from netbox.views import generic
from netbox.views.generic.base import BaseObjectView from netbox.views.generic.base import BaseObjectView

View File

@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
from django.db.models import Q from django.db.models import Q
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from core.models import DataSource from core.models import ConfigRevision, DataSource
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup

View File

@ -6,7 +6,7 @@ from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from core.forms.mixins import SyncedDataMixin from core.forms.mixins import SyncedDataMixin
from core.models import ContentType from core.models import ConfigRevision, ContentType
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
from extras.choices import * from extras.choices import *
from extras.models import * from extras.models import *

View File

@ -0,0 +1,24 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('extras', '0100_customfield_ui_attrs'),
]
operations = [
migrations.SeparateDatabaseAndState(
state_operations=[
migrations.DeleteModel(
name='ConfigRevision',
),
],
database_operations=[
migrations.AlterModelTable(
name='ConfigRevision',
table='core_configrevision',
),
],
),
]

View File

@ -3,14 +3,13 @@ import urllib.parse
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.cache import cache
from django.core.validators import ValidationError from django.core.validators import ValidationError
from django.db import models from django.db import models
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.formats import date_format from django.utils.formats import date_format
from django.utils.translation import gettext, gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework.utils.encoders import JSONEncoder from rest_framework.utils.encoders import JSONEncoder
from core.models import ContentType from core.models import ContentType
@ -28,7 +27,6 @@ from utilities.utils import clean_html, dict_to_querydict, render_jinja2
__all__ = ( __all__ = (
'Bookmark', 'Bookmark',
'ConfigRevision',
'CustomLink', 'CustomLink',
'ExportTemplate', 'ExportTemplate',
'ImageAttachment', 'ImageAttachment',
@ -710,59 +708,3 @@ class Bookmark(models.Model):
raise ValidationError( raise ValidationError(
_("Bookmarks cannot be assigned to this object type ({type}).").format(type=self.object_type) _("Bookmarks cannot be assigned to this object type ({type}).").format(type=self.object_type)
) )
class ConfigRevision(models.Model):
"""
An atomic revision of NetBox's configuration.
"""
created = models.DateTimeField(
verbose_name=_('created'),
auto_now_add=True
)
comment = models.CharField(
verbose_name=_('comment'),
max_length=200,
blank=True
)
data = models.JSONField(
blank=True,
null=True,
verbose_name=_('configuration data')
)
objects = RestrictedQuerySet.as_manager()
class Meta:
ordering = ['-created']
verbose_name = _('config revision')
verbose_name_plural = _('config revisions')
def __str__(self):
if not self.pk:
return gettext('Default configuration')
if self.is_active:
return gettext('Current configuration')
return gettext('Config revision #{id}').format(id=self.pk)
def __getattr__(self, item):
if item in self.data:
return self.data[item]
return super().__getattribute__(item)
def get_absolute_url(self):
if not self.pk:
return reverse('core:config') # Default config view
return reverse('extras:configrevision', args=[self.pk])
def activate(self):
"""
Cache the configuration data.
"""
cache.set('config', self.data, None)
cache.set('config_version', self.pk, None)
activate.alters_data = True
@property
def is_active(self):
return cache.get('config_version') == self.pk

View File

@ -8,13 +8,14 @@ from django.dispatch import receiver, Signal
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_prometheus.models import model_deletes, model_inserts, model_updates from django_prometheus.models import model_deletes, model_inserts, model_updates
from core.models import ConfigRevision
from extras.validators import CustomValidator from extras.validators import CustomValidator
from netbox.config import get_config from netbox.config import get_config
from netbox.context import current_request, webhooks_queue from netbox.context import current_request, webhooks_queue
from netbox.signals import post_clean from netbox.signals import post_clean
from utilities.exceptions import AbortRequest from utilities.exceptions import AbortRequest
from .choices import ObjectChangeActionChoices from .choices import ObjectChangeActionChoices
from .models import ConfigRevision, CustomField, ObjectChange, TaggedItem from .models import CustomField, ObjectChange, TaggedItem
from .webhooks import enqueue_object, get_snapshots, serialize_for_webhook from .webhooks import enqueue_object, get_snapshots, serialize_for_webhook
# #

View File

@ -4,6 +4,7 @@ import django_tables2 as tables
from django.conf import settings from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from core.models import ConfigRevision
from extras.models import * from extras.models import *
from netbox.tables import NetBoxTable, columns from netbox.tables import NetBoxTable, columns
from .template_code import * from .template_code import *

View File

@ -11,7 +11,7 @@ from django.views.generic import View
from core.choices import JobStatusChoices, ManagedFileRootPathChoices from core.choices import JobStatusChoices, ManagedFileRootPathChoices
from core.forms import ManagedFileForm from core.forms import ManagedFileForm
from core.models import Job from core.models import ConfigRevision, Job
from core.tables import JobTable from core.tables import JobTable
from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm
from extras.dashboard.utils import get_widget_class from extras.dashboard.utils import get_widget_class

View File

@ -74,7 +74,7 @@ class Config:
def _populate_from_db(self): def _populate_from_db(self):
"""Cache data from latest ConfigRevision, then populate from cache""" """Cache data from latest ConfigRevision, then populate from cache"""
from extras.models import ConfigRevision from core.models import ConfigRevision
try: try:
revision = ConfigRevision.objects.last() revision = ConfigRevision.objects.last()

View File

@ -2,7 +2,7 @@ from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.test import override_settings, TestCase from django.test import override_settings, TestCase
from extras.models import ConfigRevision from core.models import ConfigRevision
from netbox.config import clear_config, get_config from netbox.config import clear_config, get_config