Retire dox repository

This change removes all content from the repository and adds the usual
README file to point out that the repository is retired following the
process from
https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project

Depends-On: https://review.opendev.org/701446
Change-Id: I49ddca0f6c4a5d0e546e22a5515d405f0e869eab
This commit is contained in:
Andreas Jaeger 2020-01-07 20:46:02 +01:00
parent 3087d31254
commit 06e67f317d
55 changed files with 8 additions and 2514 deletions

View File

@ -1,7 +0,0 @@
[run]
branch = True
source = dox
omit = dox/tests/*,dox/openstack/*
[report]
ignore_errors = True

55
.gitignore vendored
View File

@ -1,55 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
.testrepository
cover
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
# Autogenerated by ourseleves when testing the dox.yml
.dox

View File

@ -1,3 +0,0 @@
# Format is:
# <preferred e-mail> <other e-mail 1>
# <preferred e-mail> <other e-mail 2>

View File

@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,16 +0,0 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Storyboard, not GitHub:
https://storyboard.openstack.org

View File

@ -1,4 +0,0 @@
dox Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

175
LICENSE
View File

@ -1,175 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -1,6 +0,0 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

View File

@ -1,149 +1,10 @@
===
dox
===
This project is no longer maintained.
dox is a tool for using docker containers to run local tests, inspired by
tox and virtualenv for python. There are two elements to its configuration:
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
* What commands should be run?
* In what image should they be run?
If there is a dox.yml file, you're set. You want to specify what image to
use and what commands to run. You win::
image: ubuntu:trusty
commands: |
pip install . -r test-requirements.txt
python setup.py test
You might either not be willing to commit to dox as a way of life yet, or you
may want to use dox in a project that similarly has not done so.
What commands should be run
---------------------------
dox.yml wins.
If there is a tox.ini file, the commands specified in the base [testenv]
will be used.
If there is a .travis.yml file, the script section will be used.
If there are none of those things, dox will do its best to infer what
should be done. Examining the directory can often provide hints if you
haven't been too clever. For instance, if you have a Gruntfile, you probably
want to run grunt. If you have a Makefile, then make && make test is probably
your bag. If you have a Makefile.am, you probably want to run autotools first.
If you have a setup.py file, python setup.py test is a likely choice (although
in that case, you probably haven't done it right because setuptools support
for this is quite awful.)
After all of that, if we still can't figure out what you want - it's probably
easiest to just edit a file called dox.yml and put in a section telling us
what to do.
In what image should they be run
--------------------------------
Again, dox.yml wins, and thanks for making things easy!
If there is a tox.ini file, and it contains a [docker] section, the value in
"image" will be used::
[docker]
image=ubuntu:trusty
If there is not an image key in the docker section or an image key in the
dox.yml but there is a Dockerfile in the repo, an new image will be built
using the Dockerfile and the test commands will be run inside of the image.
If all of that fails, tests are going to run in a bare ubuntu image. Good luck!
Image Caching
-------------
Every run actually has two images associated with it: The `base` image and
the `test` image.
The image referenced above is the `base` image. When you execute `dox`,
it will search docker for the named image. If it exists, it will do nothing.
If it does not, it will either pull it, or, it will build it from the
Dockerfile. In the case of building from a Dockerfile, dox will make an image
named for the source directory. So if you're in ~/src/openstack/nova, it'll
make an image called "dox/nova/base".
The `test` image is an image made by dox for the test run. Similar to the
base run, it'll have a generated name, such as "dox/nova/test", and similar
to the base image, it will get generated once and then left alone.
If you want to regenerate the `test` image, you can run dox with the `-r`
option. If you want to regenerate/repull everything, you can run it with the
`--rebuild-all` option.
The reasoning behind this is that the base image should really be the
substrata which doesn't have a lot to do with the repo itself ... it shouldn't
really expect to change much based on day to day changes in the repo. The
test image on the other hand is built a bit more based on the repo itself.
So, for instance, in the base image you might want to do things like::
apt-get install libxml-dev
and in the test image, you'd want things like::
pip install -U requirements.txt
Neither change frequently, but the second it more likely to change day to day
than the first.
Additional information
----------------------
Regardless, dox will mount the current source dir as a volume at `/src` in
the container and will run commands in that context.
dox will attempt to reuse containers. Since the source is bind-mounted into
the container, things that might be expensive like copying source dirs or
re-installing the source into the system can be minimized.
Boot2Docker support
-------------------
To get support for non Linux OSes that doesn't support natively docker
there is a tool called `boot2docker <http://boot2docker.io/>`_ which
allows you to run a remote docker server in a VirtualBox VM and the
client running on the non Linux desktop.
Volume support started to be supported by `boot2docker` since docker version
1.3. You will need to be at least on that version to have volume mount support.
If you username id is different from the docker username on the `boot2docker` vm,
you will need to specify it on the command line, like this::
dox --user-map=docker:1000:10
If you use VirtualBox guest additions to mount your osx onto the `boot2docker` vm,
example /Users/your_name/openstack/oslo-incubator as /home/your_name/openstack/oslo-incubator,
then you can add the following mapping::
dos --path-map=/Users/your_name:/home/your_name
Advanced
--------
It is possible to specify multiple images to be used in a dox run.
Images can be provided on the command line, via the dox.yml file, or the
tox.ini file.
For the command line, images should be provided via the --images option,
in a comma-separated list.
The tox.ini file should also use a comma-separated list.
The dox.yml file should list images in an array.
The same prep and command instructions will be executed on each image sequentially.
dox does not currently allow for multiple images executing different tasks
at this time. However, it is a goal to allow for such test scenarios in
the future.
For any further questions, please email
openstack-discuss@lists.openstack.org or join #openstack-dev on
Freenode.

View File

@ -1 +0,0 @@
[python: **.py]

View File

@ -1,6 +0,0 @@
# This is a cross-platform list tracking distribution packages needed by tests;
# see http://docs.openstack.org/infra/bindep/ for additional information.
docker.io [platform:dpkg test]
python-dev [platform:dpkg test]
python-devel [platform:rpm test]

View File

@ -1,74 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# 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',
'oslo.sphinx'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'dox'
copyright = u'2013, OpenStack Foundation'
# 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
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -1 +0,0 @@
.. include:: ../../CONTRIBUTING.rst

View File

@ -1,37 +0,0 @@
.. dox documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to dox's documentation!
========================================================
Contents:
.. toctree::
:maxdepth: 2
readme
installation
usage
contributing
Release Notes
==============
0.2.0
-----
dffe391 Don't prefix the cached image with `_`
ea141b9 Don't run useradd for root
d3971df Add Centos 7 Dockerfile
d0d15f9 More informative error when command fails
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,12 +0,0 @@
============
Installation
============
At the command line::
$ pip install dox
Or, if you have virtualenvwrapper installed::
$ mkvirtualenv dox
$ pip install dox

View File

@ -1 +0,0 @@
.. include:: ../README.rst

View File

@ -1,7 +0,0 @@
========
Usage
========
To use dox in a project::
import dox

View File

@ -1,9 +0,0 @@
FROM centos:7
MAINTAINER OpenStack <openstack-dev@lists.openstack.org>
RUN yum -y update
RUN yum -y groupinstall 'Development Tools'
RUN yum -y install wget git python
RUN wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py && rm get-pip.py
RUN pip install -U setuptools

View File

@ -1,9 +0,0 @@
FROM fedora:20
MAINTAINER OpenStack <openstack-dev@lists.openstack.org>
RUN yum -y update
RUN yum -y groupinstall 'Development Tools'
RUN yum -y install wget git python
RUN wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py && rm get-pip.py
RUN pip install -U setuptools

View File

@ -1,8 +0,0 @@
FROM ubuntu:trusty
MAINTAINER OpenStack <openstack-dev@lists.openstack.org>
RUN apt-get update --fix-missing
RUN apt-get install -y build-essential wget git python python-dev
RUN wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py && rm get-pip.py
RUN pip install -U setuptools

View File

@ -1,8 +0,0 @@
FROM ubuntu:xenial
MAINTAINER OpenStack <openstack-dev@lists.openstack.org>
RUN apt-get update --fix-missing
RUN apt-get install -y build-essential wget git python python-dev
RUN wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py && rm get-pip.py
RUN pip install -U setuptools

19
dox.yml
View File

@ -1,19 +0,0 @@
testing:
images:
- infra/trusty
add:
- requirements.txt
- test-requirements.txt
prep:
- pip install -U -r requirements.txt -r test-requirements.txt
commands:
- export PYTHONHASHSEED=$RANDOM
- python setup.py testr --slowest
testing:pep8:
commands:
- flake8
testing:cover:
commands:
- /bin/echo "hello"

View File

@ -1,16 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pbr.version
__version__ = pbr.version.VersionInfo('dox').version_string()

View File

@ -1,140 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import functools
import logging
import os
import sys
import dox.commands
import dox.config.cmdline
import dox.images
import dox.runner
logger = logging.getLogger(__name__)
def get_log_level(args):
if args.debug:
return logging.DEBUG
if args.quiet:
return logging.WARN
return logging.INFO
def setup_logging(level):
handler = logging.StreamHandler()
formatter = logging.Formatter('%(levelname)s|%(name)s|%(message)s')
handler.setFormatter(formatter)
logger = logging.getLogger('dox')
logger.setLevel(level)
logger.addHandler(handler)
def parse_args():
parser = argparse.ArgumentParser(description='Run tests in docker.')
parser.add_argument(dest='extra_args', nargs='*',
help='args to append to command, or command to run'
' if -c is given')
parser.add_argument('-i', '--images', dest='images',
help='Base images to use')
parser.add_argument('-e', '--environment', dest='environment',
default=None,
help='Run target environment.')
parser.add_argument('-c', '--command', dest='command', default=False,
action='store_true',
help='Treat arguments as the entire command to run')
parser.add_argument('-r', '--rebuild', dest='rebuild', default=False,
action='store_true',
help='Rebuild the test image')
parser.add_argument('--rebuild-all', dest='rebuild_all', default=False,
action='store_true', help='Rebuild all images')
parser.add_argument('-d', '--debug', dest='debug', default=False,
action='store_true', help='Debug mode')
parser.add_argument('-q', '--quiet', dest='quiet', default=False,
action='store_true', help='Quiet output')
parser.add_argument('-n', '--noop', dest='noop', default=False,
action='store_true',
help="Don't actually execute commands")
parser.add_argument('--user-map', default=os.environ.get("DOX_USER_MAP"),
help='User to run the container to '
'format is user:uid:gid, with boot2docker use '
'docker:1000:10 (default to your current user)')
parser.add_argument('--path-map', default=os.environ.get("DOX_PATH_MAP"),
help='with boot2docker, specify how osx path maps to '
'linux path. example --path-map /Users:/home, '
'means /Users is available as /home on docker '
'container')
parser.add_argument('-k', '--keep', dest='keep_image', default=False,
action='store_true',
help="Keep test container after command finishes")
return parser.parse_args()
def main():
args = parse_args()
setup_logging(get_log_level(args))
return runner(args)
def run_dox(args, images, command, image_name):
# Run
try:
run = functools.partial(dox.runner.Runner(args, image_name).run,
command=command)
map(run, images)
except Exception as e:
logger.error("Operation failed, aborting dox.", exc_info=e)
return 1
def runner(args):
options = {}
args_images = None
if not dox.runner.Runner(args).is_docker_installed():
sys.exit(1)
# Get Image
if args.images:
args_images = [x.strip() for x in args.images.split(',')]
if args.command:
command = dox.config.cmdline.CommandLine(args.extra_args)
logger.debug("Command source is the command line")
return run_dox(args, args_images, command, image_name="commandline")
if args.environment:
sections = args.environment.split(',')
else:
sections = ['_default']
for section in sections:
options['section'] = section
if args_images:
images = args_images
else:
images = dox.images.get_images(options)
command = dox.commands.Commands(args.extra_args, options)
logger.debug("Command source is %s, section %s" % (
command.source.source_name(), section))
# TODO(chmouel): add to section a proper image_name that include the
# type of backend i.e: dox_yaml/tox_init
run_dox(args, images, command, image_name=section)

View File

@ -1,96 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'get_commands',
'Commands',
]
import logging
import os
import dox.config.dox_yaml
import dox.config.tox_ini
import dox.config.travis_yaml
logger = logging.getLogger(__name__)
def get_commands(options):
'''Examine the local environment and figure out what we should run.'''
dox_yaml = dox.config.dox_yaml.get_dox_yaml(options)
tox_ini = dox.config.tox_ini.get_tox_ini(options)
travis_yaml = dox.config.travis_yaml.get_travis_yaml(options)
for source in (dox_yaml, tox_ini, travis_yaml):
if source.exists():
return source
raise Exception("dox cannot figure out what command to run")
class Commands(object):
def __init__(self, extra_args=[], options=None):
self.options = options or {}
self.source = get_commands(options)
self.args = []
self.extra_args = extra_args
def _test_command_as_script(self, commands, shell='/bin/sh'):
"""Combine test commands into a master script file.
The script, using the given shell, will be created in the .dox
subdirectory of the current directory.
:param commands: A list of commands to execute.
:param shell: Path to the OS shell to run the commands.
"""
dox_dir = '.dox'
master_script = os.path.join(dox_dir, 'master_script.sh')
if not os.path.exists(dox_dir):
os.mkdir(dox_dir, 0o755)
with open(master_script, "w") as f:
f.write("#!" + shell + "\n")
f.write("\n".join(commands))
f.write("\n")
os.chmod(master_script, 0o700)
return master_script
def test_command(self):
"""Return the command to execute in the container.
If there is more than one command, we combine them into a master
script to execute. Otherwise, we just issue the command normally
on the docker command line.
"""
commands = self.source.get_commands(self.extra_args)
if len(commands) > 1:
return self._test_command_as_script(commands)
ret = commands[0] + ' ' + ' '.join(self.args)
return ret.strip()
def prep_commands(self):
return self.source.get_prep_commands()
def get_add_files(self):
return self.source.get_add_files()
def append(self, args):
self.args = args

View File

View File

@ -1,81 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class ConfigBase(object):
"""Configuration file reader base class."""
def __init__(self, options):
self.options = options
@abc.abstractmethod
def exists(self):
"""Check if the configuration file is present.
:returns: True if the file is present.
:returns: False if the file is not present.
"""
@abc.abstractmethod
def get_images(self):
"""Get list of docker source images used to build the test image.
:returns: List of image names in <user>/<repo>[:<tag>] format.
"""
@abc.abstractmethod
def get_commands(self):
"""Get list of commands to execute with the final test image.
These commands will be executed via the 'docker run' command
with the final test image.
:returns: List of executable commands.
"""
@abc.abstractmethod
def get_prep_commands(self):
"""Get list of commands to run while building the test image.
These commands will be executed while building the test image,
thus allowing for any software installation, configuration, etc.
to be built into the test image.
:returns: List of executable commands.
"""
@abc.abstractmethod
def get_add_files(self):
"""Get list of files to add to the test image.
The named files will be placed in the working directory of the
built test image.
:returns: List of file names.
"""
@abc.abstractmethod
def source_name(self):
"""The source of the configuration.
This identifies the source of the configuration values. E.g.,
a file name, or other descriptive text.
:returns: String describing the source.
"""

View File

@ -1,33 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'CommandLine',
]
class CommandLine(object):
def __init__(self, args):
self.args = args
def test_command(self):
return " ".join(self.args)
def prep_commands(self):
return ""
def get_add_files(self):
return []

View File

@ -1,35 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'get_dockerfile',
]
import os
_dockerfile = None
def get_dockerfile():
global _dockerfile
if _dockerfile is None:
_dockerfile = Dockerfile()
return _dockerfile
class Dockerfile(object):
def exists(self):
return os.path.exists('Dockerfile')

View File

@ -1,107 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import yaml
import dox.config.base as base
__all__ = [
'get_dox_yaml',
]
_dox_yaml = None
class DoxYamlSectionNotFound(Exception):
pass
def get_dox_yaml(options):
global _dox_yaml
if _dox_yaml is None:
_dox_yaml = DoxYaml(options)
return _dox_yaml
class DoxYaml(base.ConfigBase):
_yaml = None
dox_file = 'dox.yml'
default_section = 'testing'
default_keys_of_section = ['images', 'commands', 'add', 'prep']
def _parse_parent_child_section(self, section, _yaml):
ret = {}
if ':' not in section:
return _yaml
parent, child = section.split(':')
if parent in self._yaml.keys():
ret = self._yaml.get(parent)
ret.update(_yaml)
else:
raise DoxYamlSectionNotFound("Parent %s was not found" % parent)
return ret
def get_section(self, _yaml, section):
if section == '_default':
section = self.default_section
# NOTE(chmou): This is for compatibility mode with dox.yml with no
# sections, probably need to be removed in the future
if (section is None and
(all(i in _yaml.keys() for i in self.default_keys_of_section)
or all(i in self.default_keys_of_section
for i in _yaml.keys()))):
return _yaml
elif not section:
if self.default_section in _yaml.keys():
return self._parse_parent_child_section(
self.default_section, _yaml.get(self.default_section))
raise DoxYamlSectionNotFound("You need to specify a section.")
elif section not in _yaml.keys():
raise DoxYamlSectionNotFound(section)
return self._parse_parent_child_section(section,
_yaml.get(section))
def _open_dox_yaml(self):
if self._yaml is None:
with open(self.dox_file, 'r') as f:
self._yaml = yaml.load(f)
return self.get_section(self._yaml,
self.options.get('section'))
def source_name(self):
return self.dox_file
def exists(self):
return os.path.exists(self.dox_file)
def get_images(self):
return self._open_dox_yaml().get('images', [])
def get_commands(self, extra_args):
return self._open_dox_yaml().get('commands', [])
def get_prep_commands(self):
return self._open_dox_yaml().get('prep', [])
def get_add_files(self):
return self._open_dox_yaml().get('add', [])

View File

@ -1,101 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from six.moves.configparser import ConfigParser
import dox.config.base as base
__all__ = [
'get_tox_ini',
]
_tox_ini = None
def get_tox_ini(options):
global _tox_ini
if _tox_ini is None:
_tox_ini = ToxIni(options)
return _tox_ini
class ToxIni(base.ConfigBase):
_ini = None
tox_ini_file = 'tox.ini'
default_section = 'testenv'
def _open_tox_ini(self):
if self._ini is None:
self._ini = ConfigParser()
self._ini.read(self.tox_ini_file)
return self._ini
def source_name(self):
return self.tox_ini_file
def exists(self):
return os.path.exists(self.tox_ini_file)
def get_images(self):
ini = self._open_tox_ini()
if ini.has_option('docker', 'images'):
return ini.get('docker', 'images').split(',')
def get_commands(self, extra_args):
"""Get commands to run from the config file.
If any of the commands contain the string '{posargs}', then this
is replaced with the extra_args value.
"""
section = self.options.get('section',
self.default_section)
if section == '_default':
section = self.default_section
ini = self._open_tox_ini()
commands = ini.get(section, 'commands').split("\n")
extra_args = " ".join(extra_args)
scrubbed = []
for cmd in commands:
if '{posargs}' in cmd:
scrubbed.append(cmd.replace('{posargs}', extra_args))
else:
scrubbed.append(cmd)
return scrubbed
def get_prep_commands(self):
ini = self._open_tox_ini()
deps = ""
if ini.has_option('testenv', 'deps'):
deps = ini.get('testenv', 'deps')
deps = deps.replace('{toxinidir}', '/dox').replace('\n', ' ')
if deps.strip() == '':
return []
install_command = "pip install -U"
if ini.has_option('testenv', 'install_command'):
install_command = ini.get('testenv', 'install_command')
install_command = install_command.replace('{opts}', '')
install_command = install_command.replace('{packages}', deps)
return [install_command]
def get_add_files(self):
return [d for d in os.listdir('.') if d.endswith('requirements.txt')]

View File

@ -1,75 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import yaml
import dox.config.base as base
__all__ = [
'get_travis_yaml',
]
_travis_yaml = None
def get_travis_yaml(options):
global _travis_yaml
if _travis_yaml is None:
_travis_yaml = TravisYaml(options)
return _travis_yaml
class TravisYaml(base.ConfigBase):
_yaml = None
_travis_file = 'travis.yml'
def _open_travis_yaml(self):
if self._yaml is None:
with open('travis.yml', 'r') as f:
self._yaml = yaml.load(f)
return self._yaml
def source_name(self):
return self._travis_file
def exists(self):
return os.path.exists(self._travis_file)
def get_commands(self, command):
return self._open_travis_yaml().get('script', command)
def get_prep_commands(self):
travis_yaml = self._open_travis_yaml()
prep = []
for key in ('before_install', 'install', 'before_script'):
if key in travis_yaml:
val = travis_yaml[key]
if hasattr(val, 'append'):
prep.extend(val)
else:
prep.append(val)
return []
# TODO(Shrews): Implement this
def get_add_files(self):
return []
# TODO(Shrews): Implement this
def get_images(self):
return []

View File

@ -1,45 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'get_images',
]
import dox.config.dockerfile
import dox.config.dox_yaml
import dox.config.tox_ini
def get_images(options):
'''Examine the local environment and figure out where we should run.'''
dockerfile = dox.config.dockerfile.get_dockerfile()
dox_yaml = dox.config.dox_yaml.get_dox_yaml(options)
tox_ini = dox.config.tox_ini.get_tox_ini(options)
if dockerfile.exists():
default_images = []
else:
# NOTE(flaper87): We should probably raise
# `RuntimeError` if no image was specified
default_images = ['ubuntu']
images = []
if dox_yaml.exists():
images = dox_yaml.get_images()
elif tox_ini.exists():
images = tox_ini.get_images()
return images or default_images

View File

@ -1,211 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'Runner',
]
import logging
import os
import pwd
import shlex
import shutil
import subprocess
import sys
import tempfile
import textwrap
logger = logging.getLogger(__name__)
class Runner(object):
def __init__(self, args, image_name=None):
image_name = image_name and "_" + image_name or ""
self.args = args
self.project = os.path.basename(os.path.abspath('.'))
self.base_image_name = 'dox/%s%s_base' % (self.project,
image_name)
self.test_image_name = 'dox/%s%s_test' % (self.project,
image_name)
self.user_map = self._get_user_mapping()
self.path_map = self._get_path_mapping()
def _get_user_mapping(self):
"""Get user mapping from command line or current user."""
if self.args.user_map:
username, uid, gid = self.args.user_map.split(':')
else:
username, uid, gid = (pwd.getpwuid(os.getuid())[0],
os.getuid(),
os.getgid())
return {'username': username, 'uid': int(uid), 'gid': int(gid)}
def _get_path_mapping(self):
"""Get path mapping from command line."""
if not self.args.path_map:
return None
local, remote = self.args.path_map.split(':', 1)
return {'local': local, 'remote': remote}
def is_docker_installed(self):
try:
self._docker_cmd("version")
except OSError as e:
msg = 'docker does not seem installed'
if e.errno == 2 and not self.args.debug:
logger.error(msg)
else:
logger.exception(msg)
return False
return True
def _docker_build(self, image, image_dir='.'):
logger.info('Building image %s' % image)
self._docker_cmd('build', '-t', image, image_dir)
def _docker_run(self, *args):
logger.info('Running docker')
self._docker_cmd('run', *args)
def _docker_cmd(self, *args):
base_docker = ['docker']
try:
self._run_shell_command(base_docker + list(args))
except Exception as e:
logger.error("docker failed")
logger.info(e)
raise
def _run_shell_command(self, cmd):
logger.debug('shell: ' + ' '.join(cmd))
if self.args.noop:
return
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
output = process.stdout.read(1)
if output == '' and process.poll() is not None:
break
if output != '' and not self.args.quiet:
sys.stdout.write(output)
sys.stdout.flush()
if process.returncode:
raise Exception(
"%s returned %d" % (cmd, process.returncode))
def _indent(self, text):
wrapper = textwrap.TextWrapper(
initial_indent=' ', subsequent_indent=' ')
return '\n'.join([wrapper.fill(line) for line in text.split('\n')])
def _get_image_list(self):
process = subprocess.Popen(
shlex.split('docker images'),
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = process.communicate()
out_text = stdout.strip().decode('utf-8') if stdout else ""
return dict([f.split()[:2] for f in out_text.split('\n')])
def have_test_image(self):
if self.args.rebuild or self.args.rebuild_all:
return False
if self.test_image_name in self._get_image_list():
return True
return False
def build_test_image(self, image, commands):
logger.debug(
"Want test image %(image)s with %(prep_commands)s" % dict(
image=self.test_image_name,
prep_commands=commands.prep_commands()))
if self.have_test_image():
return
dockerfile = []
dockerfile.append("FROM %s" % image)
try:
tempd = tempfile.mkdtemp()
if not self.user_map['username'] == 'root':
dockerfile.append(
"RUN useradd -M -U -d /src -u %(uid)s %(user)s" % dict(
uid=self.user_map['uid'],
gid=self.user_map['gid'],
user=self.user_map['username']))
for add_file in commands.get_add_files():
shutil.copy(add_file, os.path.join(tempd, add_file))
dockerfile.append("ADD %s /dox/" % add_file)
dockerfile.append("WORKDIR /dox")
for command in commands.prep_commands():
dockerfile.append("RUN %s\n" % command)
dockerfile = '\n'.join(dockerfile)
with open(os.path.join(tempd, 'Dockerfile'), 'w') as f:
f.write(dockerfile)
logger.debug("Dockerfile:\n" + self._indent(dockerfile))
self._docker_build(self.test_image_name, tempd)
finally:
shutil.rmtree(tempd)
def run_commands(self, command):
path = os.path.abspath('.')
if self.path_map:
path = path.replace(self.path_map['local'],
self.path_map['remote'])
docker_args = ['--privileged=true',
'--user=%s' % self.user_map['username'],
'-v', "%s:/src" % path,
'-w', '/src']
if not self.args.keep_image:
docker_args.append('--rm')
docker_args.append(self.test_image_name)
for c in command:
docker_args.append(c)
self._docker_run(*docker_args)
def have_base_image(self):
if self.args.rebuild_all:
return False
if self.base_image_name in self._get_image_list():
return True
return False
def build_base_image(self):
logger.debug("Want base image")
if self.have_base_image():
return
self._docker_build(self.base_image_name)
def run(self, image, command):
logger.debug(
"Going to run %(command)s in %(image)s" % dict(
command=command.test_command(), image=image))
if self.args.rebuild:
logger.debug("Need to rebuild")
if image is None:
self.build_base_image()
self.build_test_image(image, command)
self.run_commands(shlex.split(command.test_command()))

View File

View File

@ -1,69 +0,0 @@
# Copyright 2010-2011 OpenStack Foundation
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import fixtures
import testtools
_TRUE_VALUES = ('true', '1', 'yes')
TESTDIR = os.path.dirname(os.path.abspath(__file__))
SAMPLEDIR = os.path.join(TESTDIR, 'samples')
class TestCase(testtools.TestCase):
"""Test case base class for all unit tests."""
def setUp(self):
"""Run before each test method to initialize test environment."""
super(TestCase, self).setUp()
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
try:
test_timeout = int(test_timeout)
except ValueError:
# If timeout value is invalid do not set a timeout.
test_timeout = 0
if test_timeout > 0:
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
self.useFixture(fixtures.NestedTempfile())
self.useFixture(fixtures.TempHomeDir())
if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES:
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES:
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
self.log_fixture = self.useFixture(fixtures.FakeLogger())
def fake_does_exist(self):
return True
def fake_does_not_exist(self):
return False
def bool_to_fake(val):
if val:
return fake_does_exist
else:
return fake_does_not_exist

View File

@ -1,84 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
test_commands
----------------------------------
Tests for `dox.commands` module.
"""
import fixtures
import testscenarios
from dox import commands
from dox.tests import base
def get_fake_command(value):
def fake_value(self, args):
return value
return fake_value
class TestCommands(base.TestCase):
scenarios = [
('dox_yaml', dict(
dox_yaml=True, tox_ini=False, travis_yaml=False,
dox_value=["testr run"], tox_value=None, travis_value=None,
commands="testr run")),
('dox_yaml_ignore_others', dict(
dox_yaml=True, tox_ini=True, travis_yaml=True,
dox_value=["testr run"], tox_value=["setup.py test"],
travis_value=["gem test"],
commands="testr run")),
('tox_ini', dict(
dox_yaml=False, tox_ini=True, travis_yaml=False,
dox_value=None, tox_value=["setup.py test"], travis_value=None,
commands="setup.py test")),
('travis_yaml', dict(
dox_yaml=False, tox_ini=False, travis_yaml=True,
dox_value=["testr run"], tox_value=None, travis_value=["ruby"],
commands="ruby")),
]
def setUp(self):
super(TestCommands, self).setUp()
self.useFixture(fixtures.MonkeyPatch(
'dox.config.dox_yaml.DoxYaml.exists',
base.bool_to_fake(self.dox_yaml)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.tox_ini.ToxIni.exists',
base.bool_to_fake(self.tox_ini)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.travis_yaml.TravisYaml.exists',
base.bool_to_fake(self.travis_yaml)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.dox_yaml.DoxYaml.get_commands',
get_fake_command(self.dox_value)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.tox_ini.ToxIni.get_commands',
get_fake_command(self.tox_value)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.travis_yaml.TravisYaml.get_commands',
get_fake_command(self.travis_value)))
def test_commands(self):
p = commands.Commands()
self.assertEqual(p.test_command(), self.commands)
def load_tests(loader, in_tests, pattern):
return testscenarios.load_tests_apply_scenarios(loader, in_tests, pattern)

View File

@ -1,62 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import dox.config.base as cfg_base
from dox.config import dox_yaml
from dox.tests import base
class TestDoxYaml(base.TestCase):
def setUp(self):
super(TestDoxYaml, self).setUp()
self.doxyaml = dox_yaml.DoxYaml({})
self.doxyaml.dox_file = os.path.join(base.SAMPLEDIR,
'dox.yaml')
def test_base_class(self):
self.assertIsInstance(self.doxyaml, cfg_base.ConfigBase)
def test_dox_yaml_old_parsing(self):
self.doxyaml = dox_yaml.DoxYaml({})
self.doxyaml.dox_file = os.path.join(base.SAMPLEDIR,
'dox-old.yaml')
for key in self.doxyaml.default_keys_of_section:
self.assertIn(
key, self.doxyaml._open_dox_yaml().keys())
def test_dox_yaml_not_finding_section(self):
self.doxyaml = dox_yaml.DoxYaml({'section': 'foobar'})
self.doxyaml.dox_file = os.path.join(base.SAMPLEDIR,
'dox.yaml')
self.assertRaises(
dox_yaml.DoxYamlSectionNotFound,
self.doxyaml._open_dox_yaml)
def test_dox_yaml_with_default_session(self):
self.doxyaml = dox_yaml.DoxYaml({})
self.doxyaml.dox_file = os.path.join(base.SAMPLEDIR,
'dox.yaml')
for key in self.doxyaml.default_keys_of_section:
self.assertIn(
key, self.doxyaml._open_dox_yaml().keys())
def test_dox_yaml_new_parsing(self):
for key in self.doxyaml.default_keys_of_section:
self.assertIn(
key, self.doxyaml._open_dox_yaml().keys())
# TOOD(chmou): Finish tests of dox_yaml.py

View File

@ -1,65 +0,0 @@
# Author: Chmouel Boudjnah <chmouel@enovance.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import os
import dox.config.base as cfg_base
from dox.config import tox_ini
from dox.tests import base
class TestToxIni(base.TestCase):
def setUp(self):
super(TestToxIni, self).setUp()
self.toxini = tox_ini.ToxIni({})
self.toxini.tox_ini_file = os.path.join(base.SAMPLEDIR,
'tox.ini')
def test_get_tox_ini(self):
tox_ini_new = tox_ini.ToxIni({})
with mock.patch.object(tox_ini, '_tox_ini', tox_ini_new):
self.assertEqual(tox_ini.get_tox_ini({}),
tox_ini_new)
def test_base_class(self):
self.assertIsInstance(self.toxini, cfg_base.ConfigBase)
def test_exists_ini_file(self):
self.assertTrue(self.toxini.exists())
def test_open_tox_ini(self):
self.assertIn('tox', self.toxini._open_tox_ini().sections())
def test_get_images(self):
self.assertEqual(['foo', 'bar'],
self.toxini.get_images())
def test_get_commands(self):
self.toxini = tox_ini.ToxIni({'section': 'testenv2'})
self.toxini.tox_ini_file = os.path.join(base.SAMPLEDIR,
'tox.ini')
self.assertEqual(['foobar -c blah'],
self.toxini.get_commands(
['-c']))
def test_get_prep_commands(self):
cmd = ['pip install -U -r/dox/requirements.txt '
'-r/dox/test-requirements.txt']
self.assertEqual(
self.toxini.get_prep_commands(),
cmd)

View File

@ -1,26 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import dox.config.base as cfg_base
from dox.config import travis_yaml
from dox.tests import base
class TestTravisYaml(base.TestCase):
def setUp(self):
super(TestTravisYaml, self).setUp()
self.travisyaml = travis_yaml.TravisYaml({})
def test_base_class(self):
self.assertIsInstance(self.travisyaml, cfg_base.ConfigBase)

View File

@ -1,9 +0,0 @@
images:
- infra/trusty
add:
- requirements.txt
- test-requirements.txt
prep:
- pip install -U -r requirements.txt -r test-requirements.txt
commands:
- python setup.py testr --slowest

View File

@ -1,21 +0,0 @@
testing:
images:
- infra/trusty
add:
- requirements.txt
- test-requirements.txt
prep:
- pip install -U -r requirements.txt -r test-requirements.txt
commands:
- python setup.py testr --slowest
pep8:
images:
- infra/trusty
add:
- requirements.txt
- test-requirements.txt
prep:
- pip install -U -r requirements.txt -r test-requirements.txt
commands:
- pep8

View File

@ -1,14 +0,0 @@
[tox]
minversion = 1.6
[docker]
images = foo,bar
[testenv]
commands = foobar
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
install_command = pip install -U {opts} {packages}
[testenv2]
commands = foobar {posargs} blah

View File

@ -1,79 +0,0 @@
# Author: Chmouel Boudjnah <chmouel@chmouel.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import mock
import dox.cmd
from dox.tests import base
default_argp = argparse.Namespace(user_map=None, command=None,
environment=None, extra_args=None,
debug=None, noop=True,
images=None, path_map=None)
class TestCmd(base.TestCase):
@mock.patch('dox.runner.Runner.is_docker_installed',
return_value=False)
def test_runner(self, installed_mock):
self.assertRaises(SystemExit, dox.cmd.runner, default_argp)
@mock.patch('dox.cmd.run_dox')
@mock.patch('dox.config.cmdline.CommandLine')
def test_multiple_images_one_command(self, m_cmdline, m_run_dox):
argp = default_argp
argp.images = 'foo, bar'
argp.command = '/bin/true'
dox.cmd.runner(argp)
self.assertTrue(m_cmdline.called)
# silly but i'm not sure how to test that in a proper way
self.assertEqual(['foo', 'bar'],
m_run_dox.call_args_list[0][0][1])
@mock.patch('dox.cmd.run_dox')
@mock.patch('dox.images.get_images')
def test_multiple_environments(self, m_get_images, m_run_dox):
argp = default_argp
argp.environment = 'env1, env2'
dox.cmd.runner(argp)
self.assertEqual(2, m_get_images.call_count)
self.assertEqual(2, m_run_dox.call_count)
@mock.patch('dox.cmd.run_dox')
@mock.patch('dox.images.get_images')
def test_multiple_environments_images(self, m_get_images, m_run_dox):
argp = default_argp
argp.images = 'foo, bar'
argp.environment = 'env1, env2'
dox.cmd.runner(argp)
self.assertEqual(0, m_get_images.call_count)
self.assertEqual(2, m_run_dox.call_count)
@mock.patch('dox.cmd.run_dox')
@mock.patch('dox.images.get_images')
def test_default(self, m_get_images, m_run_dox):
dox.cmd.runner(default_argp)
self.assertEqual('_default',
m_get_images.call_args_list[0][0][0].get('section'))
@mock.patch('dox.runner.Runner')
def test_run_dox(self, m_runner):
dox.cmd.run_dox(default_argp, ['1', '2', '3'], '/bin/echo', "name")
self.assertEqual(1, m_runner.call_count)

View File

@ -1,26 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
test_dox
----------------------------------
Tests for `dox` module.
"""
from dox.tests import base
class TestDox(base.TestCase):
def test_something(self):
pass

View File

@ -1,102 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
test_images
--------------
Tests for `dox.images` module.
"""
import fixtures
import testscenarios
from dox import images
from dox.tests import base
def get_fake_image(value):
if value is not None:
def fake_value(self):
return value
else:
def fake_value(self):
return ['ubuntu']
return fake_value
class TestImages(base.TestCase):
scenarios = [
('have_dockerfile', dict(
dockerfile=True, tox_ini=False, dox_yaml=False,
tox_value=[], dox_value=[], images=[])),
('no_dockerfile', dict(
dockerfile=False, tox_ini=False, dox_yaml=False,
tox_value=[], dox_value=[], images=['ubuntu'])),
('tox_no_docker', dict(
dockerfile=False, tox_ini=True, dox_yaml=False,
tox_value=[], dox_value=[], images=['ubuntu'])),
('tox_docker', dict(
dockerfile=False, tox_ini=True, dox_yaml=False,
tox_value=['tox_docker'], dox_value=[], images=['tox_docker'])),
('dox_image', dict(
dockerfile=False, tox_ini=False, dox_yaml=True,
tox_value=[], dox_value=[], images=['ubuntu'])),
('dox_no_image', dict(
dockerfile=False, tox_ini=False, dox_yaml=True,
tox_value=[], dox_value=['dox_value'], images=['dox_value'])),
('both_dox_wins', dict(
dockerfile=False, tox_ini=True, dox_yaml=True,
tox_value=['tox_wins'], dox_value=['dox_wins'],
images=['dox_wins'])),
('both_no_dox', dict(
dockerfile=False, tox_ini=True, dox_yaml=True,
tox_value=['tox_wins'], dox_value=[], images=['ubuntu'])),
('both_dockerfile_passthru', dict(
dockerfile=True, tox_ini=True, dox_yaml=True,
tox_value=[], dox_value=[], images=[])),
('all_dockerfile_dox_override', dict(
dockerfile=True, tox_ini=True, dox_yaml=True,
tox_value=[], dox_value=['dox_wins'], images=['dox_wins'])),
('all_dockerfile_tox_loses', dict(
dockerfile=True, tox_ini=True, dox_yaml=True,
tox_value=['tox_wins'], dox_value=[], images=[])),
]
def setUp(self):
super(TestImages, self).setUp()
self.useFixture(fixtures.MonkeyPatch(
'dox.config.dockerfile.Dockerfile.exists',
base.bool_to_fake(self.dockerfile)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.dox_yaml.DoxYaml.exists',
base.bool_to_fake(self.dox_yaml)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.tox_ini.ToxIni.exists',
base.bool_to_fake(self.tox_ini)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.dox_yaml.DoxYaml.get_images',
get_fake_image(self.dox_value)))
self.useFixture(fixtures.MonkeyPatch(
'dox.config.tox_ini.ToxIni.get_images',
get_fake_image(self.tox_value)))
def test_images(self):
image = images.get_images({})
self.assertEqual(image, self.images)
def load_tests(loader, in_tests, pattern):
return testscenarios.load_tests_apply_scenarios(loader, in_tests, pattern)

View File

@ -1,232 +0,0 @@
# Author: Chmouel Boudjnah <chmouel@enovance.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import os
import shutil # noqa
import tempfile
import mock
import dox.runner as doxrunner
from dox.tests import base
class FakeCommands(object):
def __init__(self, commands=None, files_to_add=None):
self.commands = commands or ["command1", "command2"]
self.files_to_add = files_to_add or ["file1"]
def prep_commands(self):
return self.commands
def get_add_files(self):
return self.files_to_add
class TestRunner(base.TestCase):
def setUp(self):
super(TestRunner, self).setUp()
def test_user_mapping(self):
dr = doxrunner.Runner(argparse.Namespace(user_map='foo:100:10',
path_map=None))
self.assertEqual('foo', dr.user_map['username'])
self.assertEqual(100, dr.user_map['uid'])
self.assertEqual(10, dr.user_map['gid'])
@mock.patch('os.getuid', return_value=12345)
@mock.patch('os.getgid', return_value=67890)
@mock.patch('pwd.getpwuid', return_value=['toto'])
def test_user_mapping_default(self, os_uid, os_gid, os_username):
dr = doxrunner.Runner(argparse.Namespace(user_map=None,
path_map=None))
self.assertEqual('toto', dr.user_map['username'])
self.assertEqual(12345, dr.user_map['uid'])
self.assertEqual(67890, dr.user_map['gid'])
def test_path_mapping(self):
dr = doxrunner.Runner(argparse.Namespace(path_map='/Users:/home',
user_map=None))
self.assertEqual('/Users', dr.path_map['local'])
self.assertEqual('/home', dr.path_map['remote'])
def test_path_mapping_extra_colon(self):
dr = doxrunner.Runner(argparse.Namespace(path_map='/Users:/home:foo',
user_map=None))
self.assertEqual('/Users', dr.path_map['local'])
self.assertEqual('/home:foo', dr.path_map['remote'])
def test_path_mapping_default(self):
dr = doxrunner.Runner(argparse.Namespace(path_map=None,
user_map=None))
self.assertIsNone(dr.path_map)
def test_is_docker_installed(self):
dr = doxrunner.Runner(argparse.Namespace(
path_map=None,
user_map=None))
def mydocker_cmd(dr, *args):
raise OSError
dr._docker_cmd = mydocker_cmd
self.assertFalse(dr.is_docker_installed())
def mydocker_cmd(dr, *args):
return True
dr._docker_cmd = mydocker_cmd
self.assertTrue(dr.is_docker_installed())
def test_docker_cmd(self):
dr = doxrunner.Runner(argparse.Namespace(user_map=None,
path_map=None,
debug=False))
dr._run_shell_command = mock.MagicMock()
dr._docker_cmd("version")
dr._run_shell_command.assert_called_with(
['docker', 'version']
)
dr = doxrunner.Runner(argparse.Namespace(user_map=None,
path_map=None,
debug=True))
dr._run_shell_command = mock.MagicMock()
dr._docker_cmd("version")
dr._run_shell_command.assert_called_with(
['docker', 'version']
)
dr = doxrunner.Runner(argparse.Namespace(user_map=None,
path_map=None,
debug=True))
dr._run_shell_command = mock.Mock()
dr._run_shell_command.side_effect = OSError("Boom")
self.assertRaises(OSError, dr._docker_cmd, "version")
def test_build_images_pass(self):
dr = doxrunner.Runner(argparse.Namespace(path_map=None,
user_map=None))
dr.have_test_image = mock.Mock()
dr.return_value = True
self.assertIsNone(dr.build_test_image("image", FakeCommands()))
@mock.patch.multiple("shutil", rmtree=mock.DEFAULT,
copy=mock.DEFAULT)
def test_build_images(self, rmtree, copy):
my_temp_file = tempfile.mkdtemp()
docker_written = os.path.join(my_temp_file, "Dockerfile")
fk = FakeCommands(["toto1", "toto2"],
["blah3", "blah4"])
dr = doxrunner.Runner(argparse.Namespace(
quiet=False, noop=False,
rebuild=True, debug=True,
path_map=None,
user_map=None))
m_docker_build = dr._docker_build = mock.Mock()
with mock.patch.object(tempfile, "mkdtemp", return_value=my_temp_file):
dr.build_test_image("myimage", fk)
m_docker_build.assert_called_once_with(
dr.test_image_name, my_temp_file)
# Only the last one
copy.assert_called_with('blah4',
os.path.join(my_temp_file, "blah4"))
self.assertTrue(copy.called)
self.assertTrue(rmtree.called)
self.assertTrue(os.path.exists(docker_written))
um = dr.user_map
expected = """FROM %s
RUN useradd -M -U -d /src -u %s %s
ADD blah3 /dox/
ADD blah4 /dox/
WORKDIR /dox
RUN toto1
RUN toto2
""""" % ("myimage", um['uid'], um['username'])
self.assertEqual(expected, open(docker_written, 'r').read())
def test_have_base_image(self):
dr = doxrunner.Runner(argparse.Namespace(
rebuild=True,
rebuild_all=False,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
self.assertFalse(dr.have_base_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=True,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
self.assertFalse(dr.have_base_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=False,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
dr._get_image_list.return_value = [dr.base_image_name]
self.assertTrue(dr.have_base_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=False,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
dr._get_image_list.return_value = []
self.assertFalse(dr.have_base_image())
def test_have_test_image(self):
# NOTE(chmou): this probably would need some refactoring with
# have_base_image
dr = doxrunner.Runner(argparse.Namespace(
rebuild=True,
rebuild_all=False,
path_map=None,
user_map=None))
self.assertFalse(dr.have_test_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=True,
path_map=None,
user_map=None))
self.assertFalse(dr.have_test_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=False,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
dr._get_image_list.return_value = [dr.test_image_name]
self.assertTrue(dr.have_test_image())
dr = doxrunner.Runner(argparse.Namespace(
rebuild=False,
rebuild_all=False,
path_map=None,
user_map=None))
dr._get_image_list = mock.MagicMock()
dr._get_image_list.return_value = []
self.assertFalse(dr.have_test_image())

View File

@ -1,4 +0,0 @@
pbr>=0.5.21,<1.0
PyYAML
six

View File

@ -1,46 +0,0 @@
[metadata]
name = dox
summary = dox runs tox descriptions in docker containers
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 2.6
Programming Language :: Python :: 3
Programming Language :: Python :: 3.3
[entry_points]
console_scripts =
dox = dox.cmd:main
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
[upload_sphinx]
upload-dir = doc/build/html
[compile_catalog]
directory = dox/locale
domain = dox
[update_catalog]
domain = dox
output_dir = dox/locale
input_file = dox/locale/dox.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = dox/locale/dox.pot

View File

@ -1,22 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
setuptools.setup(
setup_requires=['pbr'],
pbr=True)

View File

@ -1,12 +0,0 @@
hacking>=0.5.6,<0.8
coverage>=3.6
discover
fixtures>=0.3.14
python-subunit
sphinx>=1.1.2
oslo.sphinx
testrepository>=0.0.17
testscenarios>=0.4,<0.5
testtools>=0.9.32
mock

View File

@ -1,38 +0,0 @@
#!/bin/bash -ex
# Copyright 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
GROUP=docker
if [ $(id -gn) != ${GROUP} ]; then
exec sg ${GROUP} "$0 $*"
fi
### Build image with docker
IMAGES="infra/centos7 infra/trusty infra/xenial"
for IMAGE in $IMAGES; do
docker build dockerfiles/$IMAGE -t $IMAGE
done
docker images
# NOTE(pabelanger): Make sure we hash by ZUUL_COMMIT, so we know which tarball
# to download from secure worker.
DIST=$WORKSPACE/dist/$ZUUL_COMMIT
mkdir -p $DIST
### Save docker image for upload to tarballs.o.o
FILENAME=images.tar.gz
docker save $IMAGES | gzip -9 > $DIST/$FILENAME
shasum $DIST/$FILENAME > $DIST/$FILENAME.sha256

View File

@ -1,18 +0,0 @@
#!/bin/bash -ex
# Copyright 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
sudo gpasswd -a ${USER} docker
sudo service docker restart

33
tox.ini
View File

@ -1,33 +0,0 @@
[tox]
minversion = 1.6
envlist = py27,py33,pep8
skipsdist = True
[testenv]
usedevelop = True
install_command = pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LC_ALL=C
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = python setup.py testr --slowest --testr-args='{posargs}'
[testenv:pep8]
commands = flake8
[testenv:venv]
commands = {posargs}
[testenv:cover]
commands = python setup.py testr --coverage --testr-args='{posargs}'
[flake8]
show-source = True
builtins = _
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
[docker]
images = infra/trusty