Merge branch 'master' into plugins_dir

This commit is contained in:
James Kasten
2015-03-27 12:57:28 -07:00
4 changed files with 42 additions and 31 deletions
+2 -2
View File
@@ -80,7 +80,7 @@ Documentation: https://letsencrypt.readthedocs.org/
Software project: https://github.com/letsencrypt/lets-encrypt-preview Software project: https://github.com/letsencrypt/lets-encrypt-preview
Notes for developers: CONTRIBUTING.rst_ Notes for developers: CONTRIBUTING.md_
Main Website: https://letsencrypt.org/ Main Website: https://letsencrypt.org/
@@ -91,4 +91,4 @@ email to client-dev+subscribe@letsencrypt.org)
.. _Freenode: https://freenode.net .. _Freenode: https://freenode.net
.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev .. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev
.. _CONTRIBUTING.rst: https://github.com/letsencrypt/lets-encrypt-preview/blob/master/CONTRIBUTING.rst .. _CONTRIBUTING.md: https://github.com/letsencrypt/lets-encrypt-preview/blob/master/CONTRIBUTING.md
+15 -1
View File
@@ -2,4 +2,18 @@
Plugins Plugins
======= =======
You can find an example in ``examples/plugins/`` directory. Let's Encrypt client supports dynamic discovery of plugins through the
`setuptools entry points`_. This way you can, for example, create a
custom implementation of
`~letsencrypt.client.interfaces.IAuthenticator` or the
'~letsencrypt.client.interfaces.IInstaller' without having to
merge it with the core upstream source code. An example is provided in
``examples/plugins/`` directory.
Please be aware though that as this client is still in a developer-preview
stage, the API may undergo a few changes. If you believe the plugin will be
beneficial to the community, please consider submitting a pull request to the
repo and we will update it with any necessary API changes.
.. _`setuptools entry points`:
https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins
-27
View File
@@ -1,15 +1,11 @@
"""ACME protocol client class and helper functions.""" """ACME protocol client class and helper functions."""
import logging import logging
import os import os
import pkg_resources
import sys import sys
import Crypto.PublicKey.RSA import Crypto.PublicKey.RSA
import M2Crypto import M2Crypto
import zope.interface.exceptions
import zope.interface.verify
from letsencrypt.acme import messages from letsencrypt.acme import messages
from letsencrypt.acme.jose import util as jose_util from letsencrypt.acme.jose import util as jose_util
@@ -17,7 +13,6 @@ from letsencrypt.client import auth_handler
from letsencrypt.client import client_authenticator from letsencrypt.client import client_authenticator
from letsencrypt.client import crypto_util from letsencrypt.client import crypto_util
from letsencrypt.client import errors from letsencrypt.client import errors
from letsencrypt.client import interfaces
from letsencrypt.client import le_util from letsencrypt.client import le_util
from letsencrypt.client import network from letsencrypt.client import network
from letsencrypt.client import reverter from letsencrypt.client import reverter
@@ -28,28 +23,6 @@ from letsencrypt.client.display import ops as display_ops
from letsencrypt.client.display import enhancements from letsencrypt.client.display import enhancements
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT = "letsencrypt.authenticators"
"""Setuptools entry point group name for Authenticator plugins."""
def init_auths(config):
"""Find (setuptools entry points) and initialize Authenticators."""
auths = {}
for entrypoint in pkg_resources.iter_entry_points(
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT):
auth_cls = entrypoint.load()
auth = auth_cls(config)
try:
zope.interface.verify.verifyObject(interfaces.IAuthenticator, auth)
except zope.interface.exceptions.BrokenImplementation:
logging.debug(
"%r object does not provide IAuthenticator, skipping",
entrypoint.name)
else:
auths[auth] = entrypoint.name
return auths
class Client(object): class Client(object):
"""ACME protocol client. """ACME protocol client.
+25 -1
View File
@@ -11,6 +11,8 @@ import sys
import confargparse import confargparse
import zope.component import zope.component
import zope.interface.exceptions
import zope.interface.verify
import letsencrypt import letsencrypt
@@ -24,6 +26,28 @@ from letsencrypt.client.display import util as display_util
from letsencrypt.client.display import ops as display_ops from letsencrypt.client.display import ops as display_ops
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT = "letsencrypt.authenticators"
"""Setuptools entry point group name for Authenticator plugins."""
def init_auths(config):
"""Find (setuptools entry points) and initialize Authenticators."""
auths = {}
for entrypoint in pkg_resources.iter_entry_points(
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT):
auth_cls = entrypoint.load()
auth = auth_cls(config)
try:
zope.interface.verify.verifyObject(interfaces.IAuthenticator, auth)
except zope.interface.exceptions.BrokenImplementation:
logging.debug(
"%r object does not provide IAuthenticator, skipping",
entrypoint.name)
else:
auths[auth] = entrypoint.name
return auths
def create_parser(): def create_parser():
"""Create parser.""" """Create parser."""
parser = confargparse.ConfArgParser( parser = confargparse.ConfArgParser(
@@ -134,7 +158,7 @@ def main(): # pylint: disable=too-many-branches, too-many-statements
if not args.eula: if not args.eula:
display_eula() display_eula()
all_auths = client.init_auths(config) all_auths = init_auths(config)
logging.debug('Initialized authenticators: %s', all_auths.values()) logging.debug('Initialized authenticators: %s', all_auths.values())
try: try:
auth = client.determine_authenticator(all_auths.keys()) auth = client.determine_authenticator(all_auths.keys())