Storage moved to Installer and not initialized on plugin __init__

This commit is contained in:
Joona Hoikkala 2018-02-19 23:33:10 +02:00
parent 122e227d0a
commit ace2f9ff05
No known key found for this signature in database
GPG key ID: 1708DAE66E87A524
17 changed files with 77 additions and 148 deletions

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_cloudflare.dns_cloudflare."""
import os
import shutil
import tempfile
import unittest
import CloudFlare
@ -28,10 +26,8 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"cloudflare_email": EMAIL, "cloudflare_api_key": API_KEY}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(cloudflare_credentials=path,
cloudflare_propagation_seconds=0,
config_dir=self.config_dir) # don't wait during tests
cloudflare_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "cloudflare")
@ -39,9 +35,6 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
# _get_cloudflare_client | pylint: disable=protected-access
self.auth._get_cloudflare_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_perform(self):
self.auth.perform([self.achall])

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_cloudxns.dns_cloudxns."""
import os
import shutil
import tempfile
import unittest
import mock
@ -31,19 +29,15 @@ class AuthenticatorTest(test_util.TempDirTestCase,
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"cloudxns_api_key": API_KEY, "cloudxns_secret_key": SECRET}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(cloudxns_credentials=path,
cloudxns_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
cloudxns_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "cloudxns")
self.mock_client = mock.MagicMock()
# _get_cloudxns_client | pylint: disable=protected-access
self.auth._get_cloudxns_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
class CloudXNSLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconClientTest):

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_digitalocean.dns_digitalocean."""
import os
import shutil
import tempfile
import unittest
import digitalocean
@ -27,19 +25,15 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"digitalocean_token": TOKEN}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(digitalocean_credentials=path,
digitalocean_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
digitalocean_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "digitalocean")
self.mock_client = mock.MagicMock()
# _get_digitalocean_client | pylint: disable=protected-access
self.auth._get_digitalocean_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_perform(self):
self.auth.perform([self.achall])

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_dnsimple.dns_dnsimple."""
import os
import shutil
import tempfile
import unittest
import mock
@ -26,10 +24,8 @@ class AuthenticatorTest(test_util.TempDirTestCase,
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"dnsimple_token": TOKEN}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(dnsimple_credentials=path,
dnsimple_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
dnsimple_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "dnsimple")
@ -37,9 +33,6 @@ class AuthenticatorTest(test_util.TempDirTestCase,
# _get_dnsimple_client | pylint: disable=protected-access
self.auth._get_dnsimple_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
class DNSimpleLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconClientTest):

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_dnsmadeeasy.dns_dnsmadeeasy."""
import os
import shutil
import tempfile
import unittest
import mock
@ -30,10 +28,8 @@ class AuthenticatorTest(test_util.TempDirTestCase,
"dnsmadeeasy_secret_key": SECRET_KEY},
path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(dnsmadeeasy_credentials=path,
dnsmadeeasy_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
dnsmadeeasy_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "dnsmadeeasy")
@ -41,9 +37,6 @@ class AuthenticatorTest(test_util.TempDirTestCase,
# _get_dnsmadeeasy_client | pylint: disable=protected-access
self.auth._get_dnsmadeeasy_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
class DNSMadeEasyLexiconClientTest(unittest.TestCase,
dns_test_common_lexicon.BaseLexiconClientTest):

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_google.dns_google."""
import os
import shutil
import tempfile
import unittest
import mock
@ -31,11 +29,8 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
open(path, "wb").close()
super(AuthenticatorTest, self).setUp()
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(google_credentials=path,
google_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
google_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "google")
@ -43,9 +38,6 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
# _get_google_client | pylint: disable=protected-access
self.auth._get_google_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_perform(self):
self.auth.perform([self.achall])

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_luadns.dns_luadns."""
import os
import shutil
import tempfile
import unittest
import mock
@ -27,10 +25,8 @@ class AuthenticatorTest(test_util.TempDirTestCase,
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"luadns_email": EMAIL, "luadns_token": TOKEN}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(luadns_credentials=path,
luadns_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
luadns_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "luadns")
@ -38,9 +34,6 @@ class AuthenticatorTest(test_util.TempDirTestCase,
# _get_luadns_client | pylint: disable=protected-access
self.auth._get_luadns_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
class LuaDNSLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconClientTest):

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_nsone.dns_nsone."""
import os
import shutil
import tempfile
import unittest
import mock
@ -27,10 +25,8 @@ class AuthenticatorTest(test_util.TempDirTestCase,
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"nsone_api_key": API_KEY}, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(nsone_credentials=path,
nsone_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
nsone_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "nsone")
@ -38,9 +34,6 @@ class AuthenticatorTest(test_util.TempDirTestCase,
# _get_nsone_client | pylint: disable=protected-access
self.auth._get_nsone_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
class NS1LexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconClientTest):
DOMAIN_NOT_FOUND = HTTPError('404 Client Error: Not Found for url: {0}.'.format(DOMAIN))

View file

@ -1,8 +1,6 @@
"""Tests for certbot_dns_rfc2136.dns_rfc2136."""
import os
import shutil
import tempfile
import unittest
import dns.flags
@ -31,10 +29,8 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write(VALID_CONFIG, path)
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(rfc2136_credentials=path,
rfc2136_propagation_seconds=0, # don't wait during tests
config_dir=self.config_dir)
rfc2136_propagation_seconds=0) # don't wait during tests
self.auth = Authenticator(self.config, "rfc2136")
@ -42,9 +38,6 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
# _get_rfc2136_client | pylint: disable=protected-access
self.auth._get_rfc2136_client = mock.MagicMock(return_value=self.mock_client)
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_perform(self):
self.auth.perform([self.achall])

View file

@ -1,7 +1,5 @@
"""Tests for certbot_dns_route53.dns_route53.Authenticator"""
import tempfile
import shutil
import unittest
import mock
@ -20,14 +18,10 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest
super(AuthenticatorTest, self).setUp()
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(config_dir=self.config_dir)
self.config = mock.MagicMock()
self.auth = Authenticator(self.config, "route53")
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_perform(self):
self.auth._change_txt_record = mock.MagicMock()
self.auth._wait_for_change = mock.MagicMock()
@ -121,14 +115,10 @@ class ClientTest(unittest.TestCase):
super(ClientTest, self).setUp()
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(config_dir=self.config_dir)
self.config = mock.MagicMock()
self.client = Authenticator(self.config, "route53")
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_find_zone_id_for_domain(self):
self.client.r53.get_paginator = mock.MagicMock()
self.client.r53.get_paginator().paginate.return_value = [

View file

@ -47,7 +47,6 @@ class Plugin(object):
def __init__(self, config, name):
self.config = config
self.name = name
self.storage = PluginStorage(self.config, name)
@jose_util.abstractclassmethod
def add_parser_arguments(cls, add):
@ -119,13 +118,22 @@ class PluginStorage(object):
:raises .errors.PluginStorageError: when unable to open or read the file
"""
if hasattr(config, "config_dir") and os.path.isdir(config.config_dir):
self.storagepath = os.path.join(config.config_dir, "pluginstorage.json")
self.config = config
self.classkey = classkey
self.initialized = False
self._data = None
self.storagepath = None
def initialize_storage(self):
"""Initializes PluginStorage data and reads current state from the disk
if the storage json exists."""
if hasattr(self.config, "config_dir") and os.path.isdir(self.config.config_dir):
self.storagepath = os.path.join(self.config.config_dir, ".pluginstorage.json")
self._data = self.load()
else:
self.storagepath = None
self.classkey = classkey
self.initialized = True
def load(self):
"""Reads PluginStorage content from the disk to a dict structure
@ -135,7 +143,6 @@ class PluginStorage(object):
:raises .errors.PluginStorageError: when unable to open or read the file
"""
data = dict()
filedata = ""
try:
@ -170,10 +177,11 @@ class PluginStorage(object):
:raises .errors.PluginStorageError: when unable to serialize the data
or write it to the filesystem
"""
if not self.storagepath:
if not self.initialized or not self.storagepath:
errmsg = "Unable to save, problem with configuration directory"
logger.error(errmsg)
raise errors.PluginStorageError(errmsg)
try:
serialized = json.dumps(self._data)
except TypeError as e:
@ -198,6 +206,9 @@ class PluginStorage(object):
:param str key: Key to store the value to
:param value: Data to store
"""
if not self.initialized:
self.initialize_storage()
if not self.classkey in self._data.keys():
self._data[self.classkey] = dict()
self._data[self.classkey][key] = value
@ -207,6 +218,9 @@ class PluginStorage(object):
:param str key: Key to get value from the storage
"""
if not self.initialized:
self.initialize_storage()
try:
return self._data[self.classkey][key]
except KeyError:
@ -221,6 +235,7 @@ class Installer(Plugin):
"""
def __init__(self, *args, **kwargs):
super(Installer, self).__init__(*args, **kwargs)
self.storage = PluginStorage(self.config, self.name)
self.reverter = reverter.Reverter(self.config)
def add_to_checkpoint(self, save_files, save_notes, temporary=False):

View file

@ -57,14 +57,10 @@ class PluginTest(unittest.TestCase):
def add_parser_arguments(cls, add):
add("foo-bar", dest="different_to_foo_bar", x=1, y=None)
self.config_dir = tempfile.mkdtemp()
self.plugin_cls = MockPlugin
self.config = mock.MagicMock(config_dir=self.config_dir)
self.config = mock.MagicMock()
self.plugin = MockPlugin(config=self.config, name="mock")
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_init(self):
self.assertEqual("mock", self.plugin.name)
self.assertEqual(self.config, self.plugin.config)

View file

@ -1,8 +1,6 @@
"""Tests for certbot.plugins.disco."""
import functools
import shutil
import string
import tempfile
import unittest
import mock
@ -41,14 +39,9 @@ class PluginEntryPointTest(unittest.TestCase):
self.ep3 = pkg_resources.EntryPoint(
"ep3", "a.ep3", dist=mock.MagicMock(key="p3"))
self.config_dir = tempfile.mkdtemp()
from certbot.plugins.disco import PluginEntryPoint
self.plugin_ep = PluginEntryPoint(EP_SA)
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_entry_point_to_plugin_name(self):
from certbot.plugins.disco import PluginEntryPoint
@ -102,7 +95,7 @@ class PluginEntryPointTest(unittest.TestCase):
self.assertTrue(self.plugin_ep.plugin_cls is standalone.Authenticator)
def test_init(self):
config = mock.MagicMock(config_dir=self.config_dir)
config = mock.MagicMock()
plugin = self.plugin_ep.init(config=config)
self.assertTrue(self.plugin_ep.initialized)
self.assertTrue(plugin.config is config)
@ -141,7 +134,7 @@ class PluginEntryPointTest(unittest.TestCase):
self.assertFalse(self.plugin_ep.verify((iface1, iface3)))
def test_prepare(self):
config = mock.MagicMock(config_dir=self.config_dir)
config = mock.MagicMock()
self.plugin_ep.init(config=config)
self.plugin_ep.prepare()
self.assertTrue(self.plugin_ep.prepared)

View file

@ -1,6 +1,4 @@
"""Tests for certbot.plugins.null."""
import shutil
import tempfile
import unittest
import six
@ -12,12 +10,7 @@ class InstallerTest(unittest.TestCase):
def setUp(self):
from certbot.plugins.null import Installer
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(config_dir=self.config_dir)
self.installer = Installer(config=self.config, name="null")
def tearDown(self):
shutil.rmtree(self.config_dir)
self.installer = Installer(config=mock.MagicMock(), name="null")
def test_it(self):
self.assertTrue(isinstance(self.installer.more_info(), six.string_types))

View file

@ -16,61 +16,70 @@ class PluginStorageTest(unittest.TestCase):
def setUp(self):
class MockPlugin(common.Plugin):
class MockPlugin(common.Installer):
"""Mock plugin"""
pass
self.plugin_cls = MockPlugin
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(config_dir=self.config_dir)
self.plugin = MockPlugin(config=self.config, name="mockplugin")
with mock.patch("certbot.reverter.util"):
self.plugin = MockPlugin(config=self.config, name="mockplugin")
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_initialize_no_configdir(self):
delattr(self.plugin.config, "config_dir")
self.plugin.storage.initialize_storage()
self.assertTrue(self.plugin.storage.storagepath == None)
def test_load_errors(self):
with open(os.path.join(self.config_dir, "pluginstorage.json"), "w") as fh:
with open(os.path.join(self.config_dir, ".pluginstorage.json"), "w") as fh:
fh.write("dummy")
# When unable to read file that exists
mock_open = mock.mock_open()
mock_open.side_effect = IOError
self.plugin.storage.storagepath = os.path.join(self.config_dir,
".pluginstorage.json")
with mock.patch("six.moves.builtins.open", mock_open):
with mock.patch('os.path.isfile', return_value=True):
self.assertRaises(errors.PluginStorageError,
self.plugin_cls,
self.config,
"mockplugin")
with mock.patch("certbot.reverter.util"):
self.assertRaises(errors.PluginStorageError,
self.plugin.storage.load)
# When pluginstorage path is None
mock_open.side_effect = TypeError
with mock.patch("six.moves.builtins.open", mock_open):
self.assertRaises(errors.PluginStorageError,
self.plugin_cls,
self.config,
"mockplugin")
with mock.patch("certbot.reverter.util"):
nostoragepath = self.plugin_cls(self.config, "mockplugin")
self.assertRaises(errors.PluginStorageError,
nostoragepath.storage.load)
# When file exists but is completely empty
with open(os.path.join(self.config_dir, "pluginstorage.json"), "w") as fh:
with open(os.path.join(self.config_dir, ".pluginstorage.json"), "w") as fh:
fh.write('')
with mock.patch("certbot.plugins.common.logger.debug") as mock_log:
# Should not error out but write a debug log line instead
self.plugin_cls(self.config, "mockplugin")
with mock.patch("certbot.reverter.util"):
nocontent = self.plugin_cls(self.config, "mockplugin")
nocontent.storage.fetch("value")
self.assertTrue(mock_log.called)
self.assertTrue("no values loaded" in mock_log.call_args[0][0])
# File is corrupted
with open(os.path.join(self.config_dir, "pluginstorage.json"), "w") as fh:
with open(os.path.join(self.config_dir, ".pluginstorage.json"), "w") as fh:
fh.write('invalid json')
with mock.patch("certbot.plugins.common.logger.error") as mock_log:
with mock.patch("certbot.reverter.util"):
corrupted = self.plugin_cls(self.config, "mockplugin")
self.assertRaises(errors.PluginError,
self.plugin_cls,
self.config,
"mockplugin")
corrupted.storage.fetch,
"value")
self.assertTrue("is corrupted" in mock_log.call_args[0][0])
def test_save_no_storagepath(self):
with mock.patch("certbot.plugins.common.logger.error") as mock_log:
self.plugin.storage.storagepath = None
self.assertRaises(errors.PluginStorageError,
self.plugin.storage.save)
self.assertTrue("Unable to save" in mock_log.call_args[0][0])
@ -78,6 +87,8 @@ class PluginStorageTest(unittest.TestCase):
def test_save_errors(self):
with mock.patch("certbot.plugins.common.logger.error") as mock_log:
# Set data as something that can't be serialized
self.plugin.storage.initialized = True
self.plugin.storage.storagepath = "/tmp/whatever"
self.plugin.storage._data = self.plugin_cls # pylint: disable=protected-access
self.assertRaises(errors.PluginStorageError,
self.plugin.storage.save)
@ -94,8 +105,9 @@ class PluginStorageTest(unittest.TestCase):
self.assertTrue("Could not write" in mock_log.call_args[0][0])
def test_namespace_isolation(self):
plugin1 = self.plugin_cls(self.config, "first")
plugin2 = self.plugin_cls(self.config, "second")
with mock.patch("certbot.reverter.util"):
plugin1 = self.plugin_cls(self.config, "first")
plugin2 = self.plugin_cls(self.config, "second")
plugin1.storage.put("first_key", "first_value")
self.assertEqual(plugin2.storage.fetch("first_key"), None)
self.assertEqual(plugin2.storage.fetch("first"), None)
@ -106,11 +118,12 @@ class PluginStorageTest(unittest.TestCase):
self.plugin.storage.put("testkey", "testvalue")
# Write to disk
self.plugin.storage.save()
another = self.plugin_cls(self.config, "mockplugin")
with mock.patch("certbot.reverter.util"):
another = self.plugin_cls(self.config, "mockplugin")
self.assertEqual(another.storage.fetch("testkey"), "testvalue")
with open(os.path.join(self.config.config_dir,
"pluginstorage.json"), 'r') as fh:
".pluginstorage.json"), 'r') as fh:
psdata = fh.read()
psjson = json.loads(psdata)
self.assertTrue("mockplugin" in psjson.keys())

View file

@ -1,8 +1,6 @@
"""Tests for certbot.plugins.standalone."""
import argparse
import shutil
import socket
import tempfile
import unittest
import josepy as jose
@ -123,17 +121,13 @@ class AuthenticatorTest(unittest.TestCase):
def setUp(self):
from certbot.plugins.standalone import Authenticator
self.config_dir = tempfile.mkdtemp()
self.config = mock.MagicMock(
tls_sni_01_port=get_open_port(), http01_port=get_open_port(),
standalone_supported_challenges="tls-sni-01,http-01",
config_dir=self.config_dir)
standalone_supported_challenges="tls-sni-01,http-01")
self.auth = Authenticator(self.config, name="standalone")
self.auth.servers = mock.MagicMock()
def tearDown(self):
shutil.rmtree(self.config_dir)
def test_supported_challenges(self):
self.assertEqual(self.auth.supported_challenges,
[challenges.TLSSNI01, challenges.HTTP01])

View file

@ -35,7 +35,6 @@ class AuthenticatorTest(unittest.TestCase):
def setUp(self):
from certbot.plugins.webroot import Authenticator
self.config_dir = tempfile.mkdtemp()
self.path = tempfile.mkdtemp()
self.partial_root_challenge_path = os.path.join(
self.path, ".well-known")
@ -44,14 +43,12 @@ class AuthenticatorTest(unittest.TestCase):
self.validation_path = os.path.join(
self.root_challenge_path,
"ZXZhR3hmQURzNnBTUmIyTEF2OUlaZjE3RHQzanV4R0orUEN0OTJ3citvQQ")
self.config = mock.MagicMock(config_dir=self.config_dir,
webroot_path=self.path,
self.config = mock.MagicMock(webroot_path=self.path,
webroot_map={"thing.com": self.path})
self.auth = Authenticator(self.config, "webroot")
def tearDown(self):
shutil.rmtree(self.path)
shutil.rmtree(self.config_dir)
def test_more_info(self):
more_info = self.auth.more_info()