From 0d5f1249b3922e2cd19dc8b763cea1fa3cb6b67d Mon Sep 17 00:00:00 2001 From: Andrew Schoen Date: Fri, 21 Nov 2014 11:58:58 -0600 Subject: [PATCH] Adds a FakeNamespace object to teuthology.config that mimics what an argparse Namespace looks like when teuthology.misc.read_config is used on it. This allows us to refactor our commands to use docopt but still all all the tasks to be passed one big namespace. Signed-off-by: Andrew Schoen --- teuthology/config.py | 52 ++++++++++++++++++++++++++++++---- teuthology/test/test_config.py | 45 +++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/teuthology/config.py b/teuthology/config.py index e61c4ac5e7..54c28513f4 100644 --- a/teuthology/config.py +++ b/teuthology/config.py @@ -127,9 +127,49 @@ class JobConfig(YamlConfig): pass -system_config_path = '/etc/teuthology.yaml' -if not os.path.exists(TeuthologyConfig.yaml_path) and \ - os.path.exists(system_config_path): - config = TeuthologyConfig(yaml_path=system_config_path) -else: - config = TeuthologyConfig() +class FakeNamespace(YamlConfig): + """ This class is meant to behave like a argparse Namespace with an attached + teuthology config at the teuthology_config property. It mimics the old + way of doing things with argparse and teuthology.misc.read_config. + + We'll use this as a stop-gap as we refactor commands but allow the tasks + to still be passed a single namespace object for the time being. + """ + def __init__(self, config_dict=None, yaml_path=None): + if not yaml_path: + yaml_path = _get_config_path() + if not config_dict: + config_dict = dict() + # teuthology.misc.read_config attaches the teuthology config + # to a teuthology_config attribute of the argparse Namespace + config_dict["teuthology_config"] = TeuthologyConfig(yaml_path) + self._conf = self._clean_config(config_dict) + + def _clean_config(self, config_dict): + """ Makes sure that the keys of config_dict are able to be used. For example + the "--" prefix of a docopt dict isn't valid and won't populate correctly. + """ + result = dict() + for key, value in config_dict.iteritems(): + new_key = key + if new_key.startswith("--"): + new_key = new_key[2:] + elif new_key.startswith("<") and new_key.endswith(">"): + new_key = new_key[1:-1] + + if "-" in new_key: + new_key = new_key.replace("-", "_") + + result[new_key] = value + + return result + + +def _get_config_path(): + system_config_path = '/etc/teuthology.yaml' + if not os.path.exists(TeuthologyConfig.yaml_path) and \ + os.path.exists(system_config_path): + return system_config_path + return TeuthologyConfig.yaml_path + +config = TeuthologyConfig(yaml_path=_get_config_path()) diff --git a/teuthology/test/test_config.py b/teuthology/test/test_config.py index 3e57346bd0..7d33f97317 100644 --- a/teuthology/test/test_config.py +++ b/teuthology/test/test_config.py @@ -86,3 +86,48 @@ class TestTeuthologyConfig(TestYamlConfig): class TestJobConfig(TestYamlConfig): def setup(self): self.test_class = config.JobConfig + + +class TestFakeNamespace(TestYamlConfig): + def setup(self): + self.test_class = config.FakeNamespace + + def test_docopt_dict(self): + """ Tests if a dict in the format that docopt returns can + be parsed correctly. + """ + d = { + "--verbose": True, + "--an-option": "some_option", + "": "the_arg", + "something": "some_thing", + } + conf_obj = self.test_class(d) + assert conf_obj.verbose + assert conf_obj.an_option == "some_option" + assert conf_obj.an_arg == "the_arg" + assert conf_obj.something == "some_thing" + + def test_config(self): + """ Tests that a teuthology_config property is automatically added + and that defaults are properly used. However, we won't check all + the defaults. + """ + conf_obj = self.test_class(dict()) + assert conf_obj.teuthology_config + assert conf_obj.teuthology_config.archive_base + assert not conf_obj.teuthology_config.automated_scheduling + assert conf_obj.teuthology_config.ceph_git_base_url == 'https://github.com/ceph/' + + def test_update(self): + """ + This is slightly different thank TestYamlConfig.update() in that it + only tests what was updated - since to_dict() yields all values, + including defaults. + """ + conf_obj = self.test_class(dict()) + conf_obj.foo = 'foo' + conf_obj.bar = 'bar' + conf_obj.update(dict(bar='baz')) + assert conf_obj.foo == 'foo' + assert conf_obj.bar == 'baz' -- 2.39.5