backups: Make all generated archive names consistent

- For scheduled backups and automatic backups generated when uninstalling apps,
make the generated archive name similar to automatic name given no name is
specified when creating an archive.

Tests:

- Set schedule on a local repository, uninstall an application, and create a
backup archive without a name. The timestamp in generated backup archives in all
three cases is similar in format.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2025-01-06 16:41:03 -08:00 committed by James Valleroy
parent d710ab0790
commit 28e4fe0791
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
5 changed files with 21 additions and 14 deletions

View File

@ -241,6 +241,11 @@ class BaseBorgRepository(abc.ABC):
return None
def generate_archive_name(self):
"""Return a name to create a backup archive with using time."""
return datetime.datetime.now().astimezone().replace(
microsecond=0).isoformat()
def get_archive_apps(self, archive_name):
"""Get list of apps included in an archive."""
archive_path = self._get_archive_path(archive_name)

View File

@ -274,12 +274,14 @@ class Schedule:
logger.info('Running backup for repository %s, periods %s',
self.repository_uuid, periods)
repository = self._get_repository()
from . import api
periods = list(periods)
periods.sort()
name = 'scheduled: {periods}: {datetime}'.format(
name = 'scheduled: {periods}: {name}'.format(
periods=', '.join(periods),
datetime=datetime.now().strftime('%Y-%m-%d:%H:%M'))
name=repository.generate_archive_name())
comment = self._serialize_comment({
'type': 'scheduled',
'periods': periods
@ -290,7 +292,6 @@ class Schedule:
if component.app_id not in self.unselected_apps
]
repository = self._get_repository()
repository.create_archive(name, app_ids, archive_comment=comment)
def _run_cleanup(self, repository):

View File

@ -9,7 +9,7 @@ from unittest.mock import MagicMock, call, patch
import pytest
import plinth.modules.backups.repository # noqa, pylint: disable=unused-import
import plinth.modules.backups.repository as repository_module
from plinth.app import App
from ..components import BackupRestore
@ -431,15 +431,19 @@ def test_run_schedule(get_instance, get_setup_state, schedule_params,
repository.list_archives.side_effect = \
lambda: _get_archives_from_test_data(archives_data)
get_instance.return_value = repository
repository.generate_archive_name = lambda: \
repository_module.BaseBorgRepository.generate_archive_name(None)
with patch('plinth.modules.backups.schedule.datetime') as mock_datetime, \
patch('plinth.app.App.list') as app_list:
patch('plinth.modules.backups.repository.datetime') \
as repo_datetime, patch('plinth.app.App.list') as app_list:
app_list.return_value = [
_get_test_app('test-app1'),
_get_test_app('test-app2'),
_get_test_app('test-app3')
]
repo_datetime.datetime.now.return_value = test_now
mock_datetime.now.return_value = test_now
mock_datetime.strptime = datetime.strptime
mock_datetime.min = datetime.min
@ -458,7 +462,8 @@ def test_run_schedule(get_instance, get_setup_state, schedule_params,
run_periods.sort()
name = 'scheduled: {periods}: {datetime}'.format(
periods=', '.join(run_periods),
datetime=mock_datetime.now().strftime('%Y-%m-%d:%H:%M'))
datetime=repo_datetime.datetime.now().astimezone().replace(
microsecond=0).isoformat())
app_ids = ['test-app1', 'test-app3']
archive_comment = json.dumps({
'type': 'scheduled',

View File

@ -7,7 +7,6 @@ import contextlib
import logging
import os
import subprocess
from datetime import datetime
from urllib.parse import unquote
from django.contrib import messages
@ -141,8 +140,7 @@ class CreateArchiveView(FormView):
name = form.cleaned_data['name']
if not name:
name = datetime.now().astimezone().replace(
microsecond=0).isoformat()
name = repository.generate_archive_name()
selected_apps = form.cleaned_data['selected_apps']
with handle_common_errors(self.request):

View File

@ -3,7 +3,6 @@
Main FreedomBox views.
"""
import datetime
import random
import time
import traceback
@ -607,10 +606,9 @@ class UninstallView(FormView):
if repository.flags.get('mountable'):
repository.mount()
name = datetime.datetime.now().strftime(
'%Y-%m-%d:%H:%M:%S') + ' ' + str(
_('before uninstall of {app_id}')).format(
app_id=self.app.app_id)
name = repository.generate_archive_name() + ' ' + str(
_('before uninstall of {app_id}')).format(
app_id=self.app.app_id)
repository.create_archive(name, [self.app.app_id])
# Uninstall