diff --git a/dox.yml b/dox.yml index c5a14c6..48f7b03 100644 --- a/dox.yml +++ b/dox.yml @@ -1,9 +1,22 @@ -images: +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 + 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 + +pep8: + images: + - infra/trusty + add: + - requirements.txt + - test-requirements.txt + prep: + - pip install -U -r requirements.txt -r test-requirements.txt + commands: + - flake8 diff --git a/dox/cmd.py b/dox/cmd.py index 11bc05f..d32f6d3 100644 --- a/dox/cmd.py +++ b/dox/cmd.py @@ -51,6 +51,9 @@ def parse_args(): ' 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') @@ -93,9 +96,11 @@ def run_dox(args): if not dox.runner.Runner(args).is_docker_installed(): sys.exit(1) + options = {'section': args.environment} + # Get Image if args.images is None: - images = dox.images.get_images() + images = dox.images.get_images(options) else: images = args.images.split(',') @@ -104,9 +109,8 @@ def run_dox(args): command = dox.config.cmdline.CommandLine(args.extra_args) logger.debug("Command source is the command line") else: - command = dox.commands.Commands(args.extra_args) + command = dox.commands.Commands(args.extra_args, options) logger.debug("Command source is %s" % command.source.source_name()) - # Run try: run = functools.partial(dox.runner.Runner(args).run, diff --git a/dox/commands.py b/dox/commands.py index 54846f8..0fe767f 100644 --- a/dox/commands.py +++ b/dox/commands.py @@ -28,12 +28,12 @@ import dox.config.travis_yaml logger = logging.getLogger(__name__) -def get_commands(): +def get_commands(options): '''Examine the local environment and figure out what we should run.''' - dox_yaml = dox.config.dox_yaml.get_dox_yaml() - tox_ini = dox.config.tox_ini.get_tox_ini() - travis_yaml = dox.config.travis_yaml.get_travis_yaml() + 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(): @@ -43,8 +43,9 @@ def get_commands(): class Commands(object): - def __init__(self, extra_args=[]): - self.source = get_commands() + def __init__(self, extra_args=[], options=None): + self.options = options or {} + self.source = get_commands(options) self.args = [] self.extra_args = extra_args @@ -79,7 +80,6 @@ class Commands(object): on the docker command line. """ commands = self.source.get_commands(self.extra_args) - if len(commands) > 1: return self._test_command_as_script(commands) diff --git a/dox/config/base.py b/dox/config/base.py index f575744..ab8b994 100644 --- a/dox/config/base.py +++ b/dox/config/base.py @@ -21,6 +21,9 @@ import six 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. diff --git a/dox/config/dox_yaml.py b/dox/config/dox_yaml.py index e66c753..96edb9f 100644 --- a/dox/config/dox_yaml.py +++ b/dox/config/dox_yaml.py @@ -26,29 +26,54 @@ __all__ = [ _dox_yaml = None -def get_dox_yaml(): +class DoxYamlSectionNotFound(Exception): + pass + + +def get_dox_yaml(options): global _dox_yaml if _dox_yaml is None: - _dox_yaml = DoxYaml() + _dox_yaml = DoxYaml(options) return _dox_yaml class DoxYaml(base.ConfigBase): _yaml = None - _dox_file = 'dox.yml' + dox_file = 'dox.yml' + default_section = 'testing' + default_keys_of_section = ['images', 'commands', 'add', 'prep'] + + def get_section(self, yaml, 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 yaml.get(self.default_section) + raise DoxYamlSectionNotFound("You need to specify a section.") + elif section not in yaml.keys(): + raise DoxYamlSectionNotFound(section) + elif section: + return yaml.get(section) def _open_dox_yaml(self): if self._yaml is None: - with open('dox.yml', 'r') as f: + with open(self.dox_file, 'r') as f: self._yaml = yaml.load(f) - return self._yaml + return self.get_section(self._yaml, + self.options.get('section')) def source_name(self): - return self._dox_file + return self.dox_file def exists(self): - return os.path.exists(self._dox_file) + return os.path.exists(self.dox_file) def get_images(self): return self._open_dox_yaml().get('images', []) diff --git a/dox/config/tox_ini.py b/dox/config/tox_ini.py index c78125b..a9d0a06 100644 --- a/dox/config/tox_ini.py +++ b/dox/config/tox_ini.py @@ -28,10 +28,10 @@ __all__ = [ _tox_ini = None -def get_tox_ini(): +def get_tox_ini(options): global _tox_ini if _tox_ini is None: - _tox_ini = ToxIni() + _tox_ini = ToxIni(options) return _tox_ini @@ -39,6 +39,7 @@ class ToxIni(base.ConfigBase): _ini = None tox_ini_file = 'tox.ini' + default_section = 'testenv' def _open_tox_ini(self): if self._ini is None: @@ -57,12 +58,14 @@ class ToxIni(base.ConfigBase): if ini.has_option('docker', 'images'): return ini.get('docker', 'images').split(',') - def get_commands(self, extra_args, section='testenv'): + 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) ini = self._open_tox_ini() commands = ini.get(section, 'commands').split("\n") extra_args = " ".join(extra_args) diff --git a/dox/config/travis_yaml.py b/dox/config/travis_yaml.py index dd372a6..9d24662 100644 --- a/dox/config/travis_yaml.py +++ b/dox/config/travis_yaml.py @@ -26,10 +26,10 @@ __all__ = [ _travis_yaml = None -def get_travis_yaml(): +def get_travis_yaml(options): global _travis_yaml if _travis_yaml is None: - _travis_yaml = TravisYaml() + _travis_yaml = TravisYaml(options) return _travis_yaml diff --git a/dox/images.py b/dox/images.py index 7ce2909..03a1bf0 100644 --- a/dox/images.py +++ b/dox/images.py @@ -22,12 +22,12 @@ import dox.config.dox_yaml import dox.config.tox_ini -def get_images(): +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() - tox_ini = dox.config.tox_ini.get_tox_ini() + 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 = [] diff --git a/dox/runner.py b/dox/runner.py index d5f067b..0a5eba2 100644 --- a/dox/runner.py +++ b/dox/runner.py @@ -134,7 +134,6 @@ class Runner(object): 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, diff --git a/dox/tests/config/test_dox_yaml.py b/dox/tests/config/test_dox_yaml.py index 3055ca0..4cc7f86 100644 --- a/dox/tests/config/test_dox_yaml.py +++ b/dox/tests/config/test_dox_yaml.py @@ -12,6 +12,8 @@ # 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 @@ -22,7 +24,41 @@ class TestDoxYaml(base.TestCase): def setUp(self): super(TestDoxYaml, self).setUp() - self.doxyaml = dox_yaml.DoxYaml() + 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 diff --git a/dox/tests/config/test_tox_ini.py b/dox/tests/config/test_tox_ini.py index 2bd7168..acc2aa2 100644 --- a/dox/tests/config/test_tox_ini.py +++ b/dox/tests/config/test_tox_ini.py @@ -27,14 +27,14 @@ class TestToxIni(base.TestCase): def setUp(self): super(TestToxIni, self).setUp() - self.toxini = tox_ini.ToxIni() + 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() + tox_ini_new = tox_ini.ToxIni({}) with mock.patch.object(tox_ini, '_tox_ini', tox_ini_new): - self.assertEqual(tox_ini.get_tox_ini(), + self.assertEqual(tox_ini.get_tox_ini({}), tox_ini_new) def test_base_class(self): @@ -51,9 +51,12 @@ class TestToxIni(base.TestCase): 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'], section='testenv2')) + ['-c'])) def test_get_prep_commands(self): cmd = ['pip install -U -r/dox/requirements.txt ' diff --git a/dox/tests/config/test_travis_yaml.py b/dox/tests/config/test_travis_yaml.py index 65749dd..932f067 100644 --- a/dox/tests/config/test_travis_yaml.py +++ b/dox/tests/config/test_travis_yaml.py @@ -22,7 +22,7 @@ class TestTravisYaml(base.TestCase): def setUp(self): super(TestTravisYaml, self).setUp() - self.travisyaml = travis_yaml.TravisYaml() + self.travisyaml = travis_yaml.TravisYaml({}) def test_base_class(self): self.assertIsInstance(self.travisyaml, cfg_base.ConfigBase) diff --git a/dox/tests/samples/dox-old.yaml b/dox/tests/samples/dox-old.yaml new file mode 100644 index 0000000..076ec28 --- /dev/null +++ b/dox/tests/samples/dox-old.yaml @@ -0,0 +1,9 @@ +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 diff --git a/dox/tests/samples/dox.yaml b/dox/tests/samples/dox.yaml new file mode 100644 index 0000000..eea1702 --- /dev/null +++ b/dox/tests/samples/dox.yaml @@ -0,0 +1,21 @@ +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 diff --git a/dox/tests/test_images.py b/dox/tests/test_images.py index 10dd9e3..dce18c0 100644 --- a/dox/tests/test_images.py +++ b/dox/tests/test_images.py @@ -96,7 +96,7 @@ class TestImages(base.TestCase): get_fake_image(self.tox_value))) def test_images(self): - image = images.get_images() + image = images.get_images({}) self.assertEqual(image, self.images)