mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
backups: List apps that don't require backup too
- This serves two purposes. First is to assure user in the interface that backup of the module is not required. Second is to make sure that if an application is installed during backup it is also reinstalled during restore process (this need to be implemented). - Allow backup test to run independently. Initialize the cfg module so that load_modules() works. Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
26764b7370
commit
8d7ede728e
@ -202,7 +202,11 @@ def get_all_apps_for_backup():
|
||||
if not hasattr(module, 'backup'):
|
||||
continue
|
||||
|
||||
apps.append((module_name, module))
|
||||
apps.append({
|
||||
'name': module_name,
|
||||
'app': module,
|
||||
'has_data': bool(module.backup)
|
||||
})
|
||||
|
||||
return apps
|
||||
|
||||
|
||||
@ -23,12 +23,26 @@ import os
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.core.validators import FileExtensionValidator
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from . import api
|
||||
from . import get_export_locations, get_archive_path, get_location_path
|
||||
|
||||
|
||||
def _get_app_choices(apps):
|
||||
"""Return a list of check box multiple choices from list of apps."""
|
||||
choices = []
|
||||
for app in apps:
|
||||
name = app['app'].name
|
||||
if not app['has_data']:
|
||||
name = ugettext('{app} (No data to backup)').format(
|
||||
app=app['app'].name)
|
||||
|
||||
choices.append((app['name'], name))
|
||||
|
||||
return choices
|
||||
|
||||
|
||||
class CreateArchiveForm(forms.Form):
|
||||
name = forms.CharField(
|
||||
label=_('Archive name'), strip=True,
|
||||
@ -37,17 +51,15 @@ class CreateArchiveForm(forms.Form):
|
||||
])
|
||||
|
||||
selected_apps = forms.MultipleChoiceField(
|
||||
label=_('Included apps'),
|
||||
help_text=_('Apps to include in the backup'),
|
||||
label=_('Included apps'), help_text=_('Apps to include in the backup'),
|
||||
widget=forms.CheckboxSelectMultiple)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the form with selectable apps."""
|
||||
super().__init__(*args, **kwargs)
|
||||
apps = api.get_all_apps_for_backup()
|
||||
self.fields['selected_apps'].choices = [
|
||||
(app[0], app[1].name) for app in apps]
|
||||
self.fields['selected_apps'].initial = [app[0] for app in apps]
|
||||
self.fields['selected_apps'].choices = _get_app_choices(apps)
|
||||
self.fields['selected_apps'].initial = [app['name'] for app in apps]
|
||||
|
||||
|
||||
class ExportArchiveForm(forms.Form):
|
||||
@ -72,9 +84,8 @@ class RestoreForm(forms.Form):
|
||||
"""Initialize the form with selectable apps."""
|
||||
apps = kwargs.pop('apps')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['selected_apps'].choices = [
|
||||
(app[0], app[1].name) for app in apps]
|
||||
self.fields['selected_apps'].initial = [app[0] for app in apps]
|
||||
self.fields['selected_apps'].choices = _get_app_choices(apps)
|
||||
self.fields['selected_apps'].initial = [app['name'] for app in apps]
|
||||
|
||||
|
||||
class UploadForm(forms.Form):
|
||||
|
||||
@ -23,7 +23,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
|
||||
from plinth import cfg, module_loader
|
||||
from plinth.errors import PlinthError
|
||||
from plinth.module_loader import load_modules
|
||||
from .. import api, forms, get_export_locations, get_location_path
|
||||
@ -52,6 +52,12 @@ def _get_test_manifest(name):
|
||||
class TestBackupProcesses(unittest.TestCase):
|
||||
"""Test cases for backup processes"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Setup all the test cases."""
|
||||
super().setUpClass()
|
||||
cfg.read()
|
||||
|
||||
@staticmethod
|
||||
def test_packet_process_manifests():
|
||||
"""Test that directories/files are collected from manifests."""
|
||||
@ -82,13 +88,34 @@ class TestBackupProcesses(unittest.TestCase):
|
||||
api.restore_apps(restore_handler)
|
||||
restore_handler.assert_called_once()
|
||||
|
||||
@staticmethod
|
||||
def test_get_all_apps_for_backups():
|
||||
"""Test that apps supporting backup are included in returned list."""
|
||||
load_modules()
|
||||
apps = api.get_all_apps_for_backup()
|
||||
assert isinstance(apps, list)
|
||||
# apps may be empty, if no apps supporting backup are installed.
|
||||
@patch('plinth.module_loader.loaded_modules.items')
|
||||
def test_get_all_apps_for_backup(self, modules):
|
||||
"""Test listing apps supporting backup and needing backup."""
|
||||
apps = [
|
||||
('a', MagicMock(backup=_get_test_manifest('a'))),
|
||||
('b', MagicMock(backup=_get_test_manifest('b'))),
|
||||
('c', MagicMock(backup=None)),
|
||||
('d', MagicMock()),
|
||||
]
|
||||
del apps[3][1].backup
|
||||
modules.return_value = apps
|
||||
|
||||
module_loader.load_modules()
|
||||
returned_apps = api.get_all_apps_for_backup()
|
||||
expected_apps = [{
|
||||
'name': 'a',
|
||||
'app': apps[0][1],
|
||||
'has_data': True
|
||||
}, {
|
||||
'name': 'b',
|
||||
'app': apps[1][1],
|
||||
'has_data': True
|
||||
}, {
|
||||
'name': 'c',
|
||||
'app': apps[2][1],
|
||||
'has_data': False
|
||||
}]
|
||||
self.assertEqual(returned_apps, expected_apps)
|
||||
|
||||
def test_export_locations(self):
|
||||
"""Check get_export_locations returns a list of tuples of length 2."""
|
||||
@ -99,7 +126,7 @@ class TestBackupProcesses(unittest.TestCase):
|
||||
@staticmethod
|
||||
def test__get_apps_in_order():
|
||||
"""Test that apps are listed in correct dependency order."""
|
||||
load_modules()
|
||||
module_loader.load_modules()
|
||||
app_names = ['config', 'names']
|
||||
apps = api._get_apps_in_order(app_names)
|
||||
ordered_app_names = [app[0] for app in apps]
|
||||
|
||||
@ -60,7 +60,7 @@ class IndexView(TemplateView):
|
||||
context['exports'] = backups.get_export_files()
|
||||
context['subsubmenu'] = subsubmenu
|
||||
apps = api.get_all_apps_for_backup()
|
||||
context['available_apps'] = [app[0] for app in apps]
|
||||
context['available_apps'] = [app['name'] for app in apps]
|
||||
return context
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ class RestoreView(SuccessMessageMixin, FormView):
|
||||
included_apps = self._get_included_apps()
|
||||
installed_apps = api.get_all_apps_for_backup()
|
||||
kwargs['apps'] = [
|
||||
app for app in installed_apps if app[0] in included_apps
|
||||
app for app in installed_apps if app['name'] in included_apps
|
||||
]
|
||||
return kwargs
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user