mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-23 07:56:44 -06:00
Move ConfigRevision model & write migrations
This commit is contained in:
parent
18422e1d26
commit
c4d87efdeb
@ -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):
|
||||||
|
31
netbox/core/migrations/0009_configrevision.py
Normal file
31
netbox/core/migrations/0009_configrevision.py
Normal 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=[],
|
||||||
|
),
|
||||||
|
]
|
@ -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 *
|
||||||
|
66
netbox/core/models/config.py
Normal file
66
netbox/core/models/config.py
Normal 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
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 *
|
||||||
|
24
netbox/extras/migrations/0101_move_configrevision.py
Normal file
24
netbox/extras/migrations/0101_move_configrevision.py
Normal 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',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -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 *
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user