Merge "Check restart and auto_remove are setted for per container"

This commit is contained in:
Zuul 2018-05-02 06:47:18 +00:00 committed by Gerrit Code Review
commit c36a9f7a00
4 changed files with 105 additions and 49 deletions

View File

@ -18,6 +18,7 @@
from __future__ import print_function
import collections
import getpass
import inspect
import os
@ -90,6 +91,15 @@ def arg(*args, **kwargs):
return _decorator
def exclusive_arg(group_name, *args, **kwargs):
"""Decorator for CLI mutually exclusive args."""
def _decorator(func):
required = kwargs.pop('required', None)
add_exclusive_arg(func, group_name, required, *args, **kwargs)
return func
return _decorator
def env(*args, **kwargs):
"""Returns the first environment variable set.
@ -116,6 +126,24 @@ def add_arg(func, *args, **kwargs):
func.arguments.insert(0, (args, kwargs))
def add_exclusive_arg(func, group_name, required, *args, **kwargs):
"""Bind CLI mutally exclusive arguments to a shell.py `do_foo` function."""
if not hasattr(func, 'exclusive_args'):
func.exclusive_args = collections.defaultdict(list)
# Default required to False
func.exclusive_args['__required__'] = collections.defaultdict(bool)
# NOTE(sirp): avoid dups that can occur when the module is shared across
# tests.
if (args, kwargs) not in func.exclusive_args[group_name]:
# Because of the semantics of decorator composition if we just append
# to the options list positional options will appear to be backwards.
func.exclusive_args[group_name].insert(0, (args, kwargs))
if required is not None:
func.exclusive_args['__required__'][group_name] = required
def unauthenticated(func):
"""Adds 'unauthenticated' attribute to decorated function.

View File

@ -87,11 +87,18 @@ class CreateContainer(command.ShowOne):
'already exist on the node. '
'"always": Always pull the image from repository.'
'"never": never pull the image')
parser.add_argument(
restart_auto_remove_args = parser.add_mutually_exclusive_group()
restart_auto_remove_args.add_argument(
'--restart',
metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
restart_auto_remove_args.add_argument(
'--auto-remove',
dest='auto_remove',
action='store_true',
default=False,
help='Automatically remove the container when it exits')
parser.add_argument(
'--image-driver',
metavar='<image_driver>',
@ -142,12 +149,6 @@ class CreateContainer(command.ShowOne):
metavar='<mount>',
help='A dictionary to configure volumes mounted inside the '
'container.')
parser.add_argument(
'--auto-remove',
dest='auto_remove',
action='store_true',
default=False,
help='Automatically remove the container when it exits')
parser.add_argument(
'--runtime',
metavar='<runtime>',
@ -705,11 +706,18 @@ class RunContainer(command.ShowOne):
'already exist on the node. '
'"always": Always pull the image from repository.'
'"never": never pull the image')
parser.add_argument(
restart_auto_remove_args = parser.add_mutually_exclusive_group()
restart_auto_remove_args.add_argument(
'--restart',
metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
restart_auto_remove_args.add_argument(
'--auto-remove',
dest='auto_remove',
action='store_true',
default=False,
help='Automatically remove the container when it exits')
parser.add_argument(
'--image-driver',
metavar='<image_driver>',
@ -760,12 +768,6 @@ class RunContainer(command.ShowOne):
metavar='<mount>',
help='A dictionary to configure volumes mounted inside the '
'container.')
parser.add_argument(
'--auto-remove',
dest='auto_remove',
action='store_true',
default=False,
help='Automatically remove the container when it exits')
parser.add_argument(
'--runtime',
metavar='<runtime>',

View File

@ -429,6 +429,7 @@ class OpenStackZunShell(object):
continue
action_help = desc.strip()
exclusive_args = getattr(callback, 'exclusive_args', {})
arguments = getattr(callback, 'arguments', [])
subparser = (
@ -443,29 +444,46 @@ class OpenStackZunShell(object):
help=argparse.SUPPRESS,)
self.subcommands[command] = subparser
for (args, kwargs) in arguments:
start_version = kwargs.get("start_version", None)
if start_version:
start_version = api_versions.APIVersion(start_version)
end_version = kwargs.get("end_version", None)
if end_version:
end_version = api_versions.APIVersion(end_version)
else:
end_version = api_versions.APIVersion(
"%s.latest" % start_version.ver_major)
if do_help:
kwargs["help"] = kwargs.get("help", "") + (msg % {
"start": start_version.get_string(),
"end": end_version.get_string()})
else:
if not version.matches(start_version, end_version):
continue
kw = kwargs.copy()
kw.pop("start_version", None)
kw.pop("end_version", None)
subparser.add_argument(*args, **kwargs)
self._add_subparser_args(subparser, arguments, version, do_help,
msg)
self._add_subparser_exclusive_args(subparser, exclusive_args,
version, do_help, msg)
subparser.set_defaults(func=callback)
def _add_subparser_exclusive_args(self, subparser, exclusive_args,
version, do_help, msg):
for group_name, arguments in exclusive_args.items():
if group_name == '__required__':
continue
required = exclusive_args['__required__'][group_name]
exclusive_group = subparser.add_mutually_exclusive_group(
required=required)
self._add_subparser_args(exclusive_group, arguments,
version, do_help, msg)
def _add_subparser_args(self, subparser, arguments, version, do_help, msg):
for (args, kwargs) in arguments:
start_version = kwargs.get("start_version", None)
if start_version:
start_version = api_versions.APIVersion(start_version)
end_version = kwargs.get("end_version", None)
if end_version:
end_version = api_versions.APIVersion(end_version)
else:
end_version = api_versions.APIVersion(
"%s.latest" % start_version.ver_major)
if do_help:
kwargs["help"] = kwargs.get("help", "") + (msg % {
"start": start_version.get_string(),
"end": end_version.get_string()})
else:
if not version.matches(start_version, end_version):
continue
kw = kwargs.copy()
kw.pop("start_version", None)
kw.pop("end_version", None)
subparser.add_argument(*args, **kwargs)
def setup_debugging(self, debug):
if debug:
streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s"

View File

@ -39,6 +39,17 @@ def _show_container(container):
utils.print_dict(container._info)
@utils.exclusive_arg(
'restart_auto_remove',
'--auto-remove',
required=False, action='store_true',
help='Automatically remove the container when it exits')
@utils.exclusive_arg(
'restart_auto_remove',
'--restart',
required=False, metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
@utils.arg('-n', '--name',
metavar='<name>',
help='name of the container')
@ -55,9 +66,6 @@ def _show_container(container):
@utils.arg('--workdir',
metavar='<workdir>',
help='The working directory for commands to run in')
@utils.arg('--auto-remove',
action='store_true',
help='Automatically remove the container when it exits')
@utils.arg('--label',
metavar='<KEY=VALUE>',
action='append', default=[],
@ -75,10 +83,6 @@ def _show_container(container):
'"always": Always pull the image from repository.'
'"never": never pull the image')
@utils.arg('image', metavar='<image>', help='name or ID of the image')
@utils.arg('--restart',
metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
@utils.arg('-i', '--interactive',
dest='interactive',
action='store_true',
@ -523,6 +527,17 @@ def do_kill(cs, args):
{'container': container, 'e': e})
@utils.exclusive_arg(
'restart_auto_remove',
'--auto-remove',
required=False, action='store_true',
help='Automatically remove the container when it exits')
@utils.exclusive_arg(
'restart_auto_remove',
'--restart',
required=False, metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
@utils.arg('-n', '--name',
metavar='<name>',
help='name of the container')
@ -539,9 +554,6 @@ def do_kill(cs, args):
@utils.arg('--workdir',
metavar='<workdir>',
help='The working directory for commands to run in')
@utils.arg('--auto-remove',
action='store_true',
help='Automatically remove the container when it exits')
@utils.arg('--label',
metavar='<KEY=VALUE>',
action='append', default=[],
@ -559,10 +571,6 @@ def do_kill(cs, args):
'"always": Always pull the image from repository.'
'"never": never pull the image')
@utils.arg('image', metavar='<image>', help='name or ID of the image')
@utils.arg('--restart',
metavar='<restart>',
help='Restart policy to apply when a container exits'
'(no, on-failure[:max-retry], always, unless-stopped)')
@utils.arg('-i', '--interactive',
dest='interactive',
action='store_true',