diff --git a/DISCLAIMER b/DISCLAIMER new file mode 120000 index 000000000..e580554ff --- /dev/null +++ b/DISCLAIMER @@ -0,0 +1 @@ +letsencrypt/DISCLAIMER \ No newline at end of file diff --git a/Dockerfile-dev b/Dockerfile-dev index 2fe1a818d..daa8e9af0 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -32,7 +32,7 @@ RUN /opt/letsencrypt/src/ubuntu.sh && \ # the above is not likely to change, so by putting it further up the # Dockerfile we make sure we cache as much as possible -COPY setup.py README.rst CHANGES.rst MANIFEST.in requirements.txt EULA linter_plugin.py tox.cover.sh tox.ini pep8.travis.sh .pep8 .pylintrc /opt/letsencrypt/src/ +COPY setup.py README.rst CHANGES.rst MANIFEST.in requirements.txt DISCLAIMER linter_plugin.py tox.cover.sh tox.ini pep8.travis.sh .pep8 .pylintrc /opt/letsencrypt/src/ # all above files are necessary for setup.py, however, package source # code directory has to be copied separately to a subdirectory... diff --git a/EULA b/EULA deleted file mode 120000 index 4a6da286e..000000000 --- a/EULA +++ /dev/null @@ -1 +0,0 @@ -letsencrypt/EULA \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in index e421e0cd7..dfec1c3c9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,6 @@ include CHANGES.rst include CONTRIBUTING.md include LICENSE.txt include linter_plugin.py -include letsencrypt/EULA +include letsencrypt/DISCLAIMER recursive-include docs * recursive-include letsencrypt/tests/testdata * diff --git a/README.rst b/README.rst index 43ecd413c..769bc7a8f 100644 --- a/README.rst +++ b/README.rst @@ -76,23 +76,23 @@ server automatically!:: Current Features ---------------- -* web servers supported: +* Supports multiple web servers: - apache/2.x (tested and working on Ubuntu Linux) - nginx/0.8.48+ (under development) - - standalone (runs its own webserver to prove you control the domain) + - standalone (runs its own simple webserver to prove you control a domain) -* the private key is generated locally on your system -* can talk to the Let's Encrypt (demo) CA or optionally to other ACME - compliant services -* can get domain-validated (DV) certificates -* can revoke certificates -* adjustable RSA key bitlength (2048 (default), 4096, ...) -* optionally can install a http->https redirect, so your site effectively +* The private key is generated locally on your system. +* Can talk to the Let's Encrypt (demo) CA or optionally to other ACME + compliant services. +* Can get domain-validated (DV) certificates. +* Can revoke certificates. +* Adjustable RSA key bit-length (2048 (default), 4096, ...). +* Can optionally install a http -> https redirect, so your site effectively runs https only (Apache only) -* fully automated -* configuration changes are logged and can be reverted using the CLI -* text and ncurses UI +* Fully automated. +* Configuration changes are logged and can be reverted. +* Text and ncurses UI. * Free and Open Source Software, made with Python. diff --git a/acme/MANIFEST.in b/acme/MANIFEST.in index ec2b09e05..a452d60d4 100644 --- a/acme/MANIFEST.in +++ b/acme/MANIFEST.in @@ -1,3 +1,4 @@ include LICENSE.txt include README.rst +recursive-include docs * recursive-include acme/testdata * diff --git a/acme/README.rst b/acme/README.rst index e3ca8b738..4b6ea818c 100644 --- a/acme/README.rst +++ b/acme/README.rst @@ -1 +1 @@ -ACME protocol implementation for Python +ACME protocol implementation in Python diff --git a/acme/acme/standalone.py b/acme/acme/standalone.py index 97e52fa9f..49759bc07 100644 --- a/acme/acme/standalone.py +++ b/acme/acme/standalone.py @@ -55,6 +55,8 @@ class ACMEServerMixin: # pylint: disable=old-style-class def serve_forever2(self): """Serve forever, until other thread calls `shutdown2`.""" + logger.debug("Starting server at %s:%d...", + *self.socket.getsockname()[:2]) while not self._stopped: self.handle_request() diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index 5dd6c2952..349581a3d 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -101,8 +101,8 @@ class DVSNIServerTest(unittest.TestCase): self.assertFalse(self.server._stopped) def test_dvsni(self): - cert = crypto_util.probe_sni( - b'localhost', *self.server.socket.getsockname()) + host, port = self.server.socket.getsockname()[:2] + cert = crypto_util.probe_sni(b'localhost', host=host, port=port) self.assertEqual(jose.ComparableX509(cert), jose.ComparableX509(self.certs[b'localhost'][1])) diff --git a/acme/docs/.gitignore b/acme/docs/.gitignore new file mode 100644 index 000000000..ba65b13af --- /dev/null +++ b/acme/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/acme/docs/Makefile b/acme/docs/Makefile new file mode 100644 index 000000000..79de9c0a3 --- /dev/null +++ b/acme/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/acme-python.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/acme-python.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/acme-python" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/acme-python" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/acme/docs/_static/.gitignore b/acme/docs/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/acme/docs/_templates/.gitignore b/acme/docs/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/acme/docs/api.rst b/acme/docs/api.rst new file mode 100644 index 000000000..c874d8470 --- /dev/null +++ b/acme/docs/api.rst @@ -0,0 +1,8 @@ +================= +API Documentation +================= + +.. toctree:: + :glob: + + api/* diff --git a/acme/docs/api/challenges.rst b/acme/docs/api/challenges.rst new file mode 100644 index 000000000..7bc084fe9 --- /dev/null +++ b/acme/docs/api/challenges.rst @@ -0,0 +1,5 @@ +Challenges +---------- + +.. automodule:: acme.challenges + :members: diff --git a/acme/docs/api/client.rst b/acme/docs/api/client.rst new file mode 100644 index 000000000..d0ab89eb2 --- /dev/null +++ b/acme/docs/api/client.rst @@ -0,0 +1,5 @@ +Client +------ + +.. automodule:: acme.client + :members: diff --git a/acme/docs/api/errors.rst b/acme/docs/api/errors.rst new file mode 100644 index 000000000..644ff0e71 --- /dev/null +++ b/acme/docs/api/errors.rst @@ -0,0 +1,5 @@ +Errors +------ + +.. automodule:: acme.errors + :members: diff --git a/acme/docs/api/fields.rst b/acme/docs/api/fields.rst new file mode 100644 index 000000000..c224f7fef --- /dev/null +++ b/acme/docs/api/fields.rst @@ -0,0 +1,5 @@ +Fields +------ + +.. automodule:: acme.fields + :members: diff --git a/acme/docs/api/jose.rst b/acme/docs/api/jose.rst new file mode 100644 index 000000000..0f7dd627c --- /dev/null +++ b/acme/docs/api/jose.rst @@ -0,0 +1,10 @@ +JOSE +---- + +.. automodule:: acme.jose + :members: + +.. toctree:: + :glob: + + jose/* diff --git a/acme/docs/api/jose/base64.rst b/acme/docs/api/jose/base64.rst new file mode 100644 index 000000000..a40f8b11b --- /dev/null +++ b/acme/docs/api/jose/base64.rst @@ -0,0 +1,5 @@ +JOSE Base64 +----------- + +.. automodule:: acme.jose.b64 + :members: diff --git a/acme/docs/api/jose/errors.rst b/acme/docs/api/jose/errors.rst new file mode 100644 index 000000000..60d9b5c78 --- /dev/null +++ b/acme/docs/api/jose/errors.rst @@ -0,0 +1,5 @@ +Errors +------ + +.. automodule:: acme.jose.errors + :members: diff --git a/acme/docs/api/jose/interfaces.rst b/acme/docs/api/jose/interfaces.rst new file mode 100644 index 000000000..7b72b364f --- /dev/null +++ b/acme/docs/api/jose/interfaces.rst @@ -0,0 +1,5 @@ +Interfaces +---------- + +.. automodule:: acme.jose.interfaces + :members: diff --git a/acme/docs/api/jose/json_util.rst b/acme/docs/api/jose/json_util.rst new file mode 100644 index 000000000..f06edead2 --- /dev/null +++ b/acme/docs/api/jose/json_util.rst @@ -0,0 +1,5 @@ +JSON utilities +-------------- + +.. automodule:: acme.jose.json_util + :members: diff --git a/acme/docs/api/jose/jwa.rst b/acme/docs/api/jose/jwa.rst new file mode 100644 index 000000000..c858a5d1d --- /dev/null +++ b/acme/docs/api/jose/jwa.rst @@ -0,0 +1,5 @@ +JSON Web Algorithms +------------------- + +.. automodule:: acme.jose.jwa + :members: diff --git a/acme/docs/api/jose/jwk.rst b/acme/docs/api/jose/jwk.rst new file mode 100644 index 000000000..8e6bbe13f --- /dev/null +++ b/acme/docs/api/jose/jwk.rst @@ -0,0 +1,5 @@ +JSON Web Key +------------ + +.. automodule:: acme.jose.jwk + :members: diff --git a/acme/docs/api/jose/jws.rst b/acme/docs/api/jose/jws.rst new file mode 100644 index 000000000..15335bf8f --- /dev/null +++ b/acme/docs/api/jose/jws.rst @@ -0,0 +1,5 @@ +JSON Web Signature +------------------ + +.. automodule:: acme.jose.jws + :members: diff --git a/acme/docs/api/jose/util.rst b/acme/docs/api/jose/util.rst new file mode 100644 index 000000000..41cbbcc31 --- /dev/null +++ b/acme/docs/api/jose/util.rst @@ -0,0 +1,5 @@ +Utilities +--------- + +.. automodule:: acme.jose.util + :members: diff --git a/acme/docs/api/messages.rst b/acme/docs/api/messages.rst new file mode 100644 index 000000000..0374a72c8 --- /dev/null +++ b/acme/docs/api/messages.rst @@ -0,0 +1,5 @@ +Messages +-------- + +.. automodule:: acme.messages + :members: diff --git a/acme/docs/api/other.rst b/acme/docs/api/other.rst new file mode 100644 index 000000000..eb27a5d53 --- /dev/null +++ b/acme/docs/api/other.rst @@ -0,0 +1,5 @@ +Other ACME objects +------------------ + +.. automodule:: acme.other + :members: diff --git a/acme/docs/api/standalone.rst b/acme/docs/api/standalone.rst new file mode 100644 index 000000000..a65e5df2a --- /dev/null +++ b/acme/docs/api/standalone.rst @@ -0,0 +1,5 @@ +Standalone +---------- + +.. automodule:: acme.standalone + :members: diff --git a/acme/docs/conf.py b/acme/docs/conf.py new file mode 100644 index 000000000..1448aaea3 --- /dev/null +++ b/acme/docs/conf.py @@ -0,0 +1,312 @@ +# -*- coding: utf-8 -*- +# +# acme-python documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 18 13:38:06 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + + +here = os.path.abspath(os.path.dirname(__file__)) + + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', + 'sphinxcontrib.programoutput', +] + +autodoc_member_order = 'bysource' +autodoc_default_flags = ['show-inheritance', 'private-members'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'acme-python' +copyright = u'2015-2015, Let\'s Encrypt Project' +author = u'Let\'s Encrypt Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0' +# The full version, including alpha/beta/rc tags. +release = '0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = 'py:obj' + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'acme-pythondoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'acme-python.tex', u'acme-python Documentation', + u'Let\'s Encrypt Project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'acme-python', u'acme-python Documentation', + [author], 1), + ('man/jws', 'jws', u'jws script documentation', [project], 1), +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'acme-python', u'acme-python Documentation', + author, 'acme-python', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), +} diff --git a/acme/docs/index.rst b/acme/docs/index.rst new file mode 100644 index 000000000..8d298054e --- /dev/null +++ b/acme/docs/index.rst @@ -0,0 +1,26 @@ +.. acme-python documentation master file, created by + sphinx-quickstart on Sun Oct 18 13:38:06 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to acme-python's documentation! +======================================= + +Contents: + +.. toctree:: + :maxdepth: 2 + + api + +.. automodule:: acme + :members: + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/acme/docs/make.bat b/acme/docs/make.bat new file mode 100644 index 000000000..781185977 --- /dev/null +++ b/acme/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\acme-python.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\acme-python.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/man/jws.rst b/acme/docs/man/jws.rst similarity index 100% rename from docs/man/jws.rst rename to acme/docs/man/jws.rst diff --git a/acme/readthedocs.org.requirements.txt b/acme/readthedocs.org.requirements.txt new file mode 100644 index 000000000..65e6c7cf3 --- /dev/null +++ b/acme/readthedocs.org.requirements.txt @@ -0,0 +1,10 @@ +# readthedocs.org gives no way to change the install command to "pip +# install -e .[docs]" (that would in turn install documentation +# dependencies), but it allows to specify a requirements.txt file at +# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259) + +# Although ReadTheDocs certainly doesn't need to install the project +# in --editable mode (-e), just "pip install .[docs]" does not work as +# expected and "pip install -e .[docs]" must be used instead + +-e acme[docs] diff --git a/acme/setup.py b/acme/setup.py index 6448b7fe9..59c07d5c8 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -32,6 +32,12 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') +docs_extras = [ + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', + 'sphinxcontrib-programoutput', +] + testing_extras = [ 'nose', 'tox', @@ -41,7 +47,7 @@ testing_extras = [ setup( name='acme', version=version, - description='ACME protocol implementation', + description='ACME protocol implementation in Python', url='https://github.com/letsencrypt/letsencrypt', author="Let's Encrypt Project", author_email='client-dev@letsencrypt.org', @@ -61,6 +67,7 @@ setup( include_package_data=True, install_requires=install_requires, extras_require={ + 'docs': docs_extras, 'testing': testing_extras, }, entry_points={ diff --git a/bootstrap/_deb_common.sh b/bootstrap/_deb_common.sh index 687f30d09..2f44c4e91 100755 --- a/bootstrap/_deb_common.sh +++ b/bootstrap/_deb_common.sh @@ -1,57 +1,50 @@ #!/bin/sh -# Tested with: -# - Ubuntu: -# - 12.04 (x64, Travis) -# - 14.04 (x64, Vagrant) -# - 14.10 (x64) -# - Debian: -# - 6.0.10 "squeeze" (x64) -# - 7.8 "wheezy" (x64) -# - 8.0 "jessie" (x64) -# - Raspbian: -# - 7.8 (armhf) +# Current version tested with: +# +# - Ubuntu +# - 14.04 (x64) +# - 15.04 (x64) +# - Debian +# - 7.9 "wheezy" (x64) +# - sid (2015-10-21) (x64) +# Past versions tested with: +# +# - Debian 8.0 "jessie" (x64) +# - Raspbian 7.8 (armhf) -# virtualenv binary can be found in different packages depending on -# distro version (#346) -newer () { - apt-get install -y lsb-release --no-install-recommends - distro=$(lsb_release -si) - # 6.0.10 => 60, 14.04 => 1404 - # TODO: in sid version==unstable - version=$(lsb_release -sr | awk -F '.' '{print $1 $2}') - if [ "$distro" = "Ubuntu" -a "$version" -ge 1410 ] - then - return 0; - elif [ "$distro" = "Debian" -a "$version" -ge 80 ] - then - return 0; - else - return 1; - fi -} +# Believed not to work: +# +# - Debian 6.0.10 "squeeze" (x64) apt-get update -# you can force newer if lsb_release is not available (e.g. Docker -# debian:jessie base image) -if [ "$1" = "newer" ] || newer -then +# virtualenv binary can be found in different packages depending on +# distro version (#346) + +virtualenv= +if apt-cache show virtualenv > /dev/null ; then virtualenv="virtualenv" -else - virtualenv="python-virtualenv" fi +if apt-cache show python-virtualenv > /dev/null ; then + virtualenv="$virtualenv python-virtualenv" +fi apt-get install -y --no-install-recommends \ git-core \ python \ python-dev \ - "$virtualenv" \ + $virtualenv \ gcc \ dialog \ libaugeas0 \ libssl-dev \ libffi-dev \ ca-certificates \ + +if ! which virtualenv > /dev/null ; then + echo Failed to install a working \"virtualenv\" command, exiting + exit 1 +fi diff --git a/bootstrap/archlinux.sh b/bootstrap/archlinux.sh index 6de7c23d4..884262f0b 100755 --- a/bootstrap/archlinux.sh +++ b/bootstrap/archlinux.sh @@ -3,7 +3,7 @@ # "python-virtualenv" is Python3, but "python2-virtualenv" provides # only "virtualenv2" binary, not "virtualenv" necessary in # ./bootstrap/dev/_common_venv.sh -pacman -S \ +pacman -S --needed \ git \ python2 \ python-virtualenv \ diff --git a/docs/.gitignore b/docs/.gitignore index 69fa449dd..ba65b13af 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1 @@ -_build/ +/_build/ diff --git a/docs/conf.py b/docs/conf.py index e2b360a6e..124f0f9ad 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,13 +17,6 @@ import os import re import sys -import mock - - -# http://docs.readthedocs.org/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules -# c.f. #262 -sys.modules.update( - (mod_name, mock.MagicMock()) for mod_name in ['augeas']) here = os.path.abspath(os.path.dirname(__file__)) @@ -36,13 +29,11 @@ with codecs.open(init_fn, encoding='utf8') as fd: # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) -for pkg in 'acme', 'letsencrypt-apache', 'letsencrypt-nginx': - sys.path.insert(0, os.path.abspath(os.path.join(here, '..', pkg))) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -74,7 +65,7 @@ master_doc = 'index' # General information about the project. project = u'Let\'s Encrypt' -copyright = u'2014, Let\'s Encrypt Project' +copyright = u'2014-2015, Let\'s Encrypt Project' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -126,6 +117,9 @@ pygments_style = 'sphinx' # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + # -- Options for HTML output ---------------------------------------------- @@ -289,7 +283,6 @@ man_pages = [ [project], 1), ('man/letsencrypt-renewer', 'letsencrypt-renewer', u'letsencrypt-renewer script documentation', [project], 1), - ('man/jws', 'jws', u'jws script documentation', [project], 1), ] # If true, show URL addresses after external links. @@ -320,7 +313,7 @@ texinfo_documents = [ #texinfo_no_detailmenu = False -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'http://docs.python.org/': None} - -todo_include_todos = True +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), + 'acme': ('https://acme-python.readthedocs.org', None), +} diff --git a/docs/contributing.rst b/docs/contributing.rst index 6d0a2d4ba..60e7f35c2 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -84,14 +84,8 @@ run (in a separate terminal):: If you would like to test `letsencrypt_nginx` plugin (highly encouraged) make sure to install prerequisites as listed in -``letsencrypt-nginx/tests/boulder-integration.sh``: - -.. include:: ../letsencrypt-nginx/tests/boulder-integration.sh - :start-line: 1 - :end-line: 2 - :code: shell - -and rerun the integration tests suite. +``letsencrypt-nginx/tests/boulder-integration.sh`` and rerun +the integration tests suite. .. _Boulder: https://github.com/letsencrypt/boulder .. _Go: https://golang.org @@ -372,6 +366,6 @@ FreeBSD Bootstrap script for FreeBSD uses ``pkg`` for package installation, i.e. it does not use ports. -FreeBSD by default uses ``tcsh``. In order to activate virtulenv (see -below), you will need a compatbile shell, e.g. ``pkg install bash && +FreeBSD by default uses ``tcsh``. In order to activate virtualenv (see +below), you will need a compatible shell, e.g. ``pkg install bash && bash``. diff --git a/docs/index.rst b/docs/index.rst index b076b45c6..72be096f9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,6 @@ Welcome to the Let's Encrypt client documentation! :maxdepth: 1 api - pkgs Indices and tables diff --git a/docs/pkgs.rst b/docs/pkgs.rst deleted file mode 100644 index 2e1b18dfb..000000000 --- a/docs/pkgs.rst +++ /dev/null @@ -1,14 +0,0 @@ -======== -Packages -======== - -.. note:: It is planned to distribute `acme` and plugins separately as - described in `#358`_. For the time being those packages are bundled - together into a single repo, and single documentation. - -.. _`#358`: https://github.com/letsencrypt/letsencrypt/issues/358 - -.. toctree:: - :glob: - - pkgs/** diff --git a/docs/pkgs/acme/index.rst b/docs/pkgs/acme/index.rst deleted file mode 100644 index 23c5a3284..000000000 --- a/docs/pkgs/acme/index.rst +++ /dev/null @@ -1,56 +0,0 @@ -:mod:`acme` -=========== - -.. contents:: - -.. automodule:: acme - :members: - - -Client ------- - -.. automodule:: acme.client - :members: - - -Messages --------- - -.. automodule:: acme.messages - :members: - - -Challenges ----------- - -.. automodule:: acme.challenges - :members: - - -Other ACME objects ------------------- - -.. automodule:: acme.other - :members: - - -Fields ------- - -.. automodule:: acme.fields - :members: - - -Errors ------- - -.. automodule:: acme.errors - :members: - - -Standalone ----------- - -.. automodule:: acme.standalone - :members: diff --git a/docs/pkgs/acme/jose.rst b/docs/pkgs/acme/jose.rst deleted file mode 100644 index fa3a0e9bb..000000000 --- a/docs/pkgs/acme/jose.rst +++ /dev/null @@ -1,67 +0,0 @@ -:mod:`acme.jose` -================ - -.. contents:: - -.. automodule:: acme.jose - :members: - - -JSON Web Algorithms -------------------- - -.. automodule:: acme.jose.jwa - :members: - - -JSON Web Key ------------- - -.. automodule:: acme.jose.jwk - :members: - - -JSON Web Signature ------------------- - -.. automodule:: acme.jose.jws - :members: - - -Implementation details ----------------------- - - -Interfaces -~~~~~~~~~~ - -.. automodule:: acme.jose.interfaces - :members: - - -Errors -~~~~~~ - -.. automodule:: acme.jose.errors - :members: - - -JSON utilities -~~~~~~~~~~~~~~ - -.. automodule:: acme.jose.json_util - :members: - - -JOSE Base64 -~~~~~~~~~~~ - -.. automodule:: acme.jose.b64 - :members: - - -Utilities -~~~~~~~~~ - -.. automodule:: acme.jose.util - :members: diff --git a/docs/pkgs/letsencrypt_apache.rst b/docs/pkgs/letsencrypt_apache.rst deleted file mode 100644 index c4e7e8e6e..000000000 --- a/docs/pkgs/letsencrypt_apache.rst +++ /dev/null @@ -1,42 +0,0 @@ -:mod:`letsencrypt_apache` -------------------------- - -.. automodule:: letsencrypt_apache - :members: - -:mod:`letsencrypt_apache.configurator` -====================================== - -.. automodule:: letsencrypt_apache.configurator - :members: - -:mod:`letsencrypt_apache.display_ops` -===================================== - -.. automodule:: letsencrypt_apache.display_ops - :members: - -:mod:`letsencrypt_apache.dvsni` -=============================== - -.. automodule:: letsencrypt_apache.dvsni - :members: - -:mod:`letsencrypt_apache.obj` -============================= - -.. automodule:: letsencrypt_apache.obj - :members: - -:mod:`letsencrypt_apache.parser` -================================ - -.. automodule:: letsencrypt_apache.parser - :members: - - -:mod:`letsencrypt_apache.augeas_configurator` -============================================= - -.. automodule:: letsencrypt_apache.augeas_configurator - :members: diff --git a/docs/pkgs/letsencrypt_nginx.rst b/docs/pkgs/letsencrypt_nginx.rst deleted file mode 100644 index 03114b685..000000000 --- a/docs/pkgs/letsencrypt_nginx.rst +++ /dev/null @@ -1,35 +0,0 @@ -:mod:`letsencrypt_nginx` ------------------------- - -.. automodule:: letsencrypt_nginx - :members: - -:mod:`letsencrypt_nginx.configurator` -===================================== - -.. automodule:: letsencrypt_nginx.configurator - :members: - -:mod:`letsencrypt_nginx.dvsni` -============================== - -.. automodule:: letsencrypt_nginx.dvsni - :members: - -:mod:`letsencrypt_nginx.obj` -============================ - -.. automodule:: letsencrypt_nginx.obj - :members: - -:mod:`letsencrypt_nginx.parser` -=============================== - -.. automodule:: letsencrypt_nginx.parser - :members: - -:mod:`letsencrypt_nginx.nginxparser` -==================================== - -.. automodule:: letsencrypt_nginx.nginxparser - :members: diff --git a/docs/using.rst b/docs/using.rst index 0a781431a..879ea49c4 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -76,7 +76,7 @@ server that the domain your requesting a cert for resolves to, .. code-block:: shell - sudo docker auth -it --rm -p 443:443 --name letsencrypt \ + sudo docker run -it --rm -p 443:443 --name letsencrypt \ -v "/etc/letsencrypt:/etc/letsencrypt" \ -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ quay.io/letsencrypt/letsencrypt:latest auth @@ -85,4 +85,4 @@ and follow the instructions. Your new cert will be available in ``/etc/letsencrypt/certs``. .. _Docker: https://docker.com -.. _`install Docker`: https://docs.docker.com/docker/userguide/ +.. _`install Docker`: https://docs.docker.com/userguide/ diff --git a/examples/dev-cli.ini b/examples/dev-cli.ini index 085d4bfcc..2ea5d247d 100644 --- a/examples/dev-cli.ini +++ b/examples/dev-cli.ini @@ -8,7 +8,7 @@ email = foo@example.com domains = example.com text = True -agree-eula = True +agree-dev-preview = True agree-tos = True debug = True # Unfortunately, it's not possible to specify "verbose" multiple times diff --git a/letsencrypt-apache/MANIFEST.in b/letsencrypt-apache/MANIFEST.in index ff99bf0d8..51c2df858 100644 --- a/letsencrypt-apache/MANIFEST.in +++ b/letsencrypt-apache/MANIFEST.in @@ -1,4 +1,5 @@ include LICENSE.txt include README.rst +recursive-include docs * recursive-include letsencrypt_apache/tests/testdata * include letsencrypt_apache/options-ssl-apache.conf diff --git a/letsencrypt-apache/docs/.gitignore b/letsencrypt-apache/docs/.gitignore new file mode 100644 index 000000000..ba65b13af --- /dev/null +++ b/letsencrypt-apache/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/letsencrypt-apache/docs/Makefile b/letsencrypt-apache/docs/Makefile new file mode 100644 index 000000000..9bf5154fe --- /dev/null +++ b/letsencrypt-apache/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/letsencrypt-apache.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/letsencrypt-apache.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/letsencrypt-apache" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/letsencrypt-apache" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/letsencrypt-apache/docs/_static/.gitignore b/letsencrypt-apache/docs/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-apache/docs/_templates/.gitignore b/letsencrypt-apache/docs/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-apache/docs/api.rst b/letsencrypt-apache/docs/api.rst new file mode 100644 index 000000000..8668ec5d8 --- /dev/null +++ b/letsencrypt-apache/docs/api.rst @@ -0,0 +1,8 @@ +================= +API Documentation +================= + +.. toctree:: + :glob: + + api/** diff --git a/letsencrypt-apache/docs/api/augeas_configurator.rst b/letsencrypt-apache/docs/api/augeas_configurator.rst new file mode 100644 index 000000000..3b1821e3d --- /dev/null +++ b/letsencrypt-apache/docs/api/augeas_configurator.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.augeas_configurator` +--------------------------------------------- + +.. automodule:: letsencrypt_apache.augeas_configurator + :members: diff --git a/letsencrypt-apache/docs/api/configurator.rst b/letsencrypt-apache/docs/api/configurator.rst new file mode 100644 index 000000000..2ed613286 --- /dev/null +++ b/letsencrypt-apache/docs/api/configurator.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.configurator` +-------------------------------------- + +.. automodule:: letsencrypt_apache.configurator + :members: diff --git a/letsencrypt-apache/docs/api/display_ops.rst b/letsencrypt-apache/docs/api/display_ops.rst new file mode 100644 index 000000000..59ff9d15e --- /dev/null +++ b/letsencrypt-apache/docs/api/display_ops.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.display_ops` +------------------------------------- + +.. automodule:: letsencrypt_apache.display_ops + :members: diff --git a/letsencrypt-apache/docs/api/dvsni.rst b/letsencrypt-apache/docs/api/dvsni.rst new file mode 100644 index 000000000..945771db8 --- /dev/null +++ b/letsencrypt-apache/docs/api/dvsni.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.dvsni` +------------------------------- + +.. automodule:: letsencrypt_apache.dvsni + :members: diff --git a/letsencrypt-apache/docs/api/obj.rst b/letsencrypt-apache/docs/api/obj.rst new file mode 100644 index 000000000..969293ca1 --- /dev/null +++ b/letsencrypt-apache/docs/api/obj.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.obj` +----------------------------- + +.. automodule:: letsencrypt_apache.obj + :members: diff --git a/letsencrypt-apache/docs/api/parser.rst b/letsencrypt-apache/docs/api/parser.rst new file mode 100644 index 000000000..0c998e06c --- /dev/null +++ b/letsencrypt-apache/docs/api/parser.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_apache.parser` +-------------------------------- + +.. automodule:: letsencrypt_apache.parser + :members: diff --git a/letsencrypt-apache/docs/conf.py b/letsencrypt-apache/docs/conf.py new file mode 100644 index 000000000..e439428af --- /dev/null +++ b/letsencrypt-apache/docs/conf.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +# +# letsencrypt-apache documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 18 13:39:26 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + +import mock + + +# http://docs.readthedocs.org/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules +# c.f. #262 +sys.modules.update( + (mod_name, mock.MagicMock()) for mod_name in ['augeas']) + +here = os.path.abspath(os.path.dirname(__file__)) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', +] + +autodoc_member_order = 'bysource' +autodoc_default_flags = ['show-inheritance', 'private-members'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'letsencrypt-apache' +copyright = u'2014-2015, Let\'s Encrypt Project' +author = u'Let\'s Encrypt Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0' +# The full version, including alpha/beta/rc tags. +release = '0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = 'py:obj' + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'letsencrypt-apachedoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'letsencrypt-apache.tex', u'letsencrypt-apache Documentation', + u'Let\'s Encrypt Project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'letsencrypt-apache', u'letsencrypt-apache Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'letsencrypt-apache', u'letsencrypt-apache Documentation', + author, 'letsencrypt-apache', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), + 'acme': ('https://acme-python.readthedocs.org', None), + 'letsencrypt': ('https://letsencrypt.readthedocs.org', None), +} diff --git a/letsencrypt-apache/docs/index.rst b/letsencrypt-apache/docs/index.rst new file mode 100644 index 000000000..f968ccbef --- /dev/null +++ b/letsencrypt-apache/docs/index.rst @@ -0,0 +1,31 @@ +.. letsencrypt-apache documentation master file, created by + sphinx-quickstart on Sun Oct 18 13:39:26 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to letsencrypt-apache's documentation! +============================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + +.. toctree:: + :maxdepth: 1 + + api + + +.. automodule:: letsencrypt_apache + :members: + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/letsencrypt-apache/docs/make.bat b/letsencrypt-apache/docs/make.bat new file mode 100644 index 000000000..62a54fd2c --- /dev/null +++ b/letsencrypt-apache/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\letsencrypt-apache.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\letsencrypt-apache.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/letsencrypt-apache/letsencrypt_apache/configurator.py b/letsencrypt-apache/letsencrypt_apache/configurator.py index de69af91c..d376fe4b6 100644 --- a/letsencrypt-apache/letsencrypt_apache/configurator.py +++ b/letsencrypt-apache/letsencrypt_apache/configurator.py @@ -165,7 +165,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): temp_install(self.mod_ssl_conf) def deploy_cert(self, domain, cert_path, key_path, - chain_path=None, fullchain_path=None): # pylint: disable=unused-argument + chain_path=None, fullchain_path=None): # pylint: disable=unused-argument """Deploys certificate to specified virtual host. Currently tries to find the last directives to deploy the cert in diff --git a/letsencrypt-apache/readthedocs.org.requirements.txt b/letsencrypt-apache/readthedocs.org.requirements.txt new file mode 100644 index 000000000..9e782a01e --- /dev/null +++ b/letsencrypt-apache/readthedocs.org.requirements.txt @@ -0,0 +1,10 @@ +# readthedocs.org gives no way to change the install command to "pip +# install -e .[docs]" (that would in turn install documentation +# dependencies), but it allows to specify a requirements.txt file at +# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259) + +# Although ReadTheDocs certainly doesn't need to install the project +# in --editable mode (-e), just "pip install .[docs]" does not work as +# expected and "pip install -e .[docs]" must be used instead + +-e letsencrypt-apache[docs] diff --git a/letsencrypt-apache/setup.py b/letsencrypt-apache/setup.py index 626e700b2..2180219f1 100644 --- a/letsencrypt-apache/setup.py +++ b/letsencrypt-apache/setup.py @@ -20,6 +20,11 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') +docs_extras = [ + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', +] + setup( name='letsencrypt-apache', version=version, @@ -48,6 +53,9 @@ setup( packages=find_packages(), include_package_data=True, install_requires=install_requires, + extras_require={ + 'docs': docs_extras, + }, entry_points={ 'letsencrypt.plugins': [ 'apache = letsencrypt_apache.configurator:ApacheConfigurator', diff --git a/letsencrypt-auto b/letsencrypt-auto index 0b3d9b72d..5b974c1f8 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -1,5 +1,8 @@ #!/bin/sh -e # +# A script to run the latest release version of the Let's Encrypt in a +# virtual environment +# # Installs and updates the letencrypt virtualenv, and runs letsencrypt # using that virtual environment. This allows the client to function decently # without requiring specific versions of its dependencies from the operating @@ -18,7 +21,7 @@ fi for arg in "$@" ; do # This first clause is redundant with the third, but hedging on portability - if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- -v+ ; then + if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then VERBOSE=1 fi done @@ -69,8 +72,12 @@ if [ "$VERBOSE" = 1 ] ; then echo $VENV_BIN/pip install -U setuptools $VENV_BIN/pip install -U pip - # nginx is buggy / disabled for now... - $VENV_BIN/pip install -U letsencrypt letsencrypt-apache #letsencrypt-nginx + $VENV_BIN/pip install -U letsencrypt letsencrypt-apache + # nginx is buggy / disabled for now, but upgrade it if the user has + # installed it manually + if $VENV_BIN/pip freeze | grep -q letsencrypt-nginx ; then + $VENV_BIN/pip install -U letsencrypt letsencrypt-nginx + fi else $VENV_BIN/pip install -U setuptools > /dev/null echo -n . @@ -80,6 +87,10 @@ else $VENV_BIN/pip install -U letsencrypt > /dev/null echo -n . $VENV_BIN/pip install -U letsencrypt-apache > /dev/null + if $VENV_BIN/pip freeze | grep -q letsencrypt-nginx ; then + echo -n . + $VENV_BIN/pip install -U letsencrypt-nginx > /dev/null + fi echo fi diff --git a/letsencrypt-compatibility-test/MANIFEST.in b/letsencrypt-compatibility-test/MANIFEST.in index 4d346a5d0..24d777841 100644 --- a/letsencrypt-compatibility-test/MANIFEST.in +++ b/letsencrypt-compatibility-test/MANIFEST.in @@ -1,5 +1,6 @@ include LICENSE.txt include README.rst +recursive-include docs * include letsencrypt_compatibility_test/configurators/apache/a2enmod.sh include letsencrypt_compatibility_test/configurators/apache/a2dismod.sh include letsencrypt_compatibility_test/configurators/apache/Dockerfile diff --git a/letsencrypt-compatibility-test/docs/.gitignore b/letsencrypt-compatibility-test/docs/.gitignore new file mode 100644 index 000000000..ba65b13af --- /dev/null +++ b/letsencrypt-compatibility-test/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/letsencrypt-compatibility-test/docs/Makefile b/letsencrypt-compatibility-test/docs/Makefile new file mode 100644 index 000000000..90582a59b --- /dev/null +++ b/letsencrypt-compatibility-test/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/letsencrypt-compatibility-test.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/letsencrypt-compatibility-test.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/letsencrypt-compatibility-test" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/letsencrypt-compatibility-test" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/letsencrypt-compatibility-test/docs/_static/.gitignore b/letsencrypt-compatibility-test/docs/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-compatibility-test/docs/_templates/.gitignore b/letsencrypt-compatibility-test/docs/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-compatibility-test/docs/api.rst b/letsencrypt-compatibility-test/docs/api.rst new file mode 100644 index 000000000..8668ec5d8 --- /dev/null +++ b/letsencrypt-compatibility-test/docs/api.rst @@ -0,0 +1,8 @@ +================= +API Documentation +================= + +.. toctree:: + :glob: + + api/** diff --git a/docs/pkgs/letsencrypt_compatibility_test.rst b/letsencrypt-compatibility-test/docs/api/index.rst similarity index 100% rename from docs/pkgs/letsencrypt_compatibility_test.rst rename to letsencrypt-compatibility-test/docs/api/index.rst diff --git a/letsencrypt-compatibility-test/docs/conf.py b/letsencrypt-compatibility-test/docs/conf.py new file mode 100644 index 000000000..5a63c1dca --- /dev/null +++ b/letsencrypt-compatibility-test/docs/conf.py @@ -0,0 +1,314 @@ +# -*- coding: utf-8 -*- +# +# letsencrypt-compatibility-test documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 18 13:40:53 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + + +here = os.path.abspath(os.path.dirname(__file__)) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', + 'repoze.sphinx.autointerface', +] + +autodoc_member_order = 'bysource' +autodoc_default_flags = ['show-inheritance', 'private-members'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'letsencrypt-compatibility-test' +copyright = u'2014-2015, Let\'s Encrypt Project' +author = u'Let\'s Encrypt Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0' +# The full version, including alpha/beta/rc tags. +release = '0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = 'py:obj' + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'letsencrypt-compatibility-testdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'letsencrypt-compatibility-test.tex', u'letsencrypt-compatibility-test Documentation', + u'Let\'s Encrypt Project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'letsencrypt-compatibility-test', u'letsencrypt-compatibility-test Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'letsencrypt-compatibility-test', u'letsencrypt-compatibility-test Documentation', + author, 'letsencrypt-compatibility-test', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), + 'acme': ('https://acme-python.readthedocs.org', None), + 'letsencrypt': ('https://letsencrypt.readthedocs.org', None), + 'letsencrypt-apache': ('https://letsencrypt-apache.readthedocs.org', None), + 'letsencrypt-nginx': ('https://letsencrypt-nginx.readthedocs.org', None), +} diff --git a/letsencrypt-compatibility-test/docs/index.rst b/letsencrypt-compatibility-test/docs/index.rst new file mode 100644 index 000000000..df57ee6e6 --- /dev/null +++ b/letsencrypt-compatibility-test/docs/index.rst @@ -0,0 +1,27 @@ +.. letsencrypt-compatibility-test documentation master file, created by + sphinx-quickstart on Sun Oct 18 13:40:53 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to letsencrypt-compatibility-test's documentation! +========================================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + +.. toctree:: + :maxdepth: 1 + + api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/letsencrypt-compatibility-test/docs/make.bat b/letsencrypt-compatibility-test/docs/make.bat new file mode 100644 index 000000000..c75269bdc --- /dev/null +++ b/letsencrypt-compatibility-test/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\letsencrypt-compatibility-test.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\letsencrypt-compatibility-test.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/letsencrypt-compatibility-test/letsencrypt_compatibility_test/configurators/apache/common.py b/letsencrypt-compatibility-test/letsencrypt_compatibility_test/configurators/apache/common.py index 5f183b611..5fef8c47f 100644 --- a/letsencrypt-compatibility-test/letsencrypt_compatibility_test/configurators/apache/common.py +++ b/letsencrypt-compatibility-test/letsencrypt_compatibility_test/configurators/apache/common.py @@ -176,7 +176,7 @@ class Proxy(configurators_common.Proxy): return {"example.com"} def deploy_cert(self, domain, cert_path, key_path, chain_path=None, - fullchain_path=None): + fullchain_path=None): """Installs cert""" cert_path, key_path, chain_path = self.copy_certs_and_keys( cert_path, key_path, chain_path) diff --git a/letsencrypt-compatibility-test/readthedocs.org.requirements.txt b/letsencrypt-compatibility-test/readthedocs.org.requirements.txt new file mode 100644 index 000000000..86d680426 --- /dev/null +++ b/letsencrypt-compatibility-test/readthedocs.org.requirements.txt @@ -0,0 +1,10 @@ +# readthedocs.org gives no way to change the install command to "pip +# install -e .[docs]" (that would in turn install documentation +# dependencies), but it allows to specify a requirements.txt file at +# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259) + +# Although ReadTheDocs certainly doesn't need to install the project +# in --editable mode (-e), just "pip install .[docs]" does not work as +# expected and "pip install -e .[docs]" must be used instead + +-e letsencrypt-compatibility-test[docs] diff --git a/letsencrypt-compatibility-test/setup.py b/letsencrypt-compatibility-test/setup.py index 2e70fd1d7..3bd8f274e 100644 --- a/letsencrypt-compatibility-test/setup.py +++ b/letsencrypt-compatibility-test/setup.py @@ -19,6 +19,12 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') +docs_extras = [ + 'repoze.sphinx.autointerface', + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', +] + setup( name='letsencrypt-compatibility-test', version=version, @@ -41,6 +47,9 @@ setup( packages=find_packages(), include_package_data=True, install_requires=install_requires, + extras_require={ + 'docs': docs_extras, + }, entry_points={ 'console_scripts': [ 'letsencrypt-compatibility-test = letsencrypt_compatibility_test.test_driver:main', diff --git a/letsencrypt-nginx/MANIFEST.in b/letsencrypt-nginx/MANIFEST.in index c4bd67735..912d624d9 100644 --- a/letsencrypt-nginx/MANIFEST.in +++ b/letsencrypt-nginx/MANIFEST.in @@ -1,4 +1,5 @@ include LICENSE.txt include README.rst +recursive-include docs * recursive-include letsencrypt_nginx/tests/testdata * include letsencrypt_nginx/options-ssl-nginx.conf diff --git a/letsencrypt-nginx/docs/.gitignore b/letsencrypt-nginx/docs/.gitignore new file mode 100644 index 000000000..ba65b13af --- /dev/null +++ b/letsencrypt-nginx/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/letsencrypt-nginx/docs/Makefile b/letsencrypt-nginx/docs/Makefile new file mode 100644 index 000000000..3a3828235 --- /dev/null +++ b/letsencrypt-nginx/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/letsencrypt-nginx.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/letsencrypt-nginx.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/letsencrypt-nginx" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/letsencrypt-nginx" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/letsencrypt-nginx/docs/_static/.gitignore b/letsencrypt-nginx/docs/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-nginx/docs/_templates/.gitignore b/letsencrypt-nginx/docs/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt-nginx/docs/api.rst b/letsencrypt-nginx/docs/api.rst new file mode 100644 index 000000000..8668ec5d8 --- /dev/null +++ b/letsencrypt-nginx/docs/api.rst @@ -0,0 +1,8 @@ +================= +API Documentation +================= + +.. toctree:: + :glob: + + api/** diff --git a/letsencrypt-nginx/docs/api/dvsni.rst b/letsencrypt-nginx/docs/api/dvsni.rst new file mode 100644 index 000000000..4f5f9d7e3 --- /dev/null +++ b/letsencrypt-nginx/docs/api/dvsni.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_nginx.dvsni` +------------------------------ + +.. automodule:: letsencrypt_nginx.dvsni + :members: diff --git a/letsencrypt-nginx/docs/api/nginxparser.rst b/letsencrypt-nginx/docs/api/nginxparser.rst new file mode 100644 index 000000000..e55bda0b1 --- /dev/null +++ b/letsencrypt-nginx/docs/api/nginxparser.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_nginx.nginxparser` +------------------------------------ + +.. automodule:: letsencrypt_nginx.nginxparser + :members: diff --git a/letsencrypt-nginx/docs/api/obj.rst b/letsencrypt-nginx/docs/api/obj.rst new file mode 100644 index 000000000..418b87cf7 --- /dev/null +++ b/letsencrypt-nginx/docs/api/obj.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_nginx.obj` +---------------------------- + +.. automodule:: letsencrypt_nginx.obj + :members: diff --git a/letsencrypt-nginx/docs/api/parser.rst b/letsencrypt-nginx/docs/api/parser.rst new file mode 100644 index 000000000..6582263ef --- /dev/null +++ b/letsencrypt-nginx/docs/api/parser.rst @@ -0,0 +1,5 @@ +:mod:`letsencrypt_nginx.parser` +------------------------------- + +.. automodule:: letsencrypt_nginx.parser + :members: diff --git a/letsencrypt-nginx/docs/conf.py b/letsencrypt-nginx/docs/conf.py new file mode 100644 index 000000000..8bcae3a78 --- /dev/null +++ b/letsencrypt-nginx/docs/conf.py @@ -0,0 +1,311 @@ +# -*- coding: utf-8 -*- +# +# letsencrypt-nginx documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 18 13:39:39 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + + +here = os.path.abspath(os.path.dirname(__file__)) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', +] + +autodoc_member_order = 'bysource' +autodoc_default_flags = ['show-inheritance', 'private-members'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'letsencrypt-nginx' +copyright = u'2014-2015, Let\'s Encrypt Project' +author = u'Let\'s Encrypt Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0' +# The full version, including alpha/beta/rc tags. +release = '0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = 'py:obj' + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'letsencrypt-nginxdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'letsencrypt-nginx.tex', u'letsencrypt-nginx Documentation', + u'Let\'s Encrypt Project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'letsencrypt-nginx', u'letsencrypt-nginx Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'letsencrypt-nginx', u'letsencrypt-nginx Documentation', + author, 'letsencrypt-nginx', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), + 'acme': ('https://acme-python.readthedocs.org', None), + 'letsencrypt': ('https://letsencrypt.readthedocs.org', None), +} diff --git a/letsencrypt-nginx/docs/index.rst b/letsencrypt-nginx/docs/index.rst new file mode 100644 index 000000000..e4f8f715f --- /dev/null +++ b/letsencrypt-nginx/docs/index.rst @@ -0,0 +1,31 @@ +.. letsencrypt-nginx documentation master file, created by + sphinx-quickstart on Sun Oct 18 13:39:39 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to letsencrypt-nginx's documentation! +============================================= + +Contents: + +.. toctree:: + :maxdepth: 2 + + +.. toctree:: + :maxdepth: 1 + + api + + +.. automodule:: letsencrypt_nginx + :members: + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/letsencrypt-nginx/docs/make.bat b/letsencrypt-nginx/docs/make.bat new file mode 100644 index 000000000..eb19a3fb5 --- /dev/null +++ b/letsencrypt-nginx/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\letsencrypt-nginx.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\letsencrypt-nginx.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/letsencrypt-nginx/letsencrypt_nginx/configurator.py b/letsencrypt-nginx/letsencrypt_nginx/configurator.py index d1ab8f3d1..29e69e498 100644 --- a/letsencrypt-nginx/letsencrypt_nginx/configurator.py +++ b/letsencrypt-nginx/letsencrypt_nginx/configurator.py @@ -119,7 +119,7 @@ class NginxConfigurator(common.Plugin): # Entry point in main.py for installing cert def deploy_cert(self, domain, cert_path, key_path, - chain_path, fullchain_path): + chain_path, fullchain_path): # pylint: disable=unused-argument """Deploys certificate to specified virtual host. diff --git a/letsencrypt-nginx/letsencrypt_nginx/parser.py b/letsencrypt-nginx/letsencrypt_nginx/parser.py index fc8ed95f1..19483821a 100644 --- a/letsencrypt-nginx/letsencrypt_nginx/parser.py +++ b/letsencrypt-nginx/letsencrypt_nginx/parser.py @@ -491,5 +491,5 @@ def _add_directives(block, directives, replace=False): changed = True if not changed: raise errors.MisconfigurationError( - 'LetsEncrypt expected directive for %s in the Nginx ' + 'Let\'s Encrypt expected directive for %s in the Nginx ' 'config but did not find it.' % directive[0]) diff --git a/letsencrypt-nginx/letsencrypt_nginx/tests/configurator_test.py b/letsencrypt-nginx/letsencrypt_nginx/tests/configurator_test.py index 203f9920c..d8bdf8355 100644 --- a/letsencrypt-nginx/letsencrypt_nginx/tests/configurator_test.py +++ b/letsencrypt-nginx/letsencrypt_nginx/tests/configurator_test.py @@ -112,11 +112,11 @@ class NginxConfiguratorTest(util.NginxTest): generated_conf = self.config.parser.parsed[example_conf] self.assertTrue(util.contains_at_depth(generated_conf, - ['ssl_stapling', 'on'], 2)) + ['ssl_stapling', 'on'], 2)) self.assertTrue(util.contains_at_depth(generated_conf, - ['ssl_stapling_verify', 'on'], 2)) + ['ssl_stapling_verify', 'on'], 2)) self.assertTrue(util.contains_at_depth(generated_conf, - ['ssl_trusted_certificate', 'example/chain.pem'], 2)) + ['ssl_trusted_certificate', 'example/chain.pem'], 2)) def test_deploy_cert(self): server_conf = self.config.parser.abs_path('server.conf') @@ -165,19 +165,20 @@ class NginxConfiguratorTest(util.NginxTest): self.assertEqual([['server_name', 'somename alias another.alias']], parsed_server_conf) self.assertTrue(util.contains_at_depth(parsed_nginx_conf, - [['server'], - [['include', self.config.parser.loc["ssl_options"]], - ['ssl_certificate_key', '/etc/nginx/key.pem'], - ['ssl_certificate', '/etc/nginx/fullchain.pem'], - ['error_log', error_log], - ['access_log', access_log], - ['listen', '5001 ssl'], - ['listen', '8000'], - ['listen', 'somename:8080'], - ['include', 'server.conf'], - [['location', '/'], - [['root', 'html'], ['index', 'index.html index.htm']]]]], - 2)) + [['server'], + [['include', self.config.parser.loc["ssl_options"]], + ['ssl_certificate_key', '/etc/nginx/key.pem'], + ['ssl_certificate', '/etc/nginx/fullchain.pem'], + ['error_log', error_log], + ['access_log', access_log], + ['listen', '5001 ssl'], + ['listen', '8000'], + ['listen', 'somename:8080'], + ['include', 'server.conf'], + [['location', '/'], + [['root', 'html'], + ['index', 'index.html index.htm']]]]], + 2)) def test_get_all_certs_keys(self): nginx_conf = self.config.parser.abs_path('nginx.conf') diff --git a/letsencrypt-nginx/readthedocs.org.requirements.txt b/letsencrypt-nginx/readthedocs.org.requirements.txt new file mode 100644 index 000000000..9a36ed259 --- /dev/null +++ b/letsencrypt-nginx/readthedocs.org.requirements.txt @@ -0,0 +1,10 @@ +# readthedocs.org gives no way to change the install command to "pip +# install -e .[docs]" (that would in turn install documentation +# dependencies), but it allows to specify a requirements.txt file at +# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259) + +# Although ReadTheDocs certainly doesn't need to install the project +# in --editable mode (-e), just "pip install .[docs]" does not work as +# expected and "pip install -e .[docs]" must be used instead + +-e letsencrypt-nginx[docs] diff --git a/letsencrypt-nginx/setup.py b/letsencrypt-nginx/setup.py index a37b8222b..5d80807d1 100644 --- a/letsencrypt-nginx/setup.py +++ b/letsencrypt-nginx/setup.py @@ -20,6 +20,11 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') +docs_extras = [ + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', +] + setup( name='letsencrypt-nginx', version=version, @@ -48,6 +53,9 @@ setup( packages=find_packages(), include_package_data=True, install_requires=install_requires, + extras_require={ + 'docs': docs_extras, + }, entry_points={ 'letsencrypt.plugins': [ 'nginx = letsencrypt_nginx.configurator:NginxConfigurator', diff --git a/letsencrypt/EULA b/letsencrypt/DISCLAIMER similarity index 100% rename from letsencrypt/EULA rename to letsencrypt/DISCLAIMER diff --git a/letsencrypt/account.py b/letsencrypt/account.py index 81d31b831..c41b10c4a 100644 --- a/letsencrypt/account.py +++ b/letsencrypt/account.py @@ -56,7 +56,7 @@ class Account(object): # pylint: disable=too-few-public-methods self.id = hashlib.md5( self.key.key.public_key().public_bytes( - encoding=serialization.Encoding.DER, + encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) ).hexdigest() # Implementation note: Email? Multiple accounts can have the diff --git a/letsencrypt/auth_handler.py b/letsencrypt/auth_handler.py index b27a569f6..2da053f8c 100644 --- a/letsencrypt/auth_handler.py +++ b/letsencrypt/auth_handler.py @@ -153,10 +153,8 @@ class AuthHandler(object): """ active_achalls = [] for achall, resp in itertools.izip(achalls, resps): - # XXX: make sure that all achalls, including those - # corresponding to None or False returned from - # Authenticator are removed from the queue and thus avoid - # infinite loop + # This line needs to be outside of the if block below to + # ensure failed challenges are cleaned up correctly active_achalls.append(achall) # Don't send challenges for None and False authenticator responses diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 1855728c3..822f231ef 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -28,7 +28,6 @@ from letsencrypt import configuration from letsencrypt import constants from letsencrypt import client from letsencrypt import crypto_util -from letsencrypt import errors from letsencrypt import interfaces from letsencrypt import le_util from letsencrypt import log @@ -37,6 +36,7 @@ from letsencrypt import storage from letsencrypt.display import util as display_util from letsencrypt.display import ops as display_ops +from letsencrypt.errors import Error, PluginSelectionError, CertStorageError from letsencrypt.plugins import disco as plugins_disco @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) # This is the stub to include in help generated by argparse SHORT_USAGE = """ - letsencrypt [SUBCOMMAND] [options] [domains] + letsencrypt [SUBCOMMAND] [options] [-d domain] [-d domain] ... The Let's Encrypt agent can obtain and install HTTPS/TLS/SSL certificates. By default, it will attempt to use a webserver both for obtaining and installing @@ -59,7 +59,7 @@ the cert. """ # altogether USAGE = SHORT_USAGE + """Major SUBCOMMANDS are: - (default) everything Obtain & install a cert in your current webserver + (default) run Obtain & install a cert in your current webserver auth Authenticate & obtain cert, but do not install it install Install a previously obtained cert in a server revoke Revoke a previously obtained certificate @@ -70,7 +70,7 @@ Choice of server for authentication/installation: --apache Use the Apache plugin for authentication & installation --nginx Use the Nginx plugin for authentication & installation - --standalone Run a standalone HTTPS server (for authentication only) + --standalone Run a standalone webserver for authentication OR: --authenticator standalone --installer nginx @@ -91,8 +91,8 @@ def _find_domains(args, installer): domains = args.domains if not domains: - raise errors.Error("Please specify --domains, or --installer that " - "will help in domain names autodiscovery") + raise Error("Please specify --domains, or --installer that " + "will help in domain names autodiscovery") return domains @@ -144,9 +144,9 @@ def _determine_account(args, config): try: acc, acme = client.register( config, account_storage, tos_cb=_tos_cb) - except errors.Error as error: + except Error as error: logger.debug(error, exc_info=True) - raise errors.Error( + raise Error( "Unable to register an account with ACME server") args.account = acc.id @@ -180,7 +180,7 @@ def _find_duplicative_certs(config, domains): try: full_path = os.path.join(configs_dir, renewal_file) candidate_lineage = storage.RenewableCert(full_path, cli_config) - except (errors.CertStorageError, IOError): + except (CertStorageError, IOError): logger.warning("Renewal configuration file %s is broken. " "Skipping.", full_path) continue @@ -252,7 +252,7 @@ def _treat_as_renewal(config, domains): br=os.linesep ), reporter_util.HIGH_PRIORITY) - raise errors.Error( + raise Error( "User did not use proper CLI and would like " "to reinvoke the client.") @@ -262,12 +262,31 @@ def _treat_as_renewal(config, domains): return None -def _report_new_cert(cert_path): - """Reports the creation of a new certificate to the user.""" +def _report_new_cert(cert_path, fullchain_path): + """Reports the creation of a new certificate to the user. + + :param str cert_path: path to cert + :param str fullchain_path: path to full chain + + """ + expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) - reporter_util.add_message("Congratulations! Your certificate has been " - "saved at {0}.".format(cert_path), - reporter_util.MEDIUM_PRIORITY) + if fullchain_path: + # Print the path to fullchain.pem because that's what modern webservers + # (Nginx and Apache2.4) will want. + and_chain = "and chain have" + path = fullchain_path + else: + # Unless we're in .csr mode and there really isn't one + and_chain = "has " + path = cert_path + # XXX Perhaps one day we could detect the presence of known old webservers + # and say something more informative here. + msg = ("Congratulations! Your certificate {0} been saved at {1}." + " Your cert will expire on {2}. To obtain a new version of the " + "certificate in the future, simply run Let's Encrypt again." + .format(and_chain, path, expiry)) + reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY) def _auth_from_domains(le_client, config, domains, plugins): @@ -293,43 +312,119 @@ def _auth_from_domains(le_client, config, domains, plugins): # TREAT AS NEW REQUEST lineage = le_client.obtain_and_enroll_certificate(domains, plugins) if not lineage: - raise errors.Error("Certificate could not be obtained") + raise Error("Certificate could not be obtained") - _report_new_cert(lineage.cert) - reporter_util = zope.component.getUtility(interfaces.IReporter) - reporter_util.add_message( - "Your certificate will expire on {0}. To obtain a new version of the " - "certificate in the future, simply run this client again.".format( - lineage.notafter().date()), - reporter_util.MEDIUM_PRIORITY) + _report_new_cert(lineage.cert, lineage.fullchain) return lineage +def set_configurator(previously, now): + """ + Setting configurators multiple ways is okay, as long as they all agree + :param str previously: previously identified request for the installer/authenticator + :param str requested: the request currently being processed + """ + if now is None: + # we're not actually setting anything + return previously + if previously: + if previously != now: + msg = "Too many flags setting configurators/installers/authenticators {0} -> {1}" + raise PluginSelectionError(msg.format(repr(previously), repr(now))) + return now + + +def diagnose_configurator_problem(cfg_type, requested, plugins): + """ + Raise the most helpful error message about a plugin being unavailable + + :param str cfg_type: either "installer" or "authenticator" + :param str requested: the plugin that was requested + :param PluginRegistry plugins: available plugins + + :raises error.PluginSelectionError: if there was a problem + """ + + if requested: + if requested not in plugins: + msg = "The requested {0} plugin does not appear to be installed".format(requested) + else: + msg = ("The {0} plugin is not working; there may be problems with " + "your existing configuration").format(requested) + elif cfg_type == "installer": + if os.path.exists("/etc/debian_version"): + # Debian... installers are at least possible + msg = ('No installers seem to be present and working on your system; ' + 'fix that or try running letsencrypt with the "auth" command') + else: + # XXX update this logic as we make progress on #788 and nginx support + msg = ('No installers are available on your OS yet; try running ' + '"letsencrypt-auto auth" to get a cert you can install manually') + else: + msg = "{0} could not be determined or is not installed".format(cfg_type) + raise PluginSelectionError(msg) + + +def choose_configurator_plugins(args, config, plugins, verb): + """ + Figure out which configurator we're going to use + + :raises error.PluginSelectionError if there was a problem + """ + + # Which plugins do we need? + need_inst = need_auth = (verb == "run") + if verb == "auth": + need_auth = True + if verb == "install": + need_inst = True + if args.authenticator: + logger.warn("Specifying an authenticator doesn't make sense in install mode") + + # Which plugins did the user request? + req_inst = req_auth = args.configurator + req_inst = set_configurator(req_inst, args.installer) + req_auth = set_configurator(req_auth, args.authenticator) + if args.nginx: + req_inst = set_configurator(req_inst, "nginx") + req_auth = set_configurator(req_auth, "nginx") + if args.apache: + req_inst = set_configurator(req_inst, "apache") + req_auth = set_configurator(req_auth, "apache") + if args.standalone: + req_auth = set_configurator(req_auth, "standalone") + logger.debug("Requested authenticator %s and installer %s", req_auth, req_inst) + + # Try to meet the user's request and/or ask them to pick plugins + authenticator = installer = None + if verb == "run" and req_auth == req_inst: + # Unless the user has explicitly asked for different auth/install, + # only consider offering a single choice + authenticator = installer = display_ops.pick_configurator(config, req_inst, plugins) + else: + if need_inst or req_inst: + installer = display_ops.pick_installer(config, req_inst, plugins) + if need_auth: + authenticator = display_ops.pick_authenticator(config, req_auth, plugins) + logger.debug("Selected authenticator %s and installer %s", authenticator, installer) + + if need_inst and not installer: + diagnose_configurator_problem("installer", req_inst, plugins) + if need_auth and not authenticator: + diagnose_configurator_problem("authenticator", req_auth, plugins) + + return installer, authenticator + + # TODO: Make run as close to auth + install as possible # Possible difficulties: args.csr was hacked into auth def run(args, config, plugins): # pylint: disable=too-many-branches,too-many-locals """Obtain a certificate and install.""" - # Begin authenticator and installer setup - if args.configurator is not None and (args.installer is not None or - args.authenticator is not None): - return ("Either --configurator or --authenticator/--installer" - "pair, but not both, is allowed") - - if args.authenticator is not None or args.installer is not None: - installer = display_ops.pick_installer( - config, args.installer, plugins) - authenticator = display_ops.pick_authenticator( - config, args.authenticator, plugins) - else: - # TODO: this assumes that user doesn't want to pick authenticator - # and installer separately... - authenticator = installer = display_ops.pick_configurator( - config, args.configurator, plugins) - - if installer is None or authenticator is None: - return "Configurator could not be determined" - # End authenticator and installer setup + try: + installer, authenticator = choose_configurator_plugins(args, config, plugins, "run") + except PluginSelectionError, e: + return e.message domains = _find_domains(args, installer) @@ -357,15 +452,11 @@ def auth(args, config, plugins): # supplied, check if CSR matches given domains? return "--domains and --csr are mutually exclusive" - authenticator = display_ops.pick_authenticator( - config, args.authenticator, plugins) - if authenticator is None: - return "Authenticator could not be determined" - - if args.installer is not None: - installer = display_ops.pick_installer(config, args.installer, plugins) - else: - installer = None + try: + # installers are used in auth mode to determine domain names + installer, authenticator = choose_configurator_plugins(args, config, plugins, "auth") + except PluginSelectionError, e: + return e.message # TODO: Handle errors from _init_le_client? le_client = _init_le_client(args, config, authenticator, installer) @@ -374,9 +465,9 @@ def auth(args, config, plugins): if args.csr is not None: certr, chain = le_client.obtain_certificate_from_csr(le_util.CSR( file=args.csr[0], data=args.csr[1], form="der")) - le_client.save_certificate( - certr, chain, args.cert_path, args.chain_path) - _report_new_cert(args.cert_path) + cert_path, _, cert_fullchain = le_client.save_certificate( + certr, chain, args.cert_path, args.chain_path, args.fullchain_path) + _report_new_cert(cert_path, cert_fullchain) else: domains = _find_domains(args, installer) _auth_from_domains(le_client, config, domains, plugins) @@ -385,9 +476,12 @@ def auth(args, config, plugins): def install(args, config, plugins): """Install a previously obtained cert in a server.""" # XXX: Update for renewer/RenewableCert - installer = display_ops.pick_installer(config, args.installer, plugins) - if installer is None: - return "Installer could not be determined" + + try: + installer, _ = choose_configurator_plugins(args, config, plugins, "auth") + except PluginSelectionError, e: + return e.message + domains = _find_domains(args, installer) le_client = _init_le_client( args, config, authenticator=None, installer=installer) @@ -679,8 +773,8 @@ def create_parser(plugins, args): help="Select renewal by default when domains are a superset of a " "a previously attained cert") helpful.add( - "automation", "--agree-eula", dest="eula", action="store_true", - help="Agree to the Let's Encrypt Developer Preview EULA") + "automation", "--agree-dev-preview", action="store_true", + help="Agree to the Let's Encrypt Developer Preview Disclaimer") helpful.add( "automation", "--agree-tos", dest="tos", action="store_true", help="Agree to the Let's Encrypt Subscriber Agreement") @@ -770,7 +864,6 @@ def _create_subparsers(helpful): "--checkpoints", type=int, metavar="N", default=flag_default("rollback_checkpoints"), help="Revert configuration N number of checkpoints.") - helpful.add("plugins", "--init", action="store_true", help="Initialize plugins.") helpful.add("plugins", @@ -830,11 +923,17 @@ def _plugins_parsing(helpful, plugins): helpful.add( "plugins", "-a", "--authenticator", help="Authenticator plugin name.") helpful.add( - "plugins", "-i", "--installer", help="Installer plugin name.") + "plugins", "-i", "--installer", help="Installer plugin name (also used to find domains).") helpful.add( "plugins", "--configurator", help="Name of the plugin that is " "both an authenticator and an installer. Should not be used " "together with --authenticator or --installer.") + helpful.add("plugins", "--apache", action="store_true", + help="Obtain and install certs using Apache") + helpful.add("plugins", "--nginx", action="store_true", + help="Obtain and install certs using Nginx") + helpful.add("plugins", "--standalone", action="store_true", + help='Obtain certs using a "standalone" webserver.') # things should not be reorder past/pre this comment: # plugins_group should be displayed in --help before plugin @@ -917,7 +1016,7 @@ def _handle_exception(exc_type, exc_value, trace, args): sys.exit("".join( traceback.format_exception(exc_type, exc_value, trace))) - if issubclass(exc_type, errors.Error): + if issubclass(exc_type, Error): sys.exit(exc_value) else: # Tell the user a bit about what happened, without overwhelming @@ -958,6 +1057,7 @@ def main(cli_args=sys.argv[1:]): args.logs_dir, 0o700, os.geteuid(), "--strict-permissions" in cli_args) setup_logging(args, _cli_log_handler, logfile='letsencrypt.log') + logger.debug("letsencrypt version: %s", letsencrypt.__version__) # do not log `args`, as it contains sensitive data (e.g. revoke --key)! logger.debug("Arguments: %r", cli_args) logger.debug("Discovered plugins: %r", plugins) @@ -976,12 +1076,12 @@ def main(cli_args=sys.argv[1:]): zope.component.provideUtility(report) atexit.register(report.atexit_print_messages) - # TODO: remove developer EULA prompt for the launch - if not config.eula: - eula = pkg_resources.resource_string("letsencrypt", "EULA") + # TODO: remove developer preview prompt for the launch + if not config.agree_dev_preview: + disclaimer = pkg_resources.resource_string("letsencrypt", "DISCLAIMER") if not zope.component.getUtility(interfaces.IDisplay).yesno( - eula, "Agree", "Cancel"): - raise errors.Error("Must agree to TOS") + disclaimer, "Agree", "Cancel"): + raise Error("Must agree to TOS") if not os.geteuid() == 0: logger.warning( @@ -998,4 +1098,7 @@ def main(cli_args=sys.argv[1:]): if __name__ == "__main__": - sys.exit(main()) # pragma: no cover + err_string = main() + if err_string: + logger.warn("Exiting with message %s", err_string) + sys.exit(err_string) # pragma: no cover diff --git a/letsencrypt/client.py b/letsencrypt/client.py index 3e32ab015..3a6d90472 100644 --- a/letsencrypt/client.py +++ b/letsencrypt/client.py @@ -258,8 +258,8 @@ class Client(object): params, config, cli_config) return lineage - def save_certificate(self, certr, chain_cert, cert_path, chain_path): - # pylint: disable=no-self-use + def save_certificate(self, certr, chain_cert, + cert_path, chain_path, fullchain_path): """Saves the certificate received from the ACME server. :param certr: ACME "certificate" resource. @@ -268,24 +268,23 @@ class Client(object): :param list chain_cert: :param str cert_path: Candidate path to a certificate. :param str chain_path: Candidate path to a certificate chain. + :param str fullchain_path: Candidate path to a full cert chain. - :returns: cert_path, chain_path (absolute paths to the actual files) + :returns: cert_path, chain_path, and fullchain_path as absolute + paths to the actual files :rtype: `tuple` of `str` :raises IOError: If unable to find room to write the cert files """ - for path in cert_path, chain_path: + for path in cert_path, chain_path, fullchain_path: le_util.make_or_verify_dir( os.path.dirname(path), 0o755, os.geteuid(), self.config.strict_permissions) - # try finally close - cert_chain_abspath = None - cert_file, act_cert_path = le_util.unique_file(cert_path, 0o644) - # TODO: Except cert_pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, certr.body) + cert_file, act_cert_path = le_util.unique_file(cert_path, 0o644) try: cert_file.write(cert_pem) finally: @@ -293,22 +292,15 @@ class Client(object): logger.info("Server issued certificate; certificate written to %s", act_cert_path) + cert_chain_abspath = None + fullchain_abspath = None if chain_cert: - chain_file, act_chain_path = le_util.unique_file( - chain_path, 0o644) - # TODO: Except chain_pem = crypto_util.dump_pyopenssl_chain(chain_cert) - try: - chain_file.write(chain_pem) - finally: - chain_file.close() + cert_chain_abspath = _save_chain(chain_pem, chain_path) + fullchain_abspath = _save_chain(cert_pem + chain_pem, + fullchain_path) - logger.info("Cert chain written to %s", act_chain_path) - - # This expects a valid chain file - cert_chain_abspath = os.path.abspath(act_chain_path) - - return os.path.abspath(act_cert_path), cert_chain_abspath + return os.path.abspath(act_cert_path), cert_chain_abspath, fullchain_abspath def deploy_certificate(self, domains, privkey_path, cert_path, chain_path, fullchain_path): @@ -329,8 +321,6 @@ class Client(object): with error_handler.ErrorHandler(self.installer.recovery_routine): for dom in domains: - # TODO: Provide a fullchain reference for installers like - # nginx that want it self.installer.deploy_cert( domain=dom, cert_path=os.path.abspath(cert_path), key_path=os.path.abspath(privkey_path), @@ -467,3 +457,25 @@ def view_config_changes(config): rev = reverter.Reverter(config) rev.recovery_routine() rev.view_config_changes() + + +def _save_chain(chain_pem, chain_path): + """Saves chain_pem at a unique path based on chain_path. + + :param str chain_pem: certificate chain in PEM format + :param str chain_path: candidate path for the cert chain + + :returns: absolute path to saved cert chain + :rtype: str + + """ + chain_file, act_chain_path = le_util.unique_file(chain_path, 0o644) + try: + chain_file.write(chain_pem) + finally: + chain_file.close() + + logger.info("Cert chain written to %s", act_chain_path) + + # This expects a valid chain file + return os.path.abspath(act_chain_path) diff --git a/letsencrypt/crypto_util.py b/letsencrypt/crypto_util.py index 61aa8b0db..f897ec852 100644 --- a/letsencrypt/crypto_util.py +++ b/letsencrypt/crypto_util.py @@ -8,6 +8,7 @@ import logging import os import OpenSSL +import pyrfc3339 import zope.component from acme import crypto_util as acme_crypto_util @@ -276,3 +277,48 @@ def dump_pyopenssl_chain(chain, filetype=OpenSSL.crypto.FILETYPE_PEM): # assumes that OpenSSL.crypto.dump_certificate includes ending # newline character return "".join(_dump_cert(cert) for cert in chain) + + +def notBefore(cert_path): + """When does the cert at cert_path start being valid? + + :param str cert_path: path to a cert in PEM format + + :returns: the notBefore value from the cert at cert_path + :rtype: :class:`datetime.datetime` + + """ + return _notAfterBefore(cert_path, OpenSSL.crypto.X509.get_notBefore) + + +def notAfter(cert_path): + """When does the cert at cert_path stop being valid? + + :param str cert_path: path to a cert in PEM format + + :returns: the notAfter value from the cert at cert_path + :rtype: :class:`datetime.datetime` + + """ + return _notAfterBefore(cert_path, OpenSSL.crypto.X509.get_notAfter) + + +def _notAfterBefore(cert_path, method): + """Internal helper function for finding notbefore/notafter. + + :param str cert_path: path to a cert in PEM format + :param function method: one of ``OpenSSL.crypto.X509.get_notBefore`` + or ``OpenSSL.crypto.X509.get_notAfter`` + + :returns: the notBefore or notAfter value from the cert at cert_path + :rtype: :class:`datetime.datetime` + + """ + with open(cert_path) as f: + x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + f.read()) + timestamp = method(x509) + reformatted_timestamp = [timestamp[0:4], "-", timestamp[4:6], "-", + timestamp[6:8], "T", timestamp[8:10], ":", + timestamp[10:12], ":", timestamp[12:]] + return pyrfc3339.parse("".join(reformatted_timestamp)) diff --git a/letsencrypt/errors.py b/letsencrypt/errors.py index 98c24bf50..3bfed4d23 100644 --- a/letsencrypt/errors.py +++ b/letsencrypt/errors.py @@ -66,6 +66,10 @@ class PluginError(Error): """Let's Encrypt Plugin error.""" +class PluginSelectionError(Error): + """A problem with plugin/configurator selection or setup""" + + class NoInstallationError(PluginError): """Let's Encrypt No Installation error.""" diff --git a/letsencrypt/plugins/manual.py b/letsencrypt/plugins/manual.py index 99463c362..f7717064b 100644 --- a/letsencrypt/plugins/manual.py +++ b/letsencrypt/plugins/manual.py @@ -130,10 +130,7 @@ binary for temporary key/certificate generation.""".replace("\n", "") if self.conf("test-mode"): logger.debug("Test mode. Executing the manual command: %s", command) # sh shipped with OS X does't support echo -n - if sys.platform == "darwin": - executable = "/bin/bash" - else: - executable = None + executable = "/bin/bash" if sys.platform == "darwin" else None try: self._httpd = subprocess.Popen( command, diff --git a/letsencrypt/plugins/standalone.py b/letsencrypt/plugins/standalone.py index 3ad823e9c..d4dddc7f6 100644 --- a/letsencrypt/plugins/standalone.py +++ b/letsencrypt/plugins/standalone.py @@ -72,13 +72,12 @@ class ServerManager(object): except socket.error as error: raise errors.StandaloneBindError(error, port) - # if port == 0, then random free port on OS is taken - # pylint: disable=no-member - host, real_port = server.socket.getsockname() thread = threading.Thread(target=server.serve_forever2) - logger.debug("Starting server at %s:%d", host, real_port) thread.start() + # if port == 0, then random free port on OS is taken + # pylint: disable=no-member + real_port = server.socket.getsockname()[1] self._instances[real_port] = self._Instance(server, thread) return server @@ -89,6 +88,8 @@ class ServerManager(object): """ instance = self._instances[port] + logger.debug("Stopping server at %s:%d...", + *instance.server.socket.getsockname()[:2]) instance.server.shutdown2() instance.thread.join() del self._instances[port] diff --git a/letsencrypt/plugins/util_test.py b/letsencrypt/plugins/util_test.py index 14cbcf7a8..1591976b0 100644 --- a/letsencrypt/plugins/util_test.py +++ b/letsencrypt/plugins/util_test.py @@ -98,6 +98,10 @@ class AlreadyListeningTest(unittest.TestCase): self.assertEqual(mock_get_utility.call_count, 1) mock_process.assert_called_once_with(4420) + @mock.patch("letsencrypt.plugins.util.psutil.net_connections") + def test_access_denied_exception(self, mock_net): + mock_net.side_effect = psutil.AccessDenied("") + self.assertFalse(self._call(12345)) if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/letsencrypt/plugins/webroot.py b/letsencrypt/plugins/webroot.py index ed8991bc5..f11325f57 100644 --- a/letsencrypt/plugins/webroot.py +++ b/letsencrypt/plugins/webroot.py @@ -72,8 +72,7 @@ to serve all files under specified web root ({0}).""" return os.path.join(self.full_root, achall.chall.encode("token")) def _perform_single(self, achall): - response, validation = achall.gen_response_and_validation( - tls=(not self.config.no_simple_http_tls)) + response, validation = achall.gen_response_and_validation(tls=False) path = self._path_for_achall(achall) logger.debug("Attempting to save validation to %s", path) with open(path, "w") as validation_file: diff --git a/letsencrypt/renewer.py b/letsencrypt/renewer.py index f7eef4125..c0014f4b2 100644 --- a/letsencrypt/renewer.py +++ b/letsencrypt/renewer.py @@ -94,7 +94,7 @@ def renew(cert, old_version): sans = crypto_util.get_sans_from_cert(f.read()) new_certr, new_chain, new_key, _ = le_client.obtain_certificate(sans) if new_chain: - # XXX: Assumes that there was no key change. We need logic + # XXX: Assumes that there was a key change. We need logic # for figuring out whether there was or not. Probably # best is to have obtain_certificate return None for # new_key if the old key is to be used (since save_successor diff --git a/letsencrypt/storage.py b/letsencrypt/storage.py index 110b20dd2..ece3df4b7 100644 --- a/letsencrypt/storage.py +++ b/letsencrypt/storage.py @@ -5,10 +5,8 @@ import re import time import configobj -import OpenSSL import parsedatetime import pytz -import pyrfc3339 from letsencrypt import constants from letsencrypt import crypto_util @@ -420,47 +418,6 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes for _, link in previous_links: os.unlink(link) - def _notafterbefore(self, method, version): - """Internal helper function for finding notbefore/notafter.""" - if version is None: - target = self.current_target("cert") - else: - target = self.version("cert", version) - pem = open(target).read() - x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, - pem) - i = method(x509) - return pyrfc3339.parse(i[0:4] + "-" + i[4:6] + "-" + i[6:8] + "T" + - i[8:10] + ":" + i[10:12] + ":" + i[12:]) - - def notbefore(self, version=None): - """When does the specified cert version start being valid? - - (If no version is specified, use the current version.) - - :param int version: the desired version number - - :returns: the notBefore value from the specified cert version in - this lineage - :rtype: :class:`datetime.datetime` - - """ - return self._notafterbefore(lambda x509: x509.get_notBefore(), version) - - def notafter(self, version=None): - """When does the specified cert version stop being valid? - - (If no version is specified, use the current version.) - - :param int version: the desired version number - - :returns: the notAfter value from the specified cert version in - this lineage - :rtype: :class:`datetime.datetime` - - """ - return self._notafterbefore(lambda x509: x509.get_notAfter(), version) - def names(self, version=None): """What are the subject names of this certificate? @@ -509,7 +466,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes interval = self.configuration.get("deploy_before_expiry", "5 days") autodeploy_interval = parse_time_interval(interval) - expiry = self.notafter() + expiry = crypto_util.notAfter(self.current_target("cert")) now = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) remaining = expiry - now if remaining < autodeploy_interval: @@ -576,7 +533,8 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes # Renewals on the basis of expiry time interval = self.configuration.get("renew_before_expiry", "10 days") autorenew_interval = parse_time_interval(interval) - expiry = self.notafter(self.latest_common_version()) + expiry = crypto_util.notAfter(self.version( + "cert", self.latest_common_version())) now = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) remaining = expiry - now if remaining < autorenew_interval: diff --git a/letsencrypt/tests/account_test.py b/letsencrypt/tests/account_test.py index 4e2fdb122..9452a74f3 100644 --- a/letsencrypt/tests/account_test.py +++ b/letsencrypt/tests/account_test.py @@ -45,16 +45,16 @@ class AccountTest(unittest.TestCase): def test_id(self): self.assertEqual( - self.acc.id, "2ba35a3bdf380ed76a5ac9e740568395") + self.acc.id, "bca5889f66457d5b62fbba7b25f9ab6f") def test_slug(self): self.assertEqual( - self.acc.slug, "test.letsencrypt.org@2015-07-04T14:04:10Z (2ba3)") + self.acc.slug, "test.letsencrypt.org@2015-07-04T14:04:10Z (bca5)") def test_repr(self): self.assertEqual( repr(self.acc), - "") + "") class ReportNewAccountTest(unittest.TestCase): diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 418ee124e..03f291723 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -13,6 +13,8 @@ from letsencrypt import account from letsencrypt import configuration from letsencrypt import errors +from letsencrypt.plugins import disco + from letsencrypt.tests import renewer_test from letsencrypt.tests import test_util @@ -36,7 +38,7 @@ class CLITest(unittest.TestCase): from letsencrypt import cli args = ['--text', '--config-dir', self.config_dir, '--work-dir', self.work_dir, '--logs-dir', self.logs_dir, - '--agree-eula'] + args + '--agree-dev-preview'] + args with mock.patch('letsencrypt.cli.sys.stdout') as stdout: with mock.patch('letsencrypt.cli.sys.stderr') as stderr: with mock.patch('letsencrypt.cli.client') as client: @@ -51,7 +53,7 @@ class CLITest(unittest.TestCase): from letsencrypt import cli args = ['--text', '--config-dir', self.config_dir, '--work-dir', self.work_dir, '--logs-dir', self.logs_dir, - '--agree-eula'] + args + '--agree-dev-preview'] + args with mock.patch('letsencrypt.cli.sys.stderr') as stderr: with mock.patch('letsencrypt.cli.client') as client: ret = cli.main(args) @@ -75,7 +77,6 @@ class CLITest(unittest.TestCase): output.truncate(0) self.assertRaises(SystemExit, self._call_stdout, ['-h', 'nginx']) out = output.getvalue() - from letsencrypt.plugins import disco if "nginx" in disco.PluginsRegistry.find_all(): # may be false while building distributions without plugins self.assertTrue("--nginx-ctl" in out) @@ -93,6 +94,28 @@ class CLITest(unittest.TestCase): from letsencrypt import cli self.assertTrue(cli.USAGE in out) + def test_configurator_selection(self): + real_plugins = disco.PluginsRegistry.find_all() + args = ['--agree-dev-preview', '--apache', + '--authenticator', 'standalone'] + + # This needed two calls to find_all(), which we're avoiding for now + # because of possible side effects: + # https://github.com/letsencrypt/letsencrypt/commit/51ed2b681f87b1eb29088dd48718a54f401e4855 + #with mock.patch('letsencrypt.cli.plugins_testable') as plugins: + # plugins.return_value = {"apache": True, "nginx": True} + # ret, _, _, _ = self._call(args) + # self.assertTrue("Too many flags setting" in ret) + + args = ["install", "--nginx", "--cert-path", "/tmp/blah", "--key-path", "/tmp/blah", + "--nginx-server-root", "/nonexistent/thing", "-d", + "example.com", "--debug"] + if "nginx" in real_plugins: + # Sending nginx a non-existent conf dir will simulate misconfiguration + # (we can only do that if letsencrypt-nginx is actually present) + ret, _, _, _ = self._call(args) + self.assertTrue("The nginx plugin is not working" in ret) + def test_rollback(self): _, _, _, client = self._call(['rollback']) self.assertEqual(1, client.rollback.call_count) @@ -117,20 +140,25 @@ class CLITest(unittest.TestCase): self.assertEqual(ret, '--domains and --csr are mutually exclusive') ret, _, _, _ = self._call(['-a', 'bad_auth', 'auth']) - self.assertEqual(ret, 'Authenticator could not be determined') + self.assertEqual(ret, 'The requested bad_auth plugin does not appear to be installed') + @mock.patch('letsencrypt.crypto_util.notAfter') @mock.patch('letsencrypt.cli.zope.component.getUtility') - def test_auth_new_request_success(self, mock_get_utility): + def test_auth_new_request_success(self, mock_get_utility, mock_notAfter): cert_path = '/etc/letsencrypt/live/foo.bar' - mock_lineage = mock.MagicMock(cert=cert_path) + date = '1970-01-01' + mock_notAfter().date.return_value = date + + mock_lineage = mock.MagicMock(cert=cert_path, fullchain=cert_path) mock_client = mock.MagicMock() mock_client.obtain_and_enroll_certificate.return_value = mock_lineage self._auth_new_request_common(mock_client) self.assertEqual( mock_client.obtain_and_enroll_certificate.call_count, 1) - msg = mock_get_utility().add_message.call_args_list[0][0][0] - self.assertTrue(cert_path in msg) - self.assertEqual(mock_get_utility().add_message.call_count, 2) + self.assertTrue( + cert_path in mock_get_utility().add_message.call_args[0][0]) + self.assertTrue( + date in mock_get_utility().add_message.call_args[0][0]) def test_auth_new_request_failure(self): mock_client = mock.MagicMock() @@ -149,8 +177,10 @@ class CLITest(unittest.TestCase): @mock.patch('letsencrypt.cli._treat_as_renewal') @mock.patch('letsencrypt.cli._init_le_client') def test_auth_renewal(self, mock_init, mock_renewal, mock_get_utility): - cert_path = '/etc/letsencrypt/live/foo.bar' - mock_lineage = mock.MagicMock(cert=cert_path) + cert_path = '/etc/letsencrypt/live/foo.bar/cert.pem' + chain_path = '/etc/letsencrypt/live/foo.bar/fullchain.pem' + + mock_lineage = mock.MagicMock(cert=cert_path, fullchain=chain_path) mock_cert = mock.MagicMock(body='body') mock_key = mock.MagicMock(pem='pem_key') mock_renewal.return_value = mock_lineage @@ -165,28 +195,37 @@ class CLITest(unittest.TestCase): self.assertEqual(mock_lineage.save_successor.call_count, 1) mock_lineage.update_all_links_to.assert_called_once_with( mock_lineage.latest_common_version()) - msg = mock_get_utility().add_message.call_args_list[0][0][0] - self.assertTrue(cert_path in msg) - self.assertEqual(mock_get_utility().add_message.call_count, 2) + self.assertTrue( + chain_path in mock_get_utility().add_message.call_args[0][0]) + @mock.patch('letsencrypt.crypto_util.notAfter') @mock.patch('letsencrypt.cli.display_ops.pick_installer') @mock.patch('letsencrypt.cli.zope.component.getUtility') @mock.patch('letsencrypt.cli._init_le_client') - def test_auth_csr(self, mock_init, mock_get_utility, mock_pick_installer): - cert_path = '/etc/letsencrypt/live/foo.bar' + def test_auth_csr(self, mock_init, mock_get_utility, + mock_pick_installer, mock_notAfter): + cert_path = '/etc/letsencrypt/live/blahcert.pem' + date = '1970-01-01' + mock_notAfter().date.return_value = date + mock_client = mock.MagicMock() mock_client.obtain_certificate_from_csr.return_value = ('certr', 'chain') + mock_client.save_certificate.return_value = cert_path, None, None mock_init.return_value = mock_client + installer = 'installer' self._call( ['-a', 'standalone', '-i', installer, 'auth', '--csr', CSR, - '--cert-path', cert_path, '--chain-path', '/']) + '--cert-path', cert_path, '--fullchain-path', '/', + '--chain-path', '/']) self.assertEqual(mock_pick_installer.call_args[0][1], installer) mock_client.save_certificate.assert_called_once_with( - 'certr', 'chain', cert_path, '/') + 'certr', 'chain', cert_path, '/', '/') self.assertTrue( cert_path in mock_get_utility().add_message.call_args[0][0]) + self.assertTrue( + date in mock_get_utility().add_message.call_args[0][0]) @mock.patch('letsencrypt.cli.sys') def test_handle_exception(self, mock_sys): diff --git a/letsencrypt/tests/client_test.py b/letsencrypt/tests/client_test.py index 3f7b84a64..2efe11108 100644 --- a/letsencrypt/tests/client_test.py +++ b/letsencrypt/tests/client_test.py @@ -120,18 +120,22 @@ class ClientTest(unittest.TestCase): os.chmod(tmp_path, 0o755) # TODO: really?? certr = mock.MagicMock(body=test_util.load_cert(certs[0])) - cert1 = test_util.load_cert(certs[1]) - cert2 = test_util.load_cert(certs[2]) + chain_cert = [test_util.load_cert(certs[1]), + test_util.load_cert(certs[2])] candidate_cert_path = os.path.join(tmp_path, "certs", "cert.pem") candidate_chain_path = os.path.join(tmp_path, "chains", "chain.pem") + candidate_fullchain_path = os.path.join(tmp_path, "chains", "fullchain.pem") - cert_path, chain_path = self.client.save_certificate( - certr, [cert1, cert2], candidate_cert_path, candidate_chain_path) + cert_path, chain_path, fullchain_path = self.client.save_certificate( + certr, chain_cert, candidate_cert_path, candidate_chain_path, + candidate_fullchain_path) self.assertEqual(os.path.dirname(cert_path), os.path.dirname(candidate_cert_path)) self.assertEqual(os.path.dirname(chain_path), os.path.dirname(candidate_chain_path)) + self.assertEqual(os.path.dirname(fullchain_path), + os.path.dirname(candidate_fullchain_path)) with open(cert_path, "r") as cert_file: cert_contents = cert_file.read() diff --git a/letsencrypt/tests/crypto_util_test.py b/letsencrypt/tests/crypto_util_test.py index 2e04c748a..f0b8c0e4d 100644 --- a/letsencrypt/tests/crypto_util_test.py +++ b/letsencrypt/tests/crypto_util_test.py @@ -15,6 +15,7 @@ from letsencrypt.tests import test_util RSA256_KEY = test_util.load_vector('rsa256_key.pem') RSA512_KEY = test_util.load_vector('rsa512_key.pem') +CERT_PATH = test_util.vector_path('cert.pem') CERT = test_util.load_vector('cert.pem') SAN_CERT = test_util.load_vector('cert-san.pem') @@ -232,5 +233,23 @@ class CertLoaderTest(unittest.TestCase): pyopenssl_load_certificate(bad_cert_data) +class NotBeforeTest(unittest.TestCase): + """Tests for letsencrypt.crypto_util.notBefore""" + + def test_notBefore(self): + from letsencrypt.crypto_util import notBefore + self.assertEqual(notBefore(CERT_PATH).isoformat(), + '2014-12-11T22:34:45+00:00') + + +class NotAfterTest(unittest.TestCase): + """Tests for letsencrypt.crypto_util.notAfter""" + + def test_notAfter(self): + from letsencrypt.crypto_util import notAfter + self.assertEqual(notAfter(CERT_PATH).isoformat(), + '2014-12-18T22:34:45+00:00') + + if __name__ == '__main__': unittest.main() # pragma: no cover diff --git a/letsencrypt/tests/renewer_test.py b/letsencrypt/tests/renewer_test.py index b28d40e2f..28ae74b34 100644 --- a/letsencrypt/tests/renewer_test.py +++ b/letsencrypt/tests/renewer_test.py @@ -7,7 +7,6 @@ import unittest import configobj import mock -import pytz from letsencrypt import configuration from letsencrypt import errors @@ -48,7 +47,6 @@ class BaseRenewableCertTest(unittest.TestCase): config_dir=self.tempdir, work_dir=self.tempdir, logs_dir=self.tempdir, - no_simple_http_tls=False, ) ) @@ -379,26 +377,6 @@ class RenewableCertTests(BaseRenewableCertTest): self.assertEqual(self.test_rc.names(12), ["example.com", "www.example.com"]) - def _test_notafterbefore(self, function, timestamp): - test_cert = test_util.load_vector("cert.pem") - os.symlink(os.path.join("..", "..", "archive", "example.org", - "cert12.pem"), self.test_rc.cert) - with open(self.test_rc.cert, "w") as f: - f.write(test_cert) - desired_time = datetime.datetime.utcfromtimestamp(timestamp) - desired_time = desired_time.replace(tzinfo=pytz.UTC) - for result in (function(), function(12)): - self.assertEqual(result, desired_time) - self.assertEqual(result.utcoffset(), datetime.timedelta(0)) - - def test_notbefore(self): - self._test_notafterbefore(self.test_rc.notbefore, 1418337285) - # 2014-12-11 22:34:45+00:00 = Unix time 1418337285 - - def test_notafter(self): - self._test_notafterbefore(self.test_rc.notafter, 1418942085) - # 2014-12-18 22:34:45+00:00 = Unix time 1418942085 - @mock.patch("letsencrypt.storage.datetime") def test_time_interval_judgments(self, mock_datetime): """Test should_autodeploy() and should_autorenew() on the basis diff --git a/letshelp-letsencrypt/MANIFEST.in b/letshelp-letsencrypt/MANIFEST.in index 96c1d7ba5..6ea55a950 100644 --- a/letshelp-letsencrypt/MANIFEST.in +++ b/letshelp-letsencrypt/MANIFEST.in @@ -1,3 +1,4 @@ include LICENSE.txt include README.rst +recursive-include docs * recursive-include letshelp_letsencrypt/testdata * diff --git a/letshelp-letsencrypt/docs/.gitignore b/letshelp-letsencrypt/docs/.gitignore new file mode 100644 index 000000000..ba65b13af --- /dev/null +++ b/letshelp-letsencrypt/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/letshelp-letsencrypt/docs/Makefile b/letshelp-letsencrypt/docs/Makefile new file mode 100644 index 000000000..8e742d837 --- /dev/null +++ b/letshelp-letsencrypt/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/letshelp-letsencrypt.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/letshelp-letsencrypt.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/letshelp-letsencrypt" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/letshelp-letsencrypt" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/letshelp-letsencrypt/docs/_static/.gitignore b/letshelp-letsencrypt/docs/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letshelp-letsencrypt/docs/_templates/.gitignore b/letshelp-letsencrypt/docs/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/letshelp-letsencrypt/docs/api.rst b/letshelp-letsencrypt/docs/api.rst new file mode 100644 index 000000000..8668ec5d8 --- /dev/null +++ b/letshelp-letsencrypt/docs/api.rst @@ -0,0 +1,8 @@ +================= +API Documentation +================= + +.. toctree:: + :glob: + + api/** diff --git a/docs/pkgs/letshelp_letsencrypt.rst b/letshelp-letsencrypt/docs/api/index.rst similarity index 100% rename from docs/pkgs/letshelp_letsencrypt.rst rename to letshelp-letsencrypt/docs/api/index.rst diff --git a/letshelp-letsencrypt/docs/conf.py b/letshelp-letsencrypt/docs/conf.py new file mode 100644 index 000000000..abbf3621d --- /dev/null +++ b/letshelp-letsencrypt/docs/conf.py @@ -0,0 +1,311 @@ +# -*- coding: utf-8 -*- +# +# letshelp-letsencrypt documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 18 13:40:19 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + + +here = os.path.abspath(os.path.dirname(__file__)) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', +] + +autodoc_member_order = 'bysource' +autodoc_default_flags = ['show-inheritance', 'private-members'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'letshelp-letsencrypt' +copyright = u'2014-2015, Let\'s Encrypt Project' +author = u'Let\'s Encrypt Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0' +# The full version, including alpha/beta/rc tags. +release = '0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = 'py:obj' + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# on_rtd is whether we are on readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'letshelp-letsencryptdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'letshelp-letsencrypt.tex', u'letshelp-letsencrypt Documentation', + u'Let\'s Encrypt Project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'letshelp-letsencrypt', u'letshelp-letsencrypt Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'letshelp-letsencrypt', u'letshelp-letsencrypt Documentation', + author, 'letshelp-letsencrypt', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +intersphinx_mapping = { + 'python': ('https://docs.python.org/', None), + 'acme': ('https://acme-python.readthedocs.org', None), + 'letsencrypt': ('https://letsencrypt.readthedocs.org', None), +} diff --git a/letshelp-letsencrypt/docs/index.rst b/letshelp-letsencrypt/docs/index.rst new file mode 100644 index 000000000..6b67a2e1f --- /dev/null +++ b/letshelp-letsencrypt/docs/index.rst @@ -0,0 +1,27 @@ +.. letshelp-letsencrypt documentation master file, created by + sphinx-quickstart on Sun Oct 18 13:40:19 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to letshelp-letsencrypt's documentation! +================================================ + +Contents: + +.. toctree:: + :maxdepth: 2 + + +.. toctree:: + :maxdepth: 1 + + api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/letshelp-letsencrypt/docs/make.bat b/letshelp-letsencrypt/docs/make.bat new file mode 100644 index 000000000..006f7825d --- /dev/null +++ b/letshelp-letsencrypt/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\letshelp-letsencrypt.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\letshelp-letsencrypt.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/letshelp-letsencrypt/readthedocs.org.requirements.txt b/letshelp-letsencrypt/readthedocs.org.requirements.txt new file mode 100644 index 000000000..898d2716e --- /dev/null +++ b/letshelp-letsencrypt/readthedocs.org.requirements.txt @@ -0,0 +1,10 @@ +# readthedocs.org gives no way to change the install command to "pip +# install -e .[docs]" (that would in turn install documentation +# dependencies), but it allows to specify a requirements.txt file at +# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259) + +# Although ReadTheDocs certainly doesn't need to install the project +# in --editable mode (-e), just "pip install .[docs]" does not work as +# expected and "pip install -e .[docs]" must be used instead + +-e letshelp-letsencrypt[docs] diff --git a/letshelp-letsencrypt/setup.py b/letshelp-letsencrypt/setup.py index a83fc8843..a63e0aad4 100644 --- a/letshelp-letsencrypt/setup.py +++ b/letshelp-letsencrypt/setup.py @@ -14,6 +14,11 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') +docs_extras = [ + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', +] + setup( name='letshelp-letsencrypt', version=version, @@ -41,6 +46,9 @@ setup( packages=find_packages(), include_package_data=True, install_requires=install_requires, + extras_require={ + 'docs': docs_extras, + }, entry_points={ 'console_scripts': [ 'letshelp-letsencrypt-apache = letshelp_letsencrypt.apache:main', diff --git a/readthedocs.org.requirements.txt b/readthedocs.org.requirements.txt index 3c3a3c576..27cccb0a6 100644 --- a/readthedocs.org.requirements.txt +++ b/readthedocs.org.requirements.txt @@ -7,9 +7,4 @@ # in --editable mode (-e), just "pip install .[docs]" does not work as # expected and "pip install -e .[docs]" must be used instead --e acme -e .[docs] --e letsencrypt-apache --e letsencrypt-nginx --e letsencrypt-compatibility-test --e letshelp-letsencrypt diff --git a/tests/integration/_common.sh b/tests/integration/_common.sh index ab645f6d6..1dffaa4e3 100755 --- a/tests/integration/_common.sh +++ b/tests/integration/_common.sh @@ -20,7 +20,7 @@ letsencrypt_test () { --manual-test-mode \ $store_flags \ --text \ - --agree-eula \ + --agree-dev-preview \ --agree-tos \ --email "" \ --renew-by-default \