PLuginsRegistry: verify, prepare, misconfigured, available.

This commit is contained in:
Jakub Warmuz 2015-05-03 12:38:53 +00:00
parent 595230fd8e
commit b600e2d270
No known key found for this signature in database
GPG key ID: 2A7BAD3A489B52EA
4 changed files with 71 additions and 69 deletions

View file

@ -82,7 +82,7 @@ def run(args, config, plugins):
acc = _account_init(args, config)
if acc is None:
return None
if args.configurator is not None and (args.installer is not None or
args.authenticator is not None):
return ("Either --configurator or --authenticator/--installer"
@ -171,53 +171,30 @@ def config_changes(args, config, plugins):
client.config_changes(config)
def _print_plugins(plugins):
# TODO: this functions should use IDisplay rather than printing
if not plugins:
print "No plugins found"
for plugin_ep in plugins.itervalues():
print "* {0}".format(plugin_ep.name)
print "Description: {0}".format(plugin_ep.plugin_cls.description)
print "Interfaces: {0}".format(", ".join(
iface.__name__ for iface in zope.interface.implementedBy(
plugin_ep.plugin_cls)))
print "Entry point: {0}".format(plugin_ep.entry_point)
if plugin_ep.initialized:
print "Initialized: {0}".format(plugin_ep.init())
# if filtered == prepared:
#if isinstance(content, tuple) and content[1] is not None:
# print content[1] # error
print # whitespace between plugins
def plugins_cmd(args, config, plugins):
def plugins_cmd(args, config, plugins): # TODO: Use IDiplay rathern than print
"""List plugins."""
logging.debug("Discovered plugins: %s", plugins)
ifaces = [] if args.ifaces is None else args.ifaces
filtered = plugins.filter(*((iface,) for iface in ifaces))
logging.debug("Filtered plugins: %s", filtered)
filtered = plugins.filter_ifaces(*((iface,) for iface in ifaces))
logging.debug("Filtered plugins: %r", filtered)
if not args.init and not args.prepare:
return _print_plugins(filtered)
print str(filtered)
return
for plugin_ep in filtered.itervalues():
plugin_ep.init(config)
#verified = plugins_disco.verify_plugins(initialized, ifaces)
#logging.debug("Verified plugins: %s", initialized)
filtered.init(config)
verified = filtered.verify(ifaces)
logging.debug("Verified plugins: %r", verified)
if not args.prepare:
return _print_plugins(filtered)
print str(verified)
return
available = plugins_disco.available_plugins(filtered)
verified.prepare()
available = verified.available()
logging.debug("Prepared plugins: %s", available)
_print_plugins(available)
print str(available)
def read_file(filename):

View file

@ -6,7 +6,7 @@ import zope.component
from letsencrypt.client import interfaces
from letsencrypt.client.display import util as display_util
from letsencrypt.client.plugins import disco as plugins_disco
# Define a helper function to avoid verbose code
util = zope.component.getUtility # pylint: disable=invalid-name
@ -18,8 +18,8 @@ def choose_plugin(prepared, question):
:param list prepared:
"""
opts = [plugin_ep.name_with_description if not plugin_ep.misconfigured
else "%s (Misconfigured)" % plugin_ep.name_with_description
opts = [plugin_ep.name_with_description
+ (" [Misconfigured]" if plugin_ep.misconfigured else "")
for plugin_ep in prepared.itervalues()]
while True:
@ -40,14 +40,15 @@ def choose_plugin(prepared, question):
def _pick_plugin(config, default, plugins, question, ifaces):
if default is not None:
filtered = {default: plugins[default]}
# throw more UX-friendly error if default not in plugins
filtered = plugins.filter(lambda p_ep: p_ep.name == default)
else:
filtered = plugins.filter(ifaces)
filtered = plugins.filter_ifaces(ifaces)
for plugin_ep in plugins.itervalues():
plugin_ep.init(config)
verified = plugins_disco.verify_plugins(filtered, ifaces)
prepared = plugins_disco.available_plugins(verified)
filtered.init(config)
verified = filtered.verify(ifaces)
filtered.prepare()
prepared = filtered.available()
if len(prepared) > 1:
logging.debug("Multiple candidate plugins: %s", prepared)

View file

@ -96,6 +96,22 @@ class PluginEntryPoint(object):
return False
return True
def __str__(self):
lines = [
"* {0}".format(self.name),
"Description: {0}".format(self.plugin_cls.description),
"Interfaces: {0}".format(", ".join(
iface.__name__ for iface in zope.interface.implementedBy(
self.plugin_cls))),
"Entry point: {0}".format(self.entry_point),
]
if self.initialized:
lines.append("Initialized: {0}".format(self.init()))
if self.prepared:
lines.append("Prep: {0}".format(self.prepare()))
return "\n".join(lines)
class PluginsRegistry(collections.Mapping):
@ -120,15 +136,34 @@ class PluginsRegistry(collections.Mapping):
"IPluginFactory, skipping", plugin_ep)
return cls(plugins)
def filter(self, *ifaces_groups):
def init(self, config):
"""Initialize all plugins in the registry."""
return [plugin_ep.init(config) for plugin_ep
in self.plugins.itervalues()]
def filter(self, pred):
"""Filter plugins based on predicate."""
return type(self)(dict((name, plugin_ep) for name, plugin_ep
in self.plugins.iteritems() if pred(plugin_ep)))
def filter_ifaces(self, *ifaces_groups):
"""Filter plugins based on interfaces."""
return type(self)(dict(
(name, plugin_ep)
for name, plugin_ep in self.plugins.iteritems()
if not ifaces_groups or any(
return self.filter(lambda plugin_ep: not ifaces_groups or any(
all(iface.implementedBy(plugin_ep.plugin_cls)
for iface in ifaces)
for ifaces in ifaces_groups)))
for ifaces in ifaces_groups))
def verify(self, ifaces):
"""Filter plugins based on verification."""
return self.filter(lambda p_ep: p_ep.verify(ifaces))
def prepare(self):
return [plugin_ep.prepare() for plugin_ep in self.plugins.itervalues()]
def available(self):
"""Filter plugins based on availability."""
return self.filter(lambda p_ep: p_ep.available)
# succefully prepared + misconfigured
def __repr__(self):
return "{0}({1!r})".format(
@ -143,18 +178,7 @@ class PluginsRegistry(collections.Mapping):
def __len__(self):
return len(self.plugins)
def verify_plugins(initialized, ifaces):
"""Verify plugin objects."""
return dict((name, plugin_ep) for name, plugin_ep in initialized.iteritems()
if plugin_ep.verify(ifaces))
def available_plugins(initialized):
"""Prepare plugins and filter available."""
prepared = {}
for name, plugin_ep in initialized.iteritems():
plugin_ep.prepare()
if plugin_ep.available:
prepared[name] = plugin_ep
return prepared # succefully prepared + misconfigured
def __str__(self):
if not self.plugins:
return "No plugins"
return "\n\n".join(map(str, self.plugins.itervalues()))

View file

@ -85,8 +85,8 @@ class PluginsRegistryTest(unittest.TestCase):
self.assertTrue(self.plugins["standalone"].plugin_cls
is authenticator.StandaloneAuthenticator)
def test_filter(self):
filtered = self.plugins.filter()
def test_id_filter(self):
filtered = self.plugins.filter(lambda _: True)
self.assertEqual(len(self.plugins), len(filtered))
def test_repr(self):