Skip to content

Commit

Permalink
Merge pull request #86 from DanSheps/develop-3.7
Browse files Browse the repository at this point in the history
Fix issue with annotations
  • Loading branch information
DanSheps authored Jan 23, 2024
2 parents 5e25005 + 031cd10 commit 0fbc0a3
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 114 deletions.
3 changes: 2 additions & 1 deletion netbox_config_backup/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from netbox_config_backup.models.backups import Backup, BackupCommit, BackupFile, BackupObject, BackupCommitTreeChange
from netbox_config_backup.models.backups import Backup
from netbox_config_backup.models.repository import BackupCommit, BackupFile, BackupObject, BackupCommitTreeChange
from netbox_config_backup.models.jobs import BackupJob


Expand Down
92 changes: 4 additions & 88 deletions netbox_config_backup/models/backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
from extras.choices import JobResultStatusChoices
from netbox.models import NetBoxModel

from netbox_config_backup.choices import FileTypeChoices, CommitTreeChangeTypeChoices, StatusChoices
from netbox_config_backup.choices import StatusChoices
from netbox_config_backup.helpers import get_repository_dir
from utilities.querysets import RestrictedQuerySet

from .abstract import BigIDModel
from netbox_config_backup.utils.rq import remove_queued
from ..querysets import BackupQuerySet
from ..utils import Differ

logger = logging.getLogger(f"netbox_config_backup")
Expand All @@ -44,31 +43,11 @@ class Backup(NetBoxModel):
null=True
)

objects = RestrictedQuerySet.as_manager()
objects = BackupQuerySet.as_manager()

class Meta:
ordering = ['name']

@property
def last_backup(self):
job = self.jobs.filter(status=JobResultStatusChoices.STATUS_COMPLETED).order_by('completed').last()
if job is not None:
return job.completed
return None

@property
def next_attempt(self):
job = self.jobs.filter(status__in=['pending', 'running']).order_by('scheduled').last()
if job is not None:
return job.scheduled
return None

@property
def last_change(self):
if self.changes.count() == 0:
return None
return self.changes.last().commit.time

@property
def backup_count(self):
return self.changes.count()
Expand All @@ -89,12 +68,6 @@ def enqueue_if_needed(self):
from netbox_config_backup.utils.rq import enqueue_if_needed
return enqueue_if_needed(self)

def clean(self):
if not self.device and self.ip:
self.ip = None

super().clean()

def requeue(self):
self.jobs.filter(
~Q(status=JobResultStatusChoices.STATUS_COMPLETED) &
Expand Down Expand Up @@ -195,61 +168,4 @@ def set_config(self, configs, files=('running', 'startup'), pk=None):

@classmethod
def get_repository_dir(cls):
return get_repository_dir()


class BackupCommit(BigIDModel):
sha = models.CharField(max_length=64)
time = models.DateTimeField()

def __str__(self):
return self.sha


class BackupObject(BigIDModel):
sha = models.CharField(max_length=64, unique=True)

def __str__(self):
return f'{self.sha}'


class BackupFile(BigIDModel):
backup = models.ForeignKey(to=Backup, on_delete=models.CASCADE, null=False, blank=False, related_name='files')
type = models.CharField(max_length=10, choices=FileTypeChoices, null=False, blank=False)

class Meta:
unique_together = ['backup', 'type']

def __str__(self):
return f'{self.name}.{self.type}'

@property
def name(self):
return f'{self.backup.uuid}'

@property
def path(self):
return f'{self.name}.{self.type}'


class BackupCommitTreeChange(BigIDModel):
backup = models.ForeignKey(to=Backup, on_delete=models.CASCADE, null=False, blank=False, related_name='changes')
file = models.ForeignKey(to=BackupFile, on_delete=models.CASCADE, null=False, blank=False, related_name='changes')

commit = models.ForeignKey(to=BackupCommit, on_delete=models.PROTECT, related_name='changes')
type = models.CharField(max_length=10)
old = models.ForeignKey(to=BackupObject, on_delete=models.PROTECT, related_name='previous', null=True)
new = models.ForeignKey(to=BackupObject, on_delete=models.PROTECT, related_name='changes', null=True)

def __str__(self):
return f'{self.commit.sha}-{self.type}'

def filename(self):
return f'{self.backup.uuid}.{self.type}'

def get_absolute_url(self):
return reverse('plugins:netbox_config_backup:backup_config', kwargs={'backup': self.backup.pk, 'current': self.pk})

@property
def previous(self):
return self.backup.changes.filter(file__type=self.file.type, commit__time__lt=self.commit.time).last()
return get_repository_dir()
63 changes: 63 additions & 0 deletions netbox_config_backup/models/repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from django.db import models
from django.urls import reverse

from netbox_config_backup.choices import FileTypeChoices
from netbox_config_backup.models import Backup
from netbox_config_backup.models.abstract import BigIDModel


class BackupCommit(BigIDModel):
sha = models.CharField(max_length=64)
time = models.DateTimeField()

def __str__(self):
return self.sha


class BackupObject(BigIDModel):
sha = models.CharField(max_length=64, unique=True)

def __str__(self):
return f'{self.sha}'


class BackupFile(BigIDModel):
backup = models.ForeignKey(to=Backup, on_delete=models.CASCADE, null=False, blank=False, related_name='files')
type = models.CharField(max_length=10, choices=FileTypeChoices, null=False, blank=False)

class Meta:
unique_together = ['backup', 'type']

def __str__(self):
return f'{self.name}.{self.type}'

@property
def name(self):
return f'{self.backup.uuid}'

@property
def path(self):
return f'{self.name}.{self.type}'


class BackupCommitTreeChange(BigIDModel):
backup = models.ForeignKey(to=Backup, on_delete=models.CASCADE, null=False, blank=False, related_name='changes')
file = models.ForeignKey(to=BackupFile, on_delete=models.CASCADE, null=False, blank=False, related_name='changes')

commit = models.ForeignKey(to=BackupCommit, on_delete=models.PROTECT, related_name='changes')
type = models.CharField(max_length=10)
old = models.ForeignKey(to=BackupObject, on_delete=models.PROTECT, related_name='previous', null=True)
new = models.ForeignKey(to=BackupObject, on_delete=models.PROTECT, related_name='changes', null=True)

def __str__(self):
return f'{self.commit.sha}-{self.type}'

def filename(self):
return f'{self.backup.uuid}.{self.type}'

def get_absolute_url(self):
return reverse('plugins:netbox_config_backup:backup_config', kwargs={'backup': self.backup.pk, 'current': self.pk})

@property
def previous(self):
return self.backup.changes.filter(file__type=self.file.type, commit__time__lt=self.commit.time).last()
22 changes: 22 additions & 0 deletions netbox_config_backup/querysets/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import models

from extras.choices import JobResultStatusChoices
from utilities.querysets import RestrictedQuerySet



class BackupQuerySet(RestrictedQuerySet):
def default_annotate(self):
from netbox_config_backup.models import BackupJob, BackupCommitTreeChange

return self.prefetch_related('jobs').annotate(
last_backup=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status=JobResultStatusChoices.STATUS_COMPLETED).order_by('completed').values('completed')[:1]
),
next_attempt=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status__in=['pending', 'running']).order_by('scheduled').values('scheduled')[:1]
),
last_change=models.Subquery(
BackupCommitTreeChange.objects.filter(backup=models.OuterRef('id')).values('commit__time')[:1]
)
)
30 changes: 6 additions & 24 deletions netbox_config_backup/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,7 @@


class BackupListView(ObjectListView):
queryset = Backup.objects.filter(device__isnull=False).prefetch_related('jobs').annotate(
last_backup=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status=JobResultStatusChoices.STATUS_COMPLETED).order_by('completed').values('completed')[:1]
),
next_attempt=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status__in=['pending', 'running']).order_by('scheduled').values('scheduled')[:1]
),
last_change=models.Subquery(
BackupCommitTreeChange.objects.filter(backup=models.OuterRef('id')).values('commit__time')[:1]
)
)
queryset = Backup.objects.filter(device__isnull=False).default_annotate()

filterset = BackupFilterSet
filterset_form = BackupFilterSetForm
Expand All @@ -40,17 +30,8 @@ class BackupListView(ObjectListView):


class UnassignedBackupListView(ObjectListView):
queryset = Backup.objects.filter(device__isnull=True).annotate(
last_backup=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status=JobResultStatusChoices.STATUS_COMPLETED).order_by('completed').values('completed')[:1]
),
next_attempt=models.Subquery(
BackupJob.objects.filter(backup=models.OuterRef('id'), status__in=['pending', 'running']).order_by('scheduled').values('scheduled')[:1]
),
last_change=models.Subquery(
BackupCommitTreeChange.objects.filter(backup=models.OuterRef('id')).values('commit__time')[:1]
)
)
queryset = Backup.objects.filter(device__isnull=True).default_annotate()

filterset = BackupFilterSet
filterset_form = BackupFilterSetForm
table = BackupTable
Expand All @@ -59,7 +40,7 @@ class UnassignedBackupListView(ObjectListView):

@register_model_view(Backup)
class BackupView(ObjectView):
queryset = Backup.objects.all()
queryset = Backup.objects.all().default_annotate()
template_name = 'netbox_config_backup/backup.html'

def get_extra_context(self, request, instance):
Expand Down Expand Up @@ -94,7 +75,8 @@ def get_extra_context(self, request, instance):

@register_model_view(Backup, name='backups')
class BackupBackupsView(ObjectChildrenView):
queryset = Backup.objects.all()
queryset = Backup.objects.all().default_annotate()

template_name = 'netbox_config_backup/backups.html'
child_model = BackupCommitTreeChange
table = BackupsTable
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='netbox_config_backup',
version='1.5.2',
version='1.5.3',
description='NetBox Configuration Backup',
long_description='Plugin to backup device configuration',
url='https://github.com/dansheps/netbox-config-backup/',
Expand Down

0 comments on commit 0fbc0a3

Please sign in to comment.