Improve config handling

Many projects need a specific config object (usually the global one)
populated for project code that relies on it. Additionally, we want
to make the code used to initialize the object overrideable so projects
can use their existing code for that. The primary benefit is that
project code has sane defaults for config file locations so in many
cases it won't be necessary to explicitly specify the location. A
very simple default implementation is also provided so the module
still works out of the box too.

Change-Id: If8ce7202bd73793688a0446f069bb4e03547c99e
This commit is contained in:
Ben Nemec 2018-09-21 15:51:56 +00:00 committed by Doug Hellmann
parent 86fd6838c2
commit a2c3f8b81d
4 changed files with 25 additions and 9 deletions

View File

@ -29,15 +29,18 @@ oslo.upgradecheck also includes a basic implementation of command line argument
handling that can be used to provide the minimum processing needed to implement
a ``$SERVICE-status upgrade check`` command. To make use of it, write a method
that creates an instance of the class created above, then pass that class's
``check`` method into :func:`oslo_upgradecheck.upgradecheck.main`. For
example::
``check`` function into :func:`oslo_upgradecheck.upgradecheck.main`. The
project's ConfigOpts instance must also be passed. In most projects this will
just be cfg.CONF. For example::
from oslo_config import cfg
def main():
inst = ProjectSpecificUpgradeCommands()
return upgradecheck.main(inst.check)
return upgradecheck.main(cfg.CONF, inst.check)
The entry point for the ``$SERVICE-status`` command should then point at this
method.
function.
Alternatively, if a project has its own CLI code that it would prefer to reuse,
it simply needs to ensure that the ``inst.check`` method is called when the

View File

@ -16,6 +16,7 @@
import sys
from oslo_config import cfg
from oslo_upgradecheck import upgradecheck
@ -34,7 +35,7 @@ class Checks(upgradecheck.UpgradeCommands):
def main():
inst = Checks()
return upgradecheck.main(inst.check)
return upgradecheck.main(cfg.CONF, inst.check)
if __name__ == '__main__':

View File

@ -22,6 +22,7 @@ Tests for `upgradecheck` module.
import sys
import mock
from oslo_config import cfg
from oslotest import base
from oslo_upgradecheck import upgradecheck
@ -73,8 +74,9 @@ class TestUpgradeCommands(base.BaseTestCase):
class TestMain(base.BaseTestCase):
def _run_test(self, func, expected):
mock_argv = ['test-status', 'upgrade', 'check']
conf = cfg.ConfigOpts()
with mock.patch.object(sys, 'argv', mock_argv, create=True):
result = upgradecheck.main(func)
result = upgradecheck.main(conf, func)
self.assertEqual(expected, result)
def test_main(self):

View File

@ -139,21 +139,31 @@ def _add_parsers(subparsers, check_callback):
upgrade_action.set_defaults(action_fn=check_callback)
def main(check_callback):
def _init_config(conf):
conf(sys.argv[1:])
def main(conf, check_callback, config_callback=_init_config):
"""Simple implementation of main for upgrade checks
This can be used in upgrade check commands to provide the minimum
necessary parameter handling and logic.
:param conf: An oslo.confg ConfigOpts instance on which to register the
upgrade check arguments.
:param check_callback: The check function from the concrete implementation
of UpgradeCommands.
:param config_callback: A function that initializes the conf object.
It must take a single argument that is the conf
object to be initialized. The default
implementation simply runs
conf(sys.argv[1:])
"""
add_parsers = functools.partial(_add_parsers,
check_callback=check_callback)
opt = cfg.SubCommandOpt('category', handler=add_parsers)
conf = cfg.ConfigOpts()
conf.register_cli_opt(opt)
conf(sys.argv[1:])
config_callback(conf)
try:
return conf.category.action_fn()