mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 08:05:31 +02:00
Make common Installer base class (#5055)
* Add installer class * Add wrapped reverter methods to common.Installer. * Use Installer class in Apache plugin * Use Installer class in Nginx plugin * Don't create reverter in Apache and Nginx plugins
This commit is contained in:
@@ -13,7 +13,9 @@ from acme.jose import util as jose_util
|
||||
|
||||
from certbot import constants
|
||||
from certbot import crypto_util
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
from certbot import reverter
|
||||
from certbot import util
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -100,6 +102,102 @@ class Plugin(object):
|
||||
# other
|
||||
|
||||
|
||||
class Installer(Plugin):
|
||||
"""An installer base class with reverter methods defined.
|
||||
|
||||
Installer plugins do not have to inherit from this class.
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Installer, self).__init__(*args, **kwargs)
|
||||
self.reverter = reverter.Reverter(self.config)
|
||||
|
||||
def add_to_checkpoint(self, save_files, save_notes, temporary=False):
|
||||
"""Add files to a checkpoint.
|
||||
|
||||
:param set save_files: set of filepaths to save
|
||||
:param str save_notes: notes about changes during the save
|
||||
:param bool temporary: True if the files should be added to a
|
||||
temporary checkpoint rather than a permanent one. This is
|
||||
usually used for changes that will soon be reverted.
|
||||
|
||||
:raises .errors.PluginError: when unable to add to checkpoint
|
||||
|
||||
"""
|
||||
if temporary:
|
||||
checkpoint_func = self.reverter.add_to_temp_checkpoint
|
||||
else:
|
||||
checkpoint_func = self.reverter.add_to_checkpoint
|
||||
|
||||
try:
|
||||
checkpoint_func(save_files, save_notes)
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
def finalize_checkpoint(self, title):
|
||||
"""Timestamp and save changes made through the reverter.
|
||||
|
||||
:param str title: Title describing checkpoint
|
||||
|
||||
:raises .errors.PluginError: when an error occurs
|
||||
|
||||
"""
|
||||
try:
|
||||
self.reverter.finalize_checkpoint(title)
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
def recovery_routine(self):
|
||||
"""Revert all previously modified files.
|
||||
|
||||
Reverts all modified files that have not been saved as a checkpoint
|
||||
|
||||
:raises .errors.PluginError: If unable to recover the configuration
|
||||
|
||||
"""
|
||||
try:
|
||||
self.reverter.recovery_routine()
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
def revert_temporary_config(self):
|
||||
"""Rollback temporary checkpoint.
|
||||
|
||||
:raises .errors.PluginError: when unable to revert config
|
||||
|
||||
"""
|
||||
try:
|
||||
self.reverter.revert_temporary_config()
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
def rollback_checkpoints(self, rollback=1):
|
||||
"""Rollback saved checkpoints.
|
||||
|
||||
:param int rollback: Number of checkpoints to revert
|
||||
|
||||
:raises .errors.PluginError: If there is a problem with the input or
|
||||
the function is unable to correctly revert the configuration
|
||||
|
||||
"""
|
||||
try:
|
||||
self.reverter.rollback_checkpoints(rollback)
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
def view_config_changes(self):
|
||||
"""Show all of the configuration changes that have taken place.
|
||||
|
||||
:raises .errors.PluginError: If there is a problem while processing
|
||||
the checkpoints directories.
|
||||
|
||||
"""
|
||||
try:
|
||||
self.reverter.view_config_changes()
|
||||
except errors.ReverterError as err:
|
||||
raise errors.PluginError(str(err))
|
||||
|
||||
|
||||
class Addr(object):
|
||||
r"""Represents an virtual host address.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Tests for certbot.plugins.common."""
|
||||
import functools
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
@@ -12,6 +13,7 @@ from acme import jose
|
||||
|
||||
from certbot import achallenges
|
||||
from certbot import crypto_util
|
||||
from certbot import errors
|
||||
|
||||
from certbot.tests import acme_util
|
||||
from certbot.tests import util as test_util
|
||||
@@ -77,6 +79,91 @@ class PluginTest(unittest.TestCase):
|
||||
"--mock-foo-bar", dest="different_to_foo_bar", x=1, y=None)
|
||||
|
||||
|
||||
class InstallerTest(unittest.TestCase):
|
||||
"""Tests for certbot.plugins.common.Installer."""
|
||||
|
||||
def setUp(self):
|
||||
from certbot.plugins.common import Installer
|
||||
|
||||
with mock.patch("certbot.plugins.common.reverter.Reverter"):
|
||||
self.installer = Installer(config=mock.MagicMock(),
|
||||
name="Installer")
|
||||
self.reverter = self.installer.reverter
|
||||
|
||||
def test_add_to_real_checkpoint(self):
|
||||
files = set(("foo.bar", "baz.qux",))
|
||||
save_notes = "foo bar baz qux"
|
||||
self._test_wrapped_method("add_to_checkpoint", files, save_notes)
|
||||
|
||||
def test_add_to_real_checkpoint2(self):
|
||||
self._test_add_to_checkpoint_common(False)
|
||||
|
||||
def test_add_to_temporary_checkpoint(self):
|
||||
self._test_add_to_checkpoint_common(True)
|
||||
|
||||
def _test_add_to_checkpoint_common(self, temporary):
|
||||
files = set(("foo.bar", "baz.qux",))
|
||||
save_notes = "foo bar baz qux"
|
||||
|
||||
installer_func = functools.partial(self.installer.add_to_checkpoint,
|
||||
temporary=temporary)
|
||||
|
||||
if temporary:
|
||||
reverter_func = self.reverter.add_to_temp_checkpoint
|
||||
else:
|
||||
reverter_func = self.reverter.add_to_checkpoint
|
||||
|
||||
self._test_adapted_method(
|
||||
installer_func, reverter_func, files, save_notes)
|
||||
|
||||
def test_finalize_checkpoint(self):
|
||||
self._test_wrapped_method("finalize_checkpoint", "foo")
|
||||
|
||||
def test_recovery_routine(self):
|
||||
self._test_wrapped_method("recovery_routine")
|
||||
|
||||
def test_revert_temporary_config(self):
|
||||
self._test_wrapped_method("revert_temporary_config")
|
||||
|
||||
def test_rollback_checkpoints(self):
|
||||
self._test_wrapped_method("rollback_checkpoints", 42)
|
||||
|
||||
def test_view_config_changes(self):
|
||||
self._test_wrapped_method("view_config_changes")
|
||||
|
||||
def _test_wrapped_method(self, name, *args, **kwargs):
|
||||
"""Test a wrapped reverter method.
|
||||
|
||||
:param str name: name of the method to test
|
||||
:param tuple args: position arguments to method
|
||||
:param dict kwargs: keyword arguments to method
|
||||
|
||||
"""
|
||||
installer_func = getattr(self.installer, name)
|
||||
reverter_func = getattr(self.reverter, name)
|
||||
self._test_adapted_method(
|
||||
installer_func, reverter_func, *args, **kwargs)
|
||||
|
||||
def _test_adapted_method(self, installer_func,
|
||||
reverter_func, *passed_args, **passed_kwargs):
|
||||
"""Test an adapted reverter method
|
||||
|
||||
:param callable installer_func: installer method to test
|
||||
:param mock.MagicMock reverter_func: mocked adapated
|
||||
reverter method
|
||||
:param tuple passed_args: positional arguments passed from
|
||||
installer method to the reverter method
|
||||
:param dict passed_kargs: keyword arguments passed from
|
||||
installer method to the reverter method
|
||||
|
||||
"""
|
||||
installer_func(*passed_args, **passed_kwargs)
|
||||
reverter_func.assert_called_once_with(*passed_args, **passed_kwargs)
|
||||
reverter_func.side_effect = errors.ReverterError
|
||||
self.assertRaises(
|
||||
errors.PluginError, installer_func, *passed_args, **passed_kwargs)
|
||||
|
||||
|
||||
class AddrTest(unittest.TestCase):
|
||||
"""Tests for certbot.client.plugins.common.Addr."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user