Reimplement zope interfaces into abc in compatibility tests (#8971)

* Reimplement zope interfaces into abc in compatibility tests

* Refactor to fix lint and mypy warnings

* Fix inheritance
This commit is contained in:
Adrien Ferrand
2021-08-13 11:00:33 +10:00
committed by GitHub
parent b4c49cf781
commit 6943cea6b7
5 changed files with 86 additions and 47 deletions
@@ -4,18 +4,14 @@ import shutil
import subprocess import subprocess
from unittest import mock from unittest import mock
import zope.interface
from certbot import errors as le_errors, configuration from certbot import errors as le_errors, configuration
from certbot import util as certbot_util from certbot import util as certbot_util
from certbot_apache._internal import entrypoint from certbot_apache._internal import entrypoint
from certbot_compatibility_test import errors from certbot_compatibility_test import errors
from certbot_compatibility_test import interfaces
from certbot_compatibility_test import util from certbot_compatibility_test import util
from certbot_compatibility_test.configurators import common as configurators_common from certbot_compatibility_test.configurators import common as configurators_common
@zope.interface.implementer(interfaces.IConfiguratorProxy)
class Proxy(configurators_common.Proxy): class Proxy(configurators_common.Proxy):
"""A common base for Apache test configurators""" """A common base for Apache test configurators"""
@@ -1,17 +1,19 @@
"""Provides a common base for configurator proxies""" """Provides a common base for configurator proxies"""
from abc import abstractmethod
import logging import logging
import os import os
import shutil import shutil
import tempfile import tempfile
from certbot._internal import constants from certbot._internal import constants
from certbot_compatibility_test import interfaces
from certbot_compatibility_test import errors from certbot_compatibility_test import errors
from certbot_compatibility_test import util from certbot_compatibility_test import util
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Proxy: class Proxy(interfaces.ConfiguratorProxy):
"""A common base for compatibility test configurators""" """A common base for compatibility test configurators"""
@classmethod @classmethod
@@ -20,6 +22,7 @@ class Proxy:
def __init__(self, args): def __init__(self, args):
"""Initializes the plugin with the given command line args""" """Initializes the plugin with the given command line args"""
super().__init__(args)
self._temp_dir = tempfile.mkdtemp() self._temp_dir = tempfile.mkdtemp()
# tempfile.mkdtemp() creates folders with too restrictive permissions to be accessible # tempfile.mkdtemp() creates folders with too restrictive permissions to be accessible
# to an Apache worker, leading to HTTP challenge failures. Let's fix that. # to an Apache worker, leading to HTTP challenge failures. Let's fix that.
@@ -33,24 +36,15 @@ class Proxy:
self.args = args self.args = args
self.http_port = 80 self.http_port = 80
self.https_port = 443 self.https_port = 443
self._configurator = None self._configurator: interfaces.Configurator
self._all_names = None self._all_names = None
self._test_names = None self._test_names = None
def __getattr__(self, name):
"""Wraps the configurator methods"""
if self._configurator is None:
raise AttributeError()
method = getattr(self._configurator, name, None)
if callable(method):
return method
raise AttributeError()
def has_more_configs(self): def has_more_configs(self):
"""Returns true if there are more configs to test""" """Returns true if there are more configs to test"""
return bool(self._configs) return bool(self._configs)
@abstractmethod
def cleanup_from_tests(self): def cleanup_from_tests(self):
"""Performs any necessary cleanup from running plugin tests""" """Performs any necessary cleanup from running plugin tests"""
@@ -99,3 +93,47 @@ class Proxy:
raise ValueError("Configurator plugin is not set.") raise ValueError("Configurator plugin is not set.")
self._configurator.deploy_cert( self._configurator.deploy_cert(
domain, cert_path, key_path, chain_path, fullchain_path) domain, cert_path, key_path, chain_path, fullchain_path)
def cleanup(self, achalls):
self._configurator.cleanup(achalls)
def config_test(self):
self._configurator.config_test()
def enhance(self, domain, enhancement, options = None):
self._configurator.enhance(domain, enhancement, options)
def get_all_names(self):
return self._configurator.get_all_names()
def get_chall_pref(self, domain):
return self._configurator.get_chall_pref(domain)
@classmethod
def inject_parser_options(cls, parser, name):
pass
def more_info(self):
return self._configurator.more_info()
def perform(self, achalls):
return self._configurator.perform(achalls)
def prepare(self):
self._configurator.prepare()
def recovery_routine(self):
self._configurator.recovery_routine()
def restart(self):
self._configurator.restart()
def rollback_checkpoints(self, rollback = 1):
self._configurator.rollback_checkpoints(rollback)
def save(self, title = None, temporary = False):
self._configurator.save(title, temporary)
def supported_enhancements(self):
return self._configurator.supported_enhancements()
@@ -2,10 +2,9 @@
import os import os
import shutil import shutil
import subprocess import subprocess
from typing import cast
from typing import Set from typing import Set
import zope.interface
from certbot import configuration from certbot import configuration
from certbot_compatibility_test import errors from certbot_compatibility_test import errors
from certbot_compatibility_test import interfaces from certbot_compatibility_test import interfaces
@@ -15,7 +14,6 @@ from certbot_nginx._internal import configurator
from certbot_nginx._internal import constants from certbot_nginx._internal import constants
@zope.interface.implementer(interfaces.IConfiguratorProxy)
class Proxy(configurators_common.Proxy): class Proxy(configurators_common.Proxy):
"""A common base for Nginx test configurators""" """A common base for Nginx test configurators"""
@@ -48,10 +46,13 @@ class Proxy(configurators_common.Proxy):
setattr(self.le_config, "nginx_" + k, constants.os_constant(k)) setattr(self.le_config, "nginx_" + k, constants.os_constant(k))
conf = configuration.NamespaceConfig(self.le_config) conf = configuration.NamespaceConfig(self.le_config)
self._configurator = configurator.NginxConfigurator( self._configurator = cast(interfaces.Configurator, configurator.NginxConfigurator(
config=conf, name="nginx") config=conf, name="nginx"))
self._configurator.prepare() self._configurator.prepare()
def cleanup_from_tests(self):
"""Performs any necessary cleanup from running plugin tests"""
def _get_server_root(config): def _get_server_root(config):
"""Returns the server root directory in config""" """Returns the server root directory in config"""
@@ -1,53 +1,65 @@
"""Certbot compatibility test interfaces""" """Certbot compatibility test interfaces"""
import zope.interface from abc import ABCMeta
from abc import abstractmethod
import certbot.interfaces from certbot import interfaces
# pylint: disable=no-self-argument,no-method-argument
class IPluginProxy(zope.interface.Interface): # pylint: disable=inherit-non-class class PluginProxy(interfaces.Plugin, metaclass=ABCMeta):
"""Wraps a Certbot plugin""" """Wraps a Certbot plugin"""
http_port = zope.interface.Attribute( http_port: int = NotImplemented
"The port to connect to on localhost for HTTP traffic") """The port to connect to on localhost for HTTP traffic"""
https_port = zope.interface.Attribute( https_port: int = NotImplemented
"The port to connect to on localhost for HTTPS traffic") """The port to connect to on localhost for HTTPS traffic"""
@classmethod
@abstractmethod
def add_parser_arguments(cls, parser): def add_parser_arguments(cls, parser):
"""Adds command line arguments needed by the parser""" """Adds command line arguments needed by the parser"""
def __init__(args): # pylint: disable=super-init-not-called @abstractmethod
def __init__(self, args):
"""Initializes the plugin with the given command line args""" """Initializes the plugin with the given command line args"""
super().__init__(args, 'proxy')
def cleanup_from_tests(): # type: ignore @abstractmethod
def cleanup_from_tests(self): # type: ignore
"""Performs any necessary cleanup from running plugin tests. """Performs any necessary cleanup from running plugin tests.
This is guaranteed to be called before the program exits. This is guaranteed to be called before the program exits.
""" """
def has_more_configs(): # type: ignore @abstractmethod
def has_more_configs(self): # type: ignore
"""Returns True if there are more configs to test""" """Returns True if there are more configs to test"""
def load_config(): # type: ignore @abstractmethod
def load_config(self): # type: ignore
"""Loads the next config and returns its name""" """Loads the next config and returns its name"""
def get_testable_domain_names(): # type: ignore @abstractmethod
def get_testable_domain_names(self): # type: ignore
"""Returns the domain names that can be used in testing""" """Returns the domain names that can be used in testing"""
class IAuthenticatorProxy(IPluginProxy, certbot.interfaces.IAuthenticator): class AuthenticatorProxy(PluginProxy, interfaces.Authenticator, metaclass=ABCMeta):
"""Wraps a Certbot authenticator""" """Wraps a Certbot authenticator"""
class IInstallerProxy(IPluginProxy, certbot.interfaces.IInstaller): class InstallerProxy(PluginProxy, interfaces.Installer, metaclass=ABCMeta):
"""Wraps a Certbot installer""" """Wraps a Certbot installer"""
def get_all_names_answer(): # type: ignore @abstractmethod
def get_all_names_answer(self): # type: ignore
"""Returns all names that should be found by the installer""" """Returns all names that should be found by the installer"""
class IConfiguratorProxy(IAuthenticatorProxy, IInstallerProxy): class ConfiguratorProxy(AuthenticatorProxy, InstallerProxy, metaclass=ABCMeta):
"""Wraps a Certbot configurator""" """Wraps a Certbot configurator"""
class Configurator(interfaces.Installer, interfaces.Authenticator, metaclass=ABCMeta):
"""Represents a plugin that has both Installer and Authenticator capabilities"""
-8
View File
@@ -1,5 +1,3 @@
import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
@@ -9,14 +7,8 @@ install_requires = [
'certbot', 'certbot',
'certbot-apache', 'certbot-apache',
'requests', 'requests',
'zope.interface',
] ]
if sys.version_info < (2, 7, 9):
# For secure SSL connexion with Python 2.7 (InsecurePlatformWarning)
install_requires.append('ndg-httpsclient')
install_requires.append('pyasn1')
setup( setup(
name='certbot-compatibility-test', name='certbot-compatibility-test',