├── .bumpversion.cfg ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.rst ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── docs ├── .python-virtualenv ├── Makefile ├── _static │ └── flask-docker.png ├── conf.py ├── index.rst ├── requirements.in └── requirements.txt ├── flask_docker.py ├── setup.cfg ├── setup.py ├── tests ├── conftest.py ├── test_factory.py ├── test_simple.py └── test_tls.py └── tox.ini /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.2.0 3 | files = setup.py flask_docker.py docs/conf.py 4 | commit = True 5 | tag = False 6 | 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | 8 | [*.py] 9 | indent_style = space 10 | indent_size = 4 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | coverage.xml 35 | 36 | # Translations 37 | *.mo 38 | 39 | # Sphinx documentation 40 | docs/_build/ 41 | 42 | # Editor 43 | *.sw[po] 44 | 45 | # Mac OS X 46 | .DS_Store 47 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.4" 5 | - "3.5" 6 | - "3.6" 7 | - "pypy" 8 | install: 9 | - "pip install tox-travis" 10 | script: "tox" 11 | after_success: "coveralls" 12 | branches: 13 | only: 14 | - master 15 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | --------- 3 | 4 | 0.2.0 - 2015-06-08 5 | ~~~~~~~~~~~~~~~~~~ 6 | 7 | * Make ``app`` attribute always be accessible in :class:`flask_docker.Docker`. 8 | * Add ``zip_safe=False`` flag to ``setup.py``. 9 | * Fix some description in the document. 10 | 11 | 0.1.0 - 2015-02-01 12 | ~~~~~~~~~~~~~~~~~~ 13 | 14 | * Initial release. 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015 Jiangge Zhang 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE README.rst 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | COMMANDS = help test release build clean 2 | .PHONY: $(COMMANDS) 3 | 4 | help: 5 | @echo "# You may need to 'pip install tox twine'." 6 | @echo 7 | @echo "available commands: $(COMMANDS)" 8 | 9 | test: 10 | tox 11 | 12 | release: clean build 13 | twine upload dist/*.{tar.gz,whl} 14 | 15 | build: 16 | python setup.py sdist bdist_wheel 17 | 18 | clean: 19 | rm -rf dist 20 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | |Build Status| |Coverage Status| |PyPI Version| |Wheel Status| 2 | 3 | Flask-Docker 4 | ============ 5 | 6 | Flask-Docker is an extension for Flask_ that integrates Docker_ client into 7 | your application. It is based on the official client docker-py_. 8 | 9 | .. _Flask: http://flask.pocoo.org 10 | .. _Docker: https://www.docker.com 11 | .. _docker-py: https://github.com/docker/docker-py#readme 12 | 13 | The document is in ReadTheDocs_. 14 | 15 | .. _ReadTheDocs: https://flask-docker.readthedocs.io 16 | 17 | 18 | Installation 19 | ------------ 20 | 21 | :: 22 | 23 | pip install Flask-Docker 24 | 25 | 26 | Issues 27 | ------ 28 | 29 | If you want to report bugs or request features, please create issues on 30 | `GitHub Issues `_. 31 | 32 | 33 | Contributes 34 | ----------- 35 | 36 | You can send a pull reueqst on 37 | `GitHub `_. 38 | 39 | 40 | 41 | .. |Build Status| image:: https://img.shields.io/travis/tonyseek/flask-docker.svg?style=flat 42 | :target: https://travis-ci.org/tonyseek/flask-docker 43 | :alt: Build Status 44 | .. |Coverage Status| image:: https://img.shields.io/coveralls/tonyseek/flask-docker.svg?style=flat 45 | :target: https://coveralls.io/r/tonyseek/flask-docker 46 | :alt: Coverage Status 47 | .. |Wheel Status| image:: https://img.shields.io/pypi/wheel/Flask-Docker.svg?style=flat 48 | :target: https://warehouse.python.org/project/Flask-Docker 49 | :alt: Wheel Status 50 | .. |PyPI Version| image:: https://img.shields.io/pypi/v/Flask-Docker.svg?style=flat 51 | :target: https://pypi.python.org/pypi/Flask-Docker 52 | :alt: PyPI Version 53 | -------------------------------------------------------------------------------- /docs/.python-virtualenv: -------------------------------------------------------------------------------- 1 | flask-docker-docs 2 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(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/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Flask-Docker.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Flask-Docker.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Flask-Docker" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Flask-Docker" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /docs/_static/flask-docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonyseek/flask-docker/bbc7faa72d0bb08fcd17f336abc210bb71f1e34e/docs/_static/flask-docker.png -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Flask-Docker documentation build configuration file, created by 4 | # sphinx-quickstart on Sat Jan 31 19:54:29 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys 16 | import os 17 | 18 | # If extensions (or modules to document with autodoc) are in another directory, 19 | # add these directories to sys.path here. If the directory is relative to the 20 | # documentation root, use os.path.abspath to make it absolute, like shown here. 21 | sys.path.insert(0, os.path.abspath('..')) 22 | 23 | # -- General configuration ------------------------------------------------ 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | #needs_sphinx = '1.0' 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be 29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 30 | # ones. 31 | extensions = [ 32 | 'sphinx.ext.autodoc', 33 | 'sphinx.ext.intersphinx', 34 | 'sphinx.ext.viewcode', 35 | ] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ['_templates'] 39 | 40 | # The suffix of source filenames. 41 | source_suffix = '.rst' 42 | 43 | # The encoding of source files. 44 | #source_encoding = 'utf-8-sig' 45 | 46 | # The master toctree document. 47 | master_doc = 'index' 48 | 49 | # General information about the project. 50 | project = u'Flask-Docker' 51 | copyright = u'2015, Jiangge Zhang' 52 | 53 | # The version info for the project you're documenting, acts as replacement for 54 | # |version| and |release|, also used in various other places throughout the 55 | # built documents. 56 | # 57 | # The short X.Y version. 58 | version = '0.2.0' 59 | # The full version, including alpha/beta/rc tags. 60 | release = '0.2.0' 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | #language = None 65 | 66 | # There are two options for replacing |today|: either, you set today to some 67 | # non-false value, then it is used: 68 | #today = '' 69 | # Else, today_fmt is used as the format for a strftime call. 70 | #today_fmt = '%B %d, %Y' 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. 74 | exclude_patterns = ['_build'] 75 | 76 | # The reST default role (used for this markup: `text`) to use for all 77 | # documents. 78 | #default_role = None 79 | 80 | # If true, '()' will be appended to :func: etc. cross-reference text. 81 | #add_function_parentheses = True 82 | 83 | # If true, the current module name will be prepended to all description 84 | # unit titles (such as .. function::). 85 | #add_module_names = True 86 | 87 | # If true, sectionauthor and moduleauthor directives will be shown in the 88 | # output. They are ignored by default. 89 | #show_authors = False 90 | 91 | # The name of the Pygments (syntax highlighting) style to use. 92 | pygments_style = 'sphinx' 93 | 94 | # A list of ignored prefixes for module index sorting. 95 | #modindex_common_prefix = [] 96 | 97 | # If true, keep warnings as "system message" paragraphs in the built documents. 98 | #keep_warnings = False 99 | 100 | 101 | # -- Options for HTML output ---------------------------------------------- 102 | 103 | # The theme to use for HTML and HTML Help pages. See the documentation for 104 | # a list of builtin themes. 105 | html_theme = 'kr_small' 106 | 107 | # Theme options are theme-specific and customize the look and feel of a theme 108 | # further. For a list of options available for each theme, see the 109 | # documentation. 110 | html_theme_options = { 111 | 'github_fork': 'tonyseek/flask-docker', 112 | 'github_fork_ribbon': 'http://aral.github.com/fork-me-on-github-retina-ribbons/right-grey@2x.png', 113 | 'index_logo': 'flask-docker.png', 114 | 'index_logo_width': '430px', 115 | 'index_logo_height': '100px', 116 | } 117 | 118 | # Add any paths that contain custom themes here, relative to this directory. 119 | #html_theme_path = [] 120 | 121 | # The name for this set of Sphinx documents. If None, it defaults to 122 | # " v documentation". 123 | #html_title = None 124 | 125 | # A shorter title for the navigation bar. Default is the same as html_title. 126 | #html_short_title = None 127 | 128 | # The name of an image file (relative to this directory) to place at the top 129 | # of the sidebar. 130 | #html_logo = None 131 | 132 | # The name of an image file (within the static path) to use as favicon of the 133 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 134 | # pixels large. 135 | #html_favicon = None 136 | 137 | # Add any paths that contain custom static files (such as style sheets) here, 138 | # relative to this directory. They are copied after the builtin static files, 139 | # so a file named "default.css" will overwrite the builtin "default.css". 140 | html_static_path = ['_static'] 141 | 142 | # Add any extra paths that contain custom files (such as robots.txt or 143 | # .htaccess) here, relative to this directory. These files are copied 144 | # directly to the root of the documentation. 145 | #html_extra_path = [] 146 | 147 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 148 | # using the given strftime format. 149 | #html_last_updated_fmt = '%b %d, %Y' 150 | 151 | # If true, SmartyPants will be used to convert quotes and dashes to 152 | # typographically correct entities. 153 | #html_use_smartypants = True 154 | 155 | # Custom sidebar templates, maps document names to template names. 156 | #html_sidebars = {} 157 | 158 | # Additional templates that should be rendered to pages, maps page names to 159 | # template names. 160 | #html_additional_pages = {} 161 | 162 | # If false, no module index is generated. 163 | #html_domain_indices = True 164 | 165 | # If false, no index is generated. 166 | #html_use_index = True 167 | 168 | # If true, the index is split into individual pages for each letter. 169 | #html_split_index = False 170 | 171 | # If true, links to the reST sources are added to the pages. 172 | #html_show_sourcelink = True 173 | 174 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 175 | #html_show_sphinx = True 176 | 177 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 178 | #html_show_copyright = True 179 | 180 | # If true, an OpenSearch description file will be output, and all pages will 181 | # contain a tag referring to it. The value of this option must be the 182 | # base URL from which the finished HTML is served. 183 | #html_use_opensearch = '' 184 | 185 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 186 | #html_file_suffix = None 187 | 188 | # Output file base name for HTML help builder. 189 | htmlhelp_basename = 'flaskdockerdoc' 190 | 191 | 192 | # -- Options for LaTeX output --------------------------------------------- 193 | 194 | latex_elements = { 195 | # The paper size ('letterpaper' or 'a4paper'). 196 | #'papersize': 'letterpaper', 197 | 198 | # The font size ('10pt', '11pt' or '12pt'). 199 | #'pointsize': '10pt', 200 | 201 | # Additional stuff for the LaTeX preamble. 202 | #'preamble': '', 203 | } 204 | 205 | # Grouping the document tree into LaTeX files. List of tuples 206 | # (source start file, target name, title, 207 | # author, documentclass [howto, manual, or own class]). 208 | latex_documents = [ 209 | ('index', 'Flask-Docker.tex', u'Flask-Docker Documentation', 210 | u'Jiangge Zhang', 'manual'), 211 | ] 212 | 213 | # The name of an image file (relative to this directory) to place at the top of 214 | # the title page. 215 | #latex_logo = None 216 | 217 | # For "manual" documents, if this is true, then toplevel headings are parts, 218 | # not chapters. 219 | #latex_use_parts = False 220 | 221 | # If true, show page references after internal links. 222 | #latex_show_pagerefs = False 223 | 224 | # If true, show URL addresses after external links. 225 | #latex_show_urls = False 226 | 227 | # Documents to append as an appendix to all manuals. 228 | #latex_appendices = [] 229 | 230 | # If false, no module index is generated. 231 | #latex_domain_indices = True 232 | 233 | 234 | # -- Options for manual page output --------------------------------------- 235 | 236 | # One entry per manual page. List of tuples 237 | # (source start file, name, description, authors, manual section). 238 | man_pages = [ 239 | ('index', 'flask-docker', u'Flask-Docker Documentation', 240 | [u'Jiangge Zhang'], 1) 241 | ] 242 | 243 | # If true, show URL addresses after external links. 244 | #man_show_urls = False 245 | 246 | 247 | # -- Options for Texinfo output ------------------------------------------- 248 | 249 | # Grouping the document tree into Texinfo files. List of tuples 250 | # (source start file, target name, title, author, 251 | # dir menu entry, description, category) 252 | texinfo_documents = [ 253 | ('index', 'Flask-Docker', u'Flask-Docker Documentation', 254 | u'Jiangge Zhang', 'Flask-Docker', 'One line description of project.', 255 | 'Miscellaneous'), 256 | ] 257 | 258 | # Documents to append as an appendix to all manuals. 259 | #texinfo_appendices = [] 260 | 261 | # If false, no module index is generated. 262 | #texinfo_domain_indices = True 263 | 264 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 265 | #texinfo_show_urls = 'footnote' 266 | 267 | # If true, do not generate a @detailmenu in the "Top" node's menu. 268 | #texinfo_no_detailmenu = False 269 | 270 | 271 | # -- Options for Epub output ---------------------------------------------- 272 | 273 | # Bibliographic Dublin Core info. 274 | epub_title = u'Flask-Docker' 275 | epub_author = u'Jiangge Zhang' 276 | epub_publisher = u'Jiangge Zhang' 277 | epub_copyright = u'2015, Jiangge Zhang' 278 | 279 | # The basename for the epub file. It defaults to the project name. 280 | #epub_basename = u'Flask-Docker' 281 | 282 | # The HTML theme for the epub output. Since the default themes are not optimized 283 | # for small screen space, using the same theme for HTML and epub output is 284 | # usually not wise. This defaults to 'epub', a theme designed to save visual 285 | # space. 286 | #epub_theme = 'epub' 287 | 288 | # The language of the text. It defaults to the language option 289 | # or en if the language is not set. 290 | #epub_language = '' 291 | 292 | # The scheme of the identifier. Typical schemes are ISBN or URL. 293 | #epub_scheme = '' 294 | 295 | # The unique identifier of the text. This can be a ISBN number 296 | # or the project homepage. 297 | #epub_identifier = '' 298 | 299 | # A unique identification for the text. 300 | #epub_uid = '' 301 | 302 | # A tuple containing the cover image and cover page html template filenames. 303 | #epub_cover = () 304 | 305 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. 306 | #epub_guide = () 307 | 308 | # HTML files that should be inserted before the pages created by sphinx. 309 | # The format is a list of tuples containing the path and title. 310 | #epub_pre_files = [] 311 | 312 | # HTML files shat should be inserted after the pages created by sphinx. 313 | # The format is a list of tuples containing the path and title. 314 | #epub_post_files = [] 315 | 316 | # A list of files that should not be packed into the epub file. 317 | epub_exclude_files = ['search.html'] 318 | 319 | # The depth of the table of contents in toc.ncx. 320 | #epub_tocdepth = 3 321 | 322 | # Allow duplicate toc entries. 323 | #epub_tocdup = True 324 | 325 | # Choose between 'default' and 'includehidden'. 326 | #epub_tocscope = 'default' 327 | 328 | # Fix unsupported image types using the PIL. 329 | #epub_fix_images = False 330 | 331 | # Scale large images. 332 | #epub_max_image_width = 0 333 | 334 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 335 | #epub_show_urls = 'inline' 336 | 337 | # If false, no index is generated. 338 | #epub_use_index = True 339 | 340 | 341 | # Example configuration for intersphinx: refer to the Python standard library. 342 | intersphinx_mapping = { 343 | 'http://docs.python.org/': None, 344 | 'http://flask.pocoo.org/docs/': None, 345 | } 346 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Flask-Docker 2 | ============ 3 | 4 | | 5 | 6 | .. include:: ../README.rst 7 | :start-line: 5 8 | :end-line: 12 9 | 10 | 11 | Installation 12 | ------------ 13 | 14 | :: 15 | 16 | $ pip install Flask-Docker 17 | 18 | 19 | Configuration 20 | ------------- 21 | 22 | You can configure it like most extensions of Flask. 23 | 24 | For single file applications: 25 | 26 | `yourapp.py`:: 27 | 28 | from flask import Flask 29 | from flask_docker import Docker 30 | 31 | app = Flask(__name__) 32 | docker = Docker(app) 33 | 34 | For large applications which following the application factory pattern: 35 | 36 | `yourapp/ext.py`:: 37 | 38 | from flask_docker import Docker 39 | 40 | docker = Docker() 41 | 42 | `yourapp/app.py`:: 43 | 44 | from flask import Flask 45 | from yourapp.ext import docker 46 | 47 | def create_app(): 48 | app = Flask(__name__) 49 | docker.init_app(app) 50 | return app 51 | 52 | The Flask-Docker has some configuration values that describes how to connect 53 | to the Docker server. 54 | 55 | ============================ ================================================== 56 | `DOCKER_URL` The URL of Docker server. **REQUIRED** 57 | `DOCKER_VERSION` The API version of Docker server. 58 | This defaults to ``"1.16"``. 59 | It is recommended to specify it instead of keeping 60 | default value in production environment to avoid 61 | upgrading issues. 62 | `DOCKER_TIMEOUT` The HTTP request timeout in seconds. 63 | This defaults to ``30``. 64 | `DOCKER_TLS` ``True`` if the SSL/TLS should be enabled. 65 | This defaults to ``False``. 66 | `DOCKER_TLS_VERIFY` ``True`` if the TLS certificate should be 67 | verified. 68 | This defaults to ``False``. 69 | `DOCKER_TLS_SSL_VERSION` The version of SSL. This defaults to ``None``. 70 | `DOCKER_TLS_ASSERT_HOSTNAME` ``True`` if the hostname in ``DOCKER_URL`` should 71 | be matched with the TLS certificate. 72 | This defaults to ``None``. 73 | `DOCKER_TLS_CLIENT_CERT` The file path to the client certificate. 74 | It is usually be used with a self-signed 75 | certificate. 76 | Because the client certificate have two files (a 77 | public and a private), this configuration value 78 | should be a colon-separated tuple of their path. 79 | (e.g. ``"/path/to/cert.pem:/path/to/key.pem"``) 80 | This defaults to ``None``. 81 | `DOCKER_TLS_CA_CERT` The file path to the CA certificate. 82 | It is usually be used with a self-signed 83 | certificate. 84 | This defaults to ``None``. 85 | `DOCKER_TLS_CERT_PATH` This defaults to ``None``. Once it be specified, 86 | The default value of `DOCKER_TLS_CLIENT_CERT` and 87 | `DOCKER_TLS_CA_CERT` will be filled to 88 | ``"{0}/cert.pem:{0}/key.pem"`` and 89 | ``"{0}/ca.pem"`` instead of 90 | ``None``. It is usually be used with boot2docker_. 91 | ============================ ================================================== 92 | 93 | .. _boot2docker: http://boot2docker.io 94 | 95 | 96 | Using with Boot2docker 97 | ---------------------- 98 | 99 | Boot2docker_ is one of the ways to use Docker in Mac OS X and Windows. It 100 | provides a command line utility to manage and inspect the VM (virtual machine) 101 | which running Docker. 102 | 103 | For using Flask-Docker with boot2docker, you need to start the VM and view its 104 | information:: 105 | 106 | $ boot2docker up 107 | ... 108 | $ boot2docker shellinit 109 | Writing /Users/yo/.boot2docker/certs/boot2docker-vm/ca.pem 110 | Writing /Users/yo/.boot2docker/certs/boot2docker-vm/cert.pem 111 | Writing /Users/yo/.boot2docker/certs/boot2docker-vm/key.pem 112 | export DOCKER_HOST=tcp://192.168.59.103:2376 113 | export DOCKER_CERT_PATH=/Users/yo/.boot2docker/certs/boot2docker-vm 114 | export DOCKER_TLS_VERIFY=1 115 | $ boot2docker ssh docker version 116 | Client version: 1.4.1 117 | Client API version: 1.16 118 | Go version (client): go1.3.3 119 | Git commit (client): 5bc2ff8 120 | OS/Arch (client): linux/amd64 121 | Server version: 1.4.1 122 | Server API version: 1.16 123 | Go version (server): go1.3.3 124 | Git commit (server): 5bc2ff8 125 | 126 | Now you can configure your Flask application:: 127 | 128 | $ cat /path/to/config 129 | DOCKER_URL="https://192.168.59.103:2376" 130 | DOCKER_VERSION="1.16" 131 | DOCKER_TLS=True 132 | DOCKER_TLS_CERT_PATH="/Users/yo/.boot2docker/certs/boot2docker-vm" 133 | DOCKER_TLS_ASSERT_HOSTNAME=False 134 | 135 | The self-signed certificate of boot2docker usually uses ``boot2docker`` as 136 | hostname. It is not able to be matched with ``http://192.168.59.103:2376``. 137 | So you may need to set ``DOCKER_TLS_ASSERT_HOSTNAME`` to ``False``. 138 | 139 | .. _Boot2docker: http://boot2docker.io 140 | 141 | 142 | API Reference 143 | ------------- 144 | 145 | .. autoclass:: flask_docker.Docker 146 | :members: 147 | 148 | .. include:: ../CHANGELOG.rst 149 | -------------------------------------------------------------------------------- /docs/requirements.in: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-kr-theme 3 | 4 | jinja2>=2.8.1 # CVE-2016-10745 and CVE-2019-10906 5 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile 3 | # To update, run: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | docutils==0.12 # via sphinx 8 | jinja2==2.10.1 9 | markupsafe==0.23 # via jinja2 10 | pygments==2.0.2 # via sphinx 11 | sphinx-kr-theme==0.2.1 12 | sphinx==1.2.3 13 | -------------------------------------------------------------------------------- /flask_docker.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask import current_app 4 | from docker import Client 5 | from docker.tls import TLSConfig 6 | 7 | 8 | __all__ = ['Docker'] 9 | __version__ = '0.2.0' 10 | 11 | 12 | class Docker(object): 13 | """The integrating between docker client and flask environment. 14 | 15 | The instance of :class:`docker.Client` will be created lazily and exist in 16 | the current application context. 17 | """ 18 | 19 | def __init__(self, app=None): 20 | if app is None: 21 | self.app = current_app 22 | else: 23 | self.app = app 24 | self.init_app(app) 25 | 26 | def init_app(self, app): 27 | """Initializes an application for using :class:`docker.Client`. 28 | 29 | :param app: an instance of :class:`~flask.Flask`. 30 | """ 31 | app.extensions = getattr(app, 'extensions', {}) 32 | app.extensions['docker.client'] = None 33 | 34 | app.config.setdefault('DOCKER_URL', None) 35 | app.config.setdefault('DOCKER_VERSION', '1.16') 36 | app.config.setdefault('DOCKER_TIMEOUT', 30) 37 | app.config.setdefault('DOCKER_TLS', False) 38 | app.config.setdefault('DOCKER_TLS_VERIFY', True) 39 | app.config.setdefault('DOCKER_TLS_SSL_VERSION', None) 40 | app.config.setdefault('DOCKER_TLS_ASSERT_HOSTNAME', None) 41 | 42 | app.config.setdefault('DOCKER_TLS_CERT_PATH', None) 43 | app.config.setdefault('DOCKER_TLS_CLIENT_CERT', None) 44 | app.config.setdefault('DOCKER_TLS_CA_CERT', None) 45 | 46 | @property 47 | def client(self): 48 | """The original :class:`docker.Client` object. All docker operation 49 | calling will be forwarded here. :: 50 | 51 | docker.create_container('ubuntu') 52 | docker.client.create_container('ubuntu') # equivalent 53 | """ 54 | if not self.app.config['DOCKER_URL']: 55 | raise RuntimeError('"DOCKER_URL" must be specified') 56 | 57 | if not self.app.extensions['docker.client']: 58 | self.app.extensions['docker.client'] = Client( 59 | base_url=self.app.config['DOCKER_URL'], 60 | version=self.app.config['DOCKER_VERSION'], 61 | timeout=self.app.config['DOCKER_TIMEOUT'], 62 | tls=make_tls_config(self.app.config)) 63 | return self.app.extensions['docker.client'] 64 | 65 | def __getattr__(self, name): 66 | if name != 'app' and hasattr(self.client, name): 67 | return getattr(self.client, name) 68 | return object.__getattribute__(self, name) 69 | 70 | 71 | def make_tls_config(app_config): 72 | """Creates TLS configuration object.""" 73 | 74 | if not app_config['DOCKER_TLS']: 75 | return False 76 | 77 | cert_path = app_config['DOCKER_TLS_CERT_PATH'] 78 | if cert_path: 79 | client_cert = '{0}:{1}'.format( 80 | os.path.join(cert_path, 'cert.pem'), 81 | os.path.join(cert_path, 'key.pem')) 82 | ca_cert = os.path.join(cert_path, 'ca.pem') 83 | else: 84 | client_cert = app_config['DOCKER_TLS_CLIENT_CERT'] 85 | ca_cert = app_config['DOCKER_TLS_CA_CERT'] 86 | 87 | client_cert = parse_client_cert_pair(client_cert) 88 | return TLSConfig( 89 | client_cert=client_cert, 90 | ca_cert=ca_cert, 91 | verify=app_config['DOCKER_TLS_VERIFY'], 92 | ssl_version=app_config['DOCKER_TLS_SSL_VERSION'], 93 | assert_hostname=app_config['DOCKER_TLS_ASSERT_HOSTNAME']) 94 | 95 | 96 | def parse_client_cert_pair(config_value): 97 | """Parses the client cert pair from config item. 98 | 99 | :param config_value: the string value of config item. 100 | :returns: tuple or none. 101 | """ 102 | if not config_value: 103 | return 104 | client_cert = config_value.split(':') 105 | if len(client_cert) != 2: 106 | tips = ('client_cert should be formatted like ' 107 | '"/path/to/cert.pem:/path/to/key.pem"') 108 | raise ValueError('{0!r} is invalid.\n{1}'.format(config_value, tips)) 109 | return tuple(client_cert) 110 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | 4 | [tool:pytest] 5 | addopts = --pep8 --cov flask_docker 6 | pep8ignore = 7 | docs/conf.py ALL 8 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup 3 | 4 | 5 | with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme: 6 | next(readme) 7 | long_description = ''.join(readme).strip() 8 | 9 | 10 | setup( 11 | name='Flask-Docker', 12 | description='Using Docker client in your Flask application.', 13 | long_description=long_description, 14 | version='0.2.0', 15 | author='Jiangge Zhang', 16 | author_email='tonyseek@gmail.com', 17 | url='https://github.com/tonyseek/flask-docker', 18 | license='MIT', 19 | classifiers=[ 20 | 'Development Status :: 3 - Alpha', 21 | 'Environment :: Web Environment', 22 | 'Framework :: Flask', 23 | 'Intended Audience :: Developers', 24 | 'License :: OSI Approved :: MIT License', 25 | 'Operating System :: OS Independent', 26 | 'Programming Language :: Python :: 2', 27 | 'Programming Language :: Python :: 2.6', 28 | 'Programming Language :: Python :: 2.7', 29 | 'Programming Language :: Python :: 3', 30 | 'Programming Language :: Python :: 3.3', 31 | 'Programming Language :: Python :: 3.4', 32 | 'Programming Language :: Python :: Implementation :: CPython', 33 | 'Programming Language :: Python :: Implementation :: PyPy', 34 | 'Topic :: Software Development :: Libraries', 35 | 'Topic :: Utilities', 36 | ], 37 | zip_safe=False, 38 | py_modules=['flask_docker'], 39 | install_requires=['flask', 'docker-py'], 40 | platforms=['Any']) 41 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonyseek/flask-docker/bbc7faa72d0bb08fcd17f336abc210bb71f1e34e/tests/conftest.py -------------------------------------------------------------------------------- /tests/test_factory.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, current_app 2 | from flask_docker import Docker 3 | from pytest import fixture, raises 4 | import responses 5 | 6 | 7 | docker = Docker() 8 | 9 | 10 | def create_app(): 11 | app = Flask(__name__) 12 | docker.init_app(app) 13 | return app 14 | 15 | 16 | @fixture 17 | def app(request): 18 | app = create_app() 19 | ctx = app.app_context() 20 | ctx.push() 21 | request.addfinalizer(ctx.pop) 22 | return app 23 | 24 | 25 | def test_factory(): 26 | assert docker.app is current_app 27 | 28 | 29 | def test_out_of_context(): 30 | docker.app # nothing raises 31 | 32 | # but if we... 33 | with raises(RuntimeError) as error: 34 | docker.app.name 35 | assert 'outside of application context' in error.value.args[0] 36 | 37 | with raises(RuntimeError) as error: 38 | docker.client 39 | assert 'outside of application context' in error.value.args[0] 40 | 41 | 42 | def test_url_missing(app): 43 | with raises(RuntimeError) as error: 44 | docker.client 45 | assert error.value.args[0] == '"DOCKER_URL" must be specified' 46 | 47 | 48 | @responses.activate 49 | def test_versioned(app): 50 | responses.add( 51 | responses.GET, 'http://docker-testing:2375/v1.11/info', 52 | body='{"message": "Yo! Gotcha."}', status=200, 53 | content_type='application/json') 54 | app.config['DOCKER_URL'] = 'http://docker-testing:2375' 55 | app.config['DOCKER_VERSION'] = '1.11' 56 | 57 | assert docker.client.info() == {'message': 'Yo! Gotcha.'} 58 | 59 | 60 | def test_lazy_creation(app): 61 | app.config['DOCKER_URL'] = 'http://docker-testing:2375' 62 | 63 | assert app.extensions['docker.client'] is None 64 | 65 | client1 = docker.client 66 | client2 = docker.client 67 | 68 | assert app.extensions['docker.client'] is client1 is client2 69 | 70 | 71 | def test_isolation(): 72 | app1 = create_app() 73 | app2 = create_app() 74 | 75 | app1.config['DOCKER_URL'] = 'http://docker-testing1:2375' 76 | app2.config['DOCKER_URL'] = 'http://docker-testing2:2375' 77 | 78 | docker1 = None 79 | docker2 = None 80 | 81 | with app1.app_context(): 82 | docker1 = docker.client 83 | with app2.app_context(): 84 | docker2 = docker.client 85 | 86 | assert docker1 is not docker2 87 | -------------------------------------------------------------------------------- /tests/test_simple.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, current_app 2 | from flask_docker import Docker 3 | from pytest import fixture, raises 4 | import responses 5 | 6 | 7 | @fixture 8 | def docker(): 9 | app = Flask(__name__) 10 | docker = Docker(app) 11 | return docker 12 | 13 | 14 | def test_singleton(docker): 15 | assert docker.app 16 | assert docker.app is not current_app 17 | 18 | 19 | def test_url_missing(docker): 20 | with raises(RuntimeError) as error: 21 | docker.client 22 | assert error.value.args[0] == '"DOCKER_URL" must be specified' 23 | 24 | 25 | @responses.activate 26 | def test_delegate(docker): 27 | responses.add( 28 | responses.GET, 'http://docker-testing:2375/v1.16/info', 29 | body='{"message": "Yo! Gotcha."}', status=200, 30 | content_type='application/json') 31 | docker.app.config['DOCKER_URL'] = 'http://docker-testing:2375' 32 | 33 | assert docker.client.info() == {'message': 'Yo! Gotcha.'} 34 | 35 | 36 | def test_lazy_creation(docker): 37 | docker.app.config['DOCKER_URL'] = 'http://docker-testing:2375' 38 | 39 | assert docker.app.extensions['docker.client'] is None 40 | 41 | client1 = docker.client 42 | client2 = docker.client 43 | 44 | assert docker.app.extensions['docker.client'] is client1 is client2 45 | 46 | 47 | def test_attribute_lookup(docker): 48 | docker.app.config['DOCKER_URL'] = 'http://docker-testing:2375' 49 | 50 | assert docker.info == docker.client.info 51 | assert docker.create_container == docker.client.create_container 52 | 53 | with raises(AttributeError) as error: 54 | docker.tonyseek 55 | assert error.value.args[0] == "'Docker' object has no attribute 'tonyseek'" 56 | -------------------------------------------------------------------------------- /tests/test_tls.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_docker import Docker 3 | from pytest import fixture, raises 4 | from mock import patch 5 | 6 | 7 | docker = Docker() 8 | 9 | 10 | @fixture 11 | def current_app(request): 12 | app = Flask(__name__) 13 | docker.init_app(app) 14 | 15 | ctx = app.app_context() 16 | ctx.push() 17 | request.addfinalizer(ctx.pop) 18 | 19 | return app 20 | 21 | 22 | @patch('flask_docker.TLSConfig') 23 | def test_tls_disabled(TLSConfig, current_app): 24 | current_app.config['DOCKER_URL'] = 'http://docker-testing:2375' 25 | 26 | assert current_app.config['DOCKER_TLS'] is False 27 | assert not TLSConfig.called 28 | 29 | 30 | @patch('flask_docker.TLSConfig') 31 | def test_tls_enabled(TLSConfig, current_app): 32 | current_app.config['DOCKER_URL'] = 'https://docker-testing:2375' 33 | current_app.config['DOCKER_TLS'] = True 34 | 35 | assert docker.client 36 | assert TLSConfig.called 37 | TLSConfig.assert_called_with( 38 | client_cert=None, ca_cert=None, verify=True, ssl_version=None, 39 | assert_hostname=None) 40 | 41 | 42 | @patch('flask_docker.TLSConfig') 43 | def test_tls_config(TLSConfig, current_app): 44 | current_app.config['DOCKER_URL'] = 'https://docker-testing:2375' 45 | current_app.config['DOCKER_TLS'] = True 46 | current_app.config['DOCKER_TLS_VERIFY'] = False 47 | current_app.config['DOCKER_TLS_SSL_VERSION'] = '12345' 48 | current_app.config['DOCKER_TLS_ASSERT_HOSTNAME'] = False 49 | current_app.config['DOCKER_TLS_CLIENT_CERT'] = \ 50 | '/etc/certs/cert.pem:/etc/certs/key.pem' 51 | current_app.config['DOCKER_TLS_CA_CERT'] = '/etc/certs/ca.pem' 52 | 53 | assert docker.client 54 | assert TLSConfig.called 55 | TLSConfig.assert_called_with( 56 | client_cert=('/etc/certs/cert.pem', '/etc/certs/key.pem'), 57 | ca_cert='/etc/certs/ca.pem', verify=False, ssl_version='12345', 58 | assert_hostname=False) 59 | 60 | 61 | @patch('flask_docker.TLSConfig') 62 | def test_tls_cert_path(TLSConfig, current_app): 63 | current_app.config['DOCKER_URL'] = 'https://docker-testing:2375' 64 | current_app.config['DOCKER_TLS'] = True 65 | current_app.config['DOCKER_TLS_ASSERT_HOSTNAME'] = False 66 | current_app.config['DOCKER_TLS_CERT_PATH'] = '/etc/certs2' 67 | 68 | assert docker.client 69 | assert TLSConfig.called 70 | TLSConfig.assert_called_with( 71 | client_cert=('/etc/certs2/cert.pem', '/etc/certs2/key.pem'), 72 | ca_cert='/etc/certs2/ca.pem', verify=True, ssl_version=None, 73 | assert_hostname=False) 74 | 75 | 76 | def test_tls_invalid_client_cert(current_app): 77 | current_app.config['DOCKER_URL'] = 'https://docker-testing:2375' 78 | current_app.config['DOCKER_TLS'] = True 79 | current_app.config['DOCKER_TLS_CLIENT_CERT'] = 'yo' 80 | 81 | with raises(ValueError) as error: 82 | docker.client 83 | assert ' is invalid' in error.value.args[0] 84 | assert "'yo'" in error.value.args[0] 85 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27,py34,py35,py36,py37,pypy,docs 3 | 4 | [testenv] 5 | # Fit for the bad design of Python 3.x 6 | setenv = 7 | LC_ALL=C.UTF-8 8 | LANG=C.UTF-8 9 | deps = 10 | setuptools>=12.0 11 | pytest>=3.6 12 | pytest-cov 13 | pytest-pep8 14 | mock 15 | responses 16 | commands = 17 | py.test 18 | 19 | [testenv:docs] 20 | changedir = docs 21 | deps = 22 | --requirement=docs/requirements.txt 23 | whitelist_externals = 24 | make 25 | commands = 26 | make html 27 | --------------------------------------------------------------------------------