From 37633008cb05ebfe9c617c848e119d67fdd32e7e Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 9 Nov 2022 10:30:44 +0100 Subject: [PATCH] Fixed restore mode --- .github/workflows/installer.yml | 60 ++++++++++++++++++++++++++ .travis.yml | 15 ------- README.rst | 27 +++++------- modoboa_installer/scripts/__init__.py | 8 ++-- modoboa_installer/scripts/amavis.py | 6 +-- modoboa_installer/scripts/base.py | 12 +++--- modoboa_installer/scripts/dovecot.py | 2 +- modoboa_installer/scripts/opendkim.py | 26 +++++------ modoboa_installer/scripts/postfix.py | 2 +- modoboa_installer/scripts/postwhite.py | 2 +- modoboa_installer/scripts/radicale.py | 4 +- run.py | 2 +- 12 files changed, 103 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/installer.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/installer.yml b/.github/workflows/installer.yml new file mode 100644 index 0000000..df9bfd6 --- /dev/null +++ b/.github/workflows/installer.yml @@ -0,0 +1,60 @@ +name: Modoboa installer + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.7, 3.8, 3.9] + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + pip install -r test-requirements.txt + - name: Run tests + if: ${{ matrix.python-version != '3.9' }} + run: | + python tests.py + - name: Run tests and coverage + if: ${{ matrix.python-version == '3.9' }} + run: | + coverage run tests.py + - name: Upload coverage result + if: ${{ matrix.python-version == '3.9' }} + uses: actions/upload-artifact@v2 + with: + name: coverage-results + path: .coverage + + coverage: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: Install dependencies + run: | + pip install codecov + - name: Download coverage results + uses: actions/download-artifact@v2 + with: + name: coverage-results + - name: Report coverage + run: | + coverage report + codecov diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 641df12..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -sudo: false -language: python -cache: pip -python: - - "2.7" - - "3.4" - -before_install: - - pip install -r test-requirements.txt - -script: - - coverage run tests.py - -after_success: - - codecov diff --git a/README.rst b/README.rst index e2af8c7..5fa04ed 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ modoboa-installer ================= -|travis| |codecov| +|workflow| |codecov| An installer which deploy a complete mail server based on Modoboa. @@ -100,7 +100,7 @@ An experimental backup mode is available. .. warning:: You must keep the original configuration file, i.e. the one used for - the installation. Otherwise, you will need to recreate it manually with the right information ! + the installation. Otherwise, you will need to recreate it manually with the right information! You can start the process as follows:: @@ -108,7 +108,7 @@ You can start the process as follows:: Then follow the step on the console. -There are also a non-interactive mode: +There is also a non-interactive mode: 1. Silent mode @@ -116,21 +116,17 @@ Command:: $ sudo ./run.py --silent-backup -This mode is the silent batch mode, when executed, it will create /modoboa_backup/ and each time you execute it, it will create a new backup directory with current date and time. +This mode will run silently. When executed, it will create +/modoboa_backup/ and each time you execute it, it will create a new +backup directory with current date and time. -You can supply a custom path. - -Command:: +You can supply a custom path if needed:: $ sudo ./run.py --silent-backup --backup-path /path/of/backup/directory -This mode is the same as silent batch mode, but you provide the path to the backup directory you want. +If you want to disable emails backup, disable dovecot in the +configuration file (set enabled to False). - -If you want to disable mail backup:: - - $ sudo ./run.py {--backup|--silent-backup} --no-mail-backup - This can be useful for larger instance. Restore mode @@ -142,7 +138,7 @@ You can start the process as follows:: $ sudo ./run.py --restore /path/to/backup/directory/ -Then wait for the process to finish +Then wait for the process to finish. Change the generated hostname ----------------------------- @@ -187,7 +183,6 @@ modify the following settings:: Change the ``email`` setting to a valid value since it will be used for account recovery. -.. |travis| image:: https://travis-ci.org/modoboa/modoboa-installer.png?branch=master - :target: https://travis-ci.org/modoboa/modoboa-installer +.. |workflow| image:: https://github.com/modoboa/modoboa-installer/workflows/Modoboa%20installer/badge.svg .. |codecov| image:: http://codecov.io/github/modoboa/modoboa-installer/coverage.svg?branch=master :target: http://codecov.io/github/modoboa/modoboa-installer?branch=master diff --git a/modoboa_installer/scripts/__init__.py b/modoboa_installer/scripts/__init__.py index 8cf0047..d006f4c 100644 --- a/modoboa_installer/scripts/__init__.py +++ b/modoboa_installer/scripts/__init__.py @@ -17,7 +17,7 @@ def load_app_script(appname): return script -def install(appname, config, upgrade, restore): +def install(appname: str, config, upgrade: bool, archive_path: str): """Install an application.""" if (config.has_option(appname, "enabled") and not config.getboolean(appname, "enabled")): @@ -26,9 +26,9 @@ def install(appname, config, upgrade, restore): utils.printcolor("Installing {}".format(appname), utils.MAGENTA) script = load_app_script(appname) try: - getattr(script, appname.capitalize())(config, upgrade, restore).run() + getattr(script, appname.capitalize())(config, upgrade, archive_path).run() except utils.FatalError as inst: - utils.printcolor(u"{}".format(inst), utils.RED) + utils.error("{}".format(inst)) sys.exit(1) @@ -43,7 +43,7 @@ def backup(appname, config, path): try: getattr(script, appname.capitalize())(config, False, False).backup(path) except utils.FatalError as inst: - utils.printcolor(u"{}".format(inst), utils.RED) + utils.error("{}".format(inst)) sys.exit(1) diff --git a/modoboa_installer/scripts/amavis.py b/modoboa_installer/scripts/amavis.py index 662d453..897fbda 100644 --- a/modoboa_installer/scripts/amavis.py +++ b/modoboa_installer/scripts/amavis.py @@ -92,8 +92,8 @@ class Amavis(base.Installer): def post_run(self): """Additional tasks.""" - install("spamassassin", self.config, self.upgrade, self.restore) - install("clamav", self.config, self.upgrade, self.restore) + install("spamassassin", self.config, self.upgrade, self.archive_path) + install("clamav", self.config, self.upgrade, self.archive_path) def custom_backup(self, path): """Backup custom configuration if any.""" @@ -109,7 +109,7 @@ class Amavis(base.Installer): if package.backend.FORMAT != "deb": return amavis_custom_configuration = os.path.join( - self.restore, "custom/99-custom") + self.archive_path, "custom/99-custom") if os.path.isfile(amavis_custom_configuration): utils.copy_file(amavis_custom_configuration, os.path.join( self.config_dir, "conf.d")) diff --git a/modoboa_installer/scripts/base.py b/modoboa_installer/scripts/base.py index 00b68fe..dea0897 100644 --- a/modoboa_installer/scripts/base.py +++ b/modoboa_installer/scripts/base.py @@ -20,11 +20,11 @@ class Installer(object): with_db = False config_files = [] - def __init__(self, config, upgrade, restore): + def __init__(self, config, upgrade: bool, archive_path: str): """Get configuration.""" self.config = config self.upgrade = upgrade - self.restore = restore + self.archive_path = archive_path if self.config.has_section(self.appname): self.app_config = dict(self.config.items(self.appname)) self.dbengine = self.config.get("database", "engine") @@ -61,7 +61,7 @@ class Installer(object): utils.MAGENTA ) database_backup_path = os.path.join( - self.restore, f"databases/{self.appname}.sql") + self.archive_path, f"databases/{self.appname}.sql") if os.path.isfile(database_backup_path): utils.success(f"SQL dump found in backup for {self.appname}!") return database_backup_path @@ -81,7 +81,7 @@ class Installer(object): self.backend.create_user(self.dbuser, self.dbpasswd) self.backend.create_database(self.dbname, self.dbuser) schema = None - if self.restore: + if self.archive_path: schema = self.get_sql_schema_from_backup() if not schema: schema = self.get_sql_schema_path() @@ -188,9 +188,9 @@ class Installer(object): if not self.upgrade: self.setup_database() self.install_config_files() - if self.restore: - self.restore() self.post_run() + if self.archive_path: + self.restore() self.restart_daemon() def _dump_database(self, backup_path: str): diff --git a/modoboa_installer/scripts/dovecot.py b/modoboa_installer/scripts/dovecot.py index 628d0c6..a1f5988 100644 --- a/modoboa_installer/scripts/dovecot.py +++ b/modoboa_installer/scripts/dovecot.py @@ -153,7 +153,7 @@ class Dovecot(base.Installer): def restore(self): """Restore emails.""" home_dir = self.config.get("dovecot", "home_dir") - mail_dir = os.path.join(self.restore, "mails/") + mail_dir = os.path.join(self.archive_path, "mails/") if len(os.listdir(mail_dir)) > 0: utils.success("Copying mail backup over dovecot directory.") if os.path.exists(home_dir): diff --git a/modoboa_installer/scripts/opendkim.py b/modoboa_installer/scripts/opendkim.py index 9ad394b..0379221 100644 --- a/modoboa_installer/scripts/opendkim.py +++ b/modoboa_installer/scripts/opendkim.py @@ -47,19 +47,7 @@ class Opendkim(base.Installer): stat.S_IROTH | stat.S_IXOTH, target[1], target[2] ) - # Restore dkim keys from backup if restoring - if self.restore is not None: - dkim_keys_backup = os.path.join( - self.restore, "custom/dkim") - if os.path.isdir(dkim_keys_backup): - for file in os.listdir(dkim_keys_backup): - file_path = os.path.join(dkim_keys_backup, file) - if os.path.isfile(file_path): - utils.copy_file(file_path, self.config.get( - "opendkim", "keys_storage_dir", fallback="/var/lib/dkim")) - utils.printcolor( - "DKIM keys restored from backup", utils.GREEN) - super(Opendkim, self).install_config_files() + super().install_config_files() def get_template_context(self): """Additional variables.""" @@ -123,6 +111,18 @@ class Opendkim(base.Installer): utils.exec_cmd( "perl -pi -e '{}' /lib/systemd/system/opendkim.service".format(pattern)) + def restore(self): + """Restore keys.""" + dkim_keys_backup = os.path.join( + self.archive_path, "custom/dkim") + if os.path.isdir(dkim_keys_backup): + for file in os.listdir(dkim_keys_backup): + file_path = os.path.join(dkim_keys_backup, file) + if os.path.isfile(file_path): + utils.copy_file(file_path, self.config.get( + "opendkim", "keys_storage_dir", fallback="/var/lib/dkim")) + utils.success("DKIM keys restored from backup") + def custom_backup(self, path): """Backup DKIM keys.""" storage_dir = self.config.get( diff --git a/modoboa_installer/scripts/postfix.py b/modoboa_installer/scripts/postfix.py index 52e9aa3..a14e234 100644 --- a/modoboa_installer/scripts/postfix.py +++ b/modoboa_installer/scripts/postfix.py @@ -97,7 +97,7 @@ class Postfix(base.Installer): utils.exec_cmd("postalias {}".format(aliases_file)) # Postwhite - install("postwhite", self.config, self.upgrade, self.restore) + install("postwhite", self.config, self.upgrade, self.archive_path) def backup(self, path): """Launch postwhite backup.""" diff --git a/modoboa_installer/scripts/postwhite.py b/modoboa_installer/scripts/postwhite.py index 650708a..30bcb14 100644 --- a/modoboa_installer/scripts/postwhite.py +++ b/modoboa_installer/scripts/postwhite.py @@ -61,7 +61,7 @@ class Postwhite(base.Installer): def restore(self): """Restore config files.""" postwhite_backup_configuration = os.path.join( - self.restore, "custom/postwhite.conf") + self.archive_path, "custom/postwhite.conf") if os.path.isfile(postwhite_backup_configuration): utils.copy_file(postwhite_backup_configuration, self.config_dir) utils.success("postwhite.conf restored from backup") diff --git a/modoboa_installer/scripts/radicale.py b/modoboa_installer/scripts/radicale.py index fa20959..a0ca309 100644 --- a/modoboa_installer/scripts/radicale.py +++ b/modoboa_installer/scripts/radicale.py @@ -26,7 +26,7 @@ class Radicale(base.Installer): def __init__(self, *args, **kwargs): """Get configuration.""" - super(Radicale, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.venv_path = self.config.get("radicale", "venv_path") def _setup_venv(self): @@ -76,7 +76,7 @@ class Radicale(base.Installer): def restore(self): """Restore collections.""" radicale_backup = os.path.join( - self.restore, "custom/radicale") + self.archive_path, "custom/radicale") if os.path.isdir(radicale_backup): restore_target = os.path.join(self.home_dir, "collections") if os.path.isdir(restore_target): diff --git a/run.py b/run.py index b4ac09d..88c7ed6 100755 --- a/run.py +++ b/run.py @@ -72,7 +72,7 @@ def backup_disclaimer(): def restore_disclaimer(): """Display restore disclamer. """ utils.printcolor( - "You are about to restore a previous installation of Modoboa." + "You are about to restore a previous installation of Modoboa.\n" "If a new version has been released in between, please update your database!", utils.BLUE)