diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2018-12-07 08:31:55 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-07 08:31:55 -0800 |
commit | d266460f7bdd8d49835c8228fe16706915f92796 (patch) | |
tree | eb6c2fc7d22912cb2a28cf20a61495ef3f83c77e | |
parent | 49d9a8f9518dd3d38219f5ead6782d4919433cfc (diff) | |
parent | c60489da47228234fd526cd67d065f9a28aafcb8 (diff) | |
download | podman-d266460f7bdd8d49835c8228fe16706915f92796.tar.gz podman-d266460f7bdd8d49835c8228fe16706915f92796.tar.bz2 podman-d266460f7bdd8d49835c8228fe16706915f92796.zip |
Merge pull request #1893 from jwhonce/bug/1869
Refactor CLI booleans to be consistent and defined behavior
32 files changed, 201 insertions, 257 deletions
diff --git a/contrib/python/podman/Makefile b/contrib/python/podman/Makefile index 11a7568d1..0cbfe2fb3 100644 --- a/contrib/python/podman/Makefile +++ b/contrib/python/podman/Makefile @@ -1,6 +1,6 @@ PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python) DESTDIR ?= / -PODMAN_VERSION ?= '0.0.4' +PODMAN_VERSION ?= '0.11.1.1' .PHONY: python-podman python-podman: @@ -22,8 +22,8 @@ install: .PHONY: upload upload: - $(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel - twine upload --repository-url https://test.pypi.org/legacy/ dist/* + PODMAN_VERSION=$(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel + twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/* .PHONY: clobber clobber: uninstall clean diff --git a/contrib/python/pypodman/Makefile b/contrib/python/pypodman/Makefile index 272145c5d..230eee44d 100644 --- a/contrib/python/pypodman/Makefile +++ b/contrib/python/pypodman/Makefile @@ -1,6 +1,6 @@ PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python) DESTDIR := / -PODMAN_VERSION ?= '0.0.4' +PODMAN_VERSION ?= '0.11.1.1' .PHONY: python-pypodman python-pypodman: @@ -22,7 +22,7 @@ install: .PHONY: upload upload: - $(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel + PODMAN_VERSION=$(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel twine upload --repository-url https://test.pypi.org/legacy/ dist/* .PHONY: clobber diff --git a/contrib/python/pypodman/pypodman/lib/__init__.py b/contrib/python/pypodman/pypodman/lib/__init__.py index be1b5f467..d9a434254 100644 --- a/contrib/python/pypodman/pypodman/lib/__init__.py +++ b/contrib/python/pypodman/pypodman/lib/__init__.py @@ -3,18 +3,17 @@ import sys import podman from pypodman.lib.action_base import AbstractActionBase -from pypodman.lib.parser_actions import (BooleanAction, BooleanValidate, - ChangeAction, PathAction, - PositiveIntAction, UnitAction) +from pypodman.lib.parser_actions import (ChangeAction, PathAction, + PositiveIntAction, SignalAction, + UnitAction) from pypodman.lib.podman_parser import PodmanArgumentParser from pypodman.lib.report import Report, ReportColumn # Silence pylint overlording... -assert BooleanAction -assert BooleanValidate assert ChangeAction assert PathAction assert PositiveIntAction +assert SignalAction assert UnitAction __all__ = [ diff --git a/contrib/python/pypodman/pypodman/lib/action_base.py b/contrib/python/pypodman/pypodman/lib/action_base.py index a950c362b..5cba7ac5c 100644 --- a/contrib/python/pypodman/pypodman/lib/action_base.py +++ b/contrib/python/pypodman/pypodman/lib/action_base.py @@ -17,29 +17,21 @@ class AbstractActionBase(abc.ABC): Use set_defaults() to set attributes "class_" and "method". These will be invoked as class_(parsed_args).method() """ - parent.add_argument( + parent.add_flag( '--all', - action='store_true', - help=('list all items.' - ' (default: no-op, included for compatibility.)')) - parent.add_argument( - '--no-trunc', - '--notruncate', - action='store_false', - dest='truncate', + help='list all items.') + parent.add_flag( + '--truncate', + '--trunc', default=True, - help='Display extended information. (default: False)') - parent.add_argument( - '--noheading', - action='store_false', - dest='heading', + help="Truncate id's and other long fields.") + parent.add_flag( + '--heading', default=True, - help=('Omit the table headings from the output.' - ' (default: False)')) - parent.add_argument( + help='Include table headings in the output.') + parent.add_flag( '--quiet', - action='store_true', - help='List only the IDs. (default: %(default)s)') + help='List only the IDs.') def __init__(self, args): """Construct class.""" diff --git a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py b/contrib/python/pypodman/pypodman/lib/actions/_create_args.py index 207f52796..8ab4292e8 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py +++ b/contrib/python/pypodman/pypodman/lib/actions/_create_args.py @@ -1,6 +1,6 @@ """Implement common create container arguments together.""" -from pypodman.lib import BooleanAction, UnitAction +from pypodman.lib import SignalAction, UnitAction class CreateArguments(): @@ -108,11 +108,9 @@ class CreateArguments(): metavar='NODES', help=('Memory nodes (MEMs) in which to allow execution (0-3, 0,1).' ' Only effective on NUMA systems')) - parser.add_argument( + parser.add_flag( '--detach', '-d', - action=BooleanAction, - default=False, help='Detached mode: run the container in the background and' ' print the new container ID. (default: False)') parser.add_argument( @@ -218,7 +216,7 @@ class CreateArguments(): # only way for argparse to handle these options. vol_args = { - 'choices': ['bind', 'tmpfs', 'ignore'], + 'choices': ('bind', 'tmpfs', 'ignore'), 'metavar': 'MODE', 'type': str.lower, 'help': 'Tells podman how to handle the builtin image volumes', @@ -228,12 +226,10 @@ class CreateArguments(): volume_group.add_argument('--image-volume', **vol_args) volume_group.add_argument('--builtin-volume', **vol_args) - parser.add_argument( + parser.add_flag( '--interactive', '-i', - action=BooleanAction, - default=False, - help='Keep STDIN open even if not attached. (default: False)') + help='Keep STDIN open even if not attached.') parser.add_argument('--ipc', help='Create namespace') parser.add_argument( '--kernel-memory', action=UnitAction, help='Kernel memory limit') @@ -278,10 +274,9 @@ class CreateArguments(): metavar='BRIDGE', help='Set the Network mode for the container.' ' (format: bridge, host, container:UUID, ns:PATH, none)') - parser.add_argument( + parser.add_flag( '--oom-kill-disable', - action=BooleanAction, - help='Whether to disable OOM Killer for the container or not') + help='Whether to disable OOM Killer for the container or not.') parser.add_argument( '--oom-score-adj', choices=range(-1000, 1000), @@ -298,41 +293,33 @@ class CreateArguments(): help=("Tune the container's pids limit." " Set -1 to have unlimited pids for the container.")) parser.add_argument('--pod', help='Run container in an existing pod') - parser.add_argument( + parser.add_flag( '--privileged', - action=BooleanAction, help='Give extended privileges to this container.') parser.add_argument( '--publish', '-p', metavar='RANGE', help="Publish a container's port, or range of ports, to the host") - parser.add_argument( + parser.add_flag( '--publish-all', '-P', - action=BooleanAction, help='Publish all exposed ports to random' - ' ports on the host interfaces' - '(default: False)') - parser.add_argument( + ' ports on the host interfaces.') + parser.add_flag( '--quiet', '-q', - action='store_true', help='Suppress output information when pulling images') - parser.add_argument( + parser.add_flag( '--read-only', - action=BooleanAction, help="Mount the container's root filesystem as read only.") - parser.add_argument( + parser.add_flag( '--rm', - action=BooleanAction, - default=False, help='Automatically remove the container when it exits.') parser.add_argument( '--rootfs', - action='store_true', - help=('If specified, the first argument refers to an' - ' exploded container on the file system of remote host.')) + help='If specified, the first argument refers to an' + ' exploded container on the file system of remote host.') parser.add_argument( '--security-opt', action='append', @@ -340,15 +327,14 @@ class CreateArguments(): help='Set security options.') parser.add_argument( '--shm-size', action=UnitAction, help='Size of /dev/shm') - parser.add_argument( + parser.add_flag( '--sig-proxy', - action=BooleanAction, - default=True, help='Proxy signals sent to the podman run' ' command to the container process') parser.add_argument( '--stop-signal', - metavar='SIGTERM', + action=SignalAction, + default='TERM', help='Signal to stop a container') parser.add_argument( '--stop-timeout', @@ -374,11 +360,9 @@ class CreateArguments(): metavar='MOUNT', help='Create a tmpfs mount.' ' (default: rw,noexec,nosuid,nodev,size=65536k.)') - parser.add_argument( + parser.add_flag( '--tty', '-t', - action=BooleanAction, - default=False, help='Allocate a pseudo-TTY for standard input of container.') parser.add_argument( '--uidmap', @@ -394,15 +378,16 @@ class CreateArguments(): parser.add_argument( '--user', '-u', - help=('Sets the username or UID used and optionally' - ' the groupname or GID for the specified command.')) + help='Sets the username or UID used and optionally' + ' the groupname or GID for the specified command.') parser.add_argument( '--userns', metavar='NAMESPACE', help='Set the user namespace mode for the container') parser.add_argument( '--uts', - choices=['host', 'ns'], + choices=('host', 'ns'), + type=str.lower, help='Set the UTS mode for the container') parser.add_argument('--volume', '-v', help='Create a bind mount.') parser.add_argument( diff --git a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py b/contrib/python/pypodman/pypodman/lib/actions/commit_action.py index 21924e938..c166e1aff 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/commit_action.py @@ -2,7 +2,7 @@ import sys import podman -from pypodman.lib import AbstractActionBase, BooleanAction, ChangeAction +from pypodman.lib import AbstractActionBase, ChangeAction class Commit(AbstractActionBase): @@ -44,17 +44,14 @@ class Commit(AbstractActionBase): help='Set commit message for committed image' ' (Only on docker images.)', ) - parser.add_argument( + parser.add_flag( '--pause', '-p', - action=BooleanAction, - default=True, help='Pause the container when creating an image', ) - parser.add_argument( + parser.add_flag( '--quiet', '-q', - action='store_true', help='Suppress output', ) parser.add_argument( diff --git a/contrib/python/pypodman/pypodman/lib/actions/history_action.py b/contrib/python/pypodman/pypodman/lib/actions/history_action.py index f9aaa54f6..76c3ad756 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/history_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/history_action.py @@ -5,8 +5,7 @@ from collections import OrderedDict import humanize import podman -from pypodman.lib import (AbstractActionBase, BooleanAction, Report, - ReportColumn) +from pypodman.lib import AbstractActionBase, Report, ReportColumn class History(AbstractActionBase): @@ -17,13 +16,10 @@ class History(AbstractActionBase): """Add History command to parent parser.""" parser = parent.add_parser('history', help='report image history') super().subparser(parser) - parser.add_argument( + parser.add_flag( '--human', '-H', - action=BooleanAction, - default='True', - help='Display sizes and dates in human readable format.' - ' (default: %(default)s)') + help='Display sizes and dates in human readable format.') parser.add_argument( '--format', choices=('json', 'table'), diff --git a/contrib/python/pypodman/pypodman/lib/actions/images_action.py b/contrib/python/pypodman/pypodman/lib/actions/images_action.py index 29bf90dd2..21376eeeb 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/images_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/images_action.py @@ -24,11 +24,9 @@ class Images(AbstractActionBase): help=('Change sort ordered of displayed images.' ' (default: %(default)s)')) - group = parser.add_mutually_exclusive_group() - group.add_argument( + parser.add_flag( '--digests', - action='store_true', - help='Include digests with images. (default: %(default)s)') + help='Include digests with images.') parser.set_defaults(class_=cls, method='list') def __init__(self, args): diff --git a/contrib/python/pypodman/pypodman/lib/actions/info_action.py b/contrib/python/pypodman/pypodman/lib/actions/info_action.py index 988284541..3c854a358 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/info_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/info_action.py @@ -22,10 +22,6 @@ class Info(AbstractActionBase): " (default: yaml)") parser.set_defaults(class_=cls, method='info') - def __init__(self, args): - """Construct Info class.""" - super().__init__(args) - def info(self): """Report on Podman Service.""" try: diff --git a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py b/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py index a581e7e4e..ca5ad2215 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py @@ -22,12 +22,9 @@ class Inspect(AbstractActionBase): type=str.lower, help='Type of object to inspect', ) - parser.add_argument( + parser.add_flag( '--size', - action='store_true', - default=False, - help='Display the total file size if the type is a container.' - ' Always True.') + help='Display the total file size if the type is a container.') parser.add_argument( 'objects', nargs='+', @@ -35,10 +32,6 @@ class Inspect(AbstractActionBase): ) parser.set_defaults(class_=cls, method='inspect') - def __init__(self, args): - """Construct Inspect class.""" - super().__init__(args) - def _get_container(self, ident): try: logging.debug("Getting container %s", ident) diff --git a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py b/contrib/python/pypodman/pypodman/lib/actions/kill_action.py index cb3d3f035..e8fb4e74d 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/kill_action.py @@ -1,9 +1,8 @@ """Remote client command for signaling podman containers.""" -import signal import sys import podman -from pypodman.lib import AbstractActionBase +from pypodman.lib import AbstractActionBase, SignalAction class Kill(AbstractActionBase): @@ -16,10 +15,9 @@ class Kill(AbstractActionBase): parser.add_argument( '--signal', '-s', - choices=range(1, signal.NSIG), - metavar='[1,{}]'.format(signal.NSIG), + action=SignalAction, default=9, - help='Signal to send to the container. (default: 9)') + help='Signal to send to the container. (default: %(default)s)') parser.add_argument( 'containers', nargs='+', @@ -27,10 +25,6 @@ class Kill(AbstractActionBase): ) parser.set_defaults(class_=cls, method='kill') - def __init__(self, args): - """Construct Kill class.""" - super().__init__(args) - def kill(self): """Signal provided containers.""" try: diff --git a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py b/contrib/python/pypodman/pypodman/lib/actions/pause_action.py index ab64d8b81..7dc02f7fe 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pause_action.py @@ -19,10 +19,6 @@ class Pause(AbstractActionBase): ) parser.set_defaults(class_=cls, method='pause') - def __init__(self, args): - """Construct Pause class.""" - super().__init__(args) - def pause(self): """Pause provided containers.""" try: diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py index 46c1e3e51..4e0bde777 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py @@ -2,7 +2,7 @@ import sys import podman -from pypodman.lib import AbstractActionBase, BooleanAction +from pypodman.lib import AbstractActionBase class CreatePod(AbstractActionBase): @@ -20,12 +20,9 @@ class CreatePod(AbstractActionBase): type=str, help='Path to cgroups under which the' ' cgroup for the pod will be created.') - parser.add_argument( + parser.add_flag( '--infra', - action=BooleanAction, - default=True, - help='Create an infra container and associate it with the pod' - '(default: %(default)s)') + help='Create an infra container and associate it with the pod.') parser.add_argument( '-l', '--label', diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py index 430ec34e0..9b6229939 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py @@ -3,7 +3,7 @@ import signal import sys import podman -from pypodman.lib import AbstractActionBase +from pypodman.lib import AbstractActionBase, SignalAction from pypodman.lib import query_model as query_pods @@ -15,18 +15,16 @@ class KillPod(AbstractActionBase): """Add Pod Kill command to parent parser.""" parser = parent.add_parser('kill', help='signal containers in pod') - parser.add_argument( - '-a', + parser.add_flag( '--all', - action='store_true', - help='Sends signal to all pods') + '-a', + help='Sends signal to all pods.') parser.add_argument( '-s', '--signal', - choices=range(1, signal.NSIG), - metavar='[1,{}]'.format(signal.NSIG), + action=SignalAction, default=9, - help='Signal to send to the pod. (default: 9)') + help='Signal to send to the pod. (default: %(default)s)') parser.add_argument('pod', nargs='*', help='pod(s) to signal') parser.set_defaults(class_=cls, method='kill') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py index daae028d4..c751314ca 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py @@ -13,8 +13,10 @@ class PausePod(AbstractActionBase): def subparser(cls, parent): """Add Pod Pause command to parent parser.""" parser = parent.add_parser('pause', help='pause containers in pod') - parser.add_argument( - '-a', '--all', action='store_true', help='Pause all pods') + parser.add_flag( + '--all', + '-a', + help='Pause all pods.') parser.add_argument('pod', nargs='*', help='pod(s) to pause.') parser.set_defaults(class_=cls, method='pause') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py index ecfcb883a..855e313c7 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py @@ -14,18 +14,15 @@ class ProcessesPod(AbstractActionBase): parser = parent.add_parser('ps', help='list processes of pod') super().subparser(parser) - parser.add_argument( + parser.add_flag( '--ctr-names', - action='store_true', - help='Include container name in the info field') - parser.add_argument( + help='Include container name in the info field.') + parser.add_flag( '--ctr-ids', - action='store_true', - help='Include container ID in the info field') - parser.add_argument( + help='Include container ID in the info field.') + parser.add_flag( '--ctr-status', - action='store_true', - help='Include container status in the info field') + help='Include container status in the info field.') parser.add_argument( '--format', choices=('json'), diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py index 40eeb7203..289325d14 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py @@ -13,13 +13,14 @@ class RemovePod(AbstractActionBase): def subparser(cls, parent): """Add Pod Rm command to parent parser.""" parser = parent.add_parser('rm', help='Delete pod and container(s)') - parser.add_argument( - '-a', '--all', action='store_true', help='Remove all pods') - parser.add_argument( - '-f', + parser.add_flag( + '--all', + '-a', + help='Remove all pods.') + parser.add_flag( '--force', - action='store_true', - help='Stop and remove container(s) then delete pod') + '-f', + help='Stop and remove container(s) then delete pod.') parser.add_argument( 'pod', nargs='*', help='Pod to remove. Or, use --all') parser.set_defaults(class_=cls, method='remove') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py index af489ad28..53f45b6de 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py @@ -13,8 +13,10 @@ class RestartPod(AbstractActionBase): def subparser(cls, parent): """Add Pod Restart command to parent parser.""" parser = parent.add_parser('restart', help='restart containers in pod') - parser.add_argument( - '-a', '--all', action='store_true', help='Restart all pods') + parser.add_flag( + '--all', + '-a', + help='Restart all pods.') parser.add_argument( 'pod', nargs='*', help='Pod to restart. Or, use --all') parser.set_defaults(class_=cls, method='restart') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py index 0ddc336bf..ff62b839e 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py @@ -14,8 +14,10 @@ class StartPod(AbstractActionBase): def subparser(cls, parent): """Add Pod Start command to parent parser.""" parser = parent.add_parser('start', help='start pod') - parser.add_argument( - '-a', '--all', action='store_true', help='Start all pods') + parser.add_flag( + '--all', + '-a', + help='Start all pods.') parser.add_argument( 'pod', nargs='*', help='Pod to start. Or, use --all') parser.set_defaults(class_=cls, method='start') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py index 7054fd38a..cbf2bf1e7 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py @@ -13,8 +13,10 @@ class StopPod(AbstractActionBase): def subparser(cls, parent): """Add Pod Stop command to parent parser.""" parser = parent.add_parser('stop', help='stop pod') - parser.add_argument( - '-a', '--all', action='store_true', help='Stop all pods') + parser.add_flag( + '--all', + '-a', + help='Stop all pods.') parser.add_argument( 'pod', nargs='*', help='Pod to stop. Or, use --all') parser.set_defaults(class_=cls, method='stop') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py index 90e1ddbe2..5186cf9cc 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py @@ -13,8 +13,10 @@ class UnpausePod(AbstractActionBase): def subparser(cls, parent): """Add Pod Unpause command to parent parser.""" parser = parent.add_parser('unpause', help='unpause pod') - parser.add_argument( - '-a', '--all', action='store_true', help='Unpause all pods') + parser.add_flag( + '--all', + '-a', + help='Unpause all pods.') parser.add_argument( 'pod', nargs='*', help='Pod to unpause. Or, use --all') parser.set_defaults(class_=cls, method='unpause') diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py b/contrib/python/pypodman/pypodman/lib/actions/pod_action.py index 046af34bb..4b8997a05 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/pod_action.py @@ -5,6 +5,8 @@ import sys from pypodman.lib import AbstractActionBase +# pylint: disable=wildcard-import +# pylint: disable=unused-wildcard-import from .pod import * diff --git a/contrib/python/pypodman/pypodman/lib/actions/port_action.py b/contrib/python/pypodman/pypodman/lib/actions/port_action.py index d2a8ded46..6913f3813 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/port_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/port_action.py @@ -13,16 +13,13 @@ class Port(AbstractActionBase): """Add Port command to parent parser.""" parser = parent.add_parser( 'port', help='retrieve ports from containers') - parser.add_argument( + parser.add_flag( '--all', '-a', - action='store_true', - default=False, help='List all known port mappings for running containers') parser.add_argument( 'containers', nargs='*', - default=None, help='containers to list ports', ) parser.set_defaults(class_=cls, method='port') @@ -61,3 +58,4 @@ class Port(AbstractActionBase): file=sys.stderr, flush=True) return 1 + return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/push_action.py b/contrib/python/pypodman/pypodman/lib/actions/push_action.py index 0030cb5b9..8e86ca335 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/push_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/push_action.py @@ -15,12 +15,10 @@ class Push(AbstractActionBase): 'push', help='push image elsewhere', ) - parser.add_argument( + parser.add_flag( '--tlsverify', - action='store_true', - default=True, help='Require HTTPS and verify certificates when' - ' contacting registries (default: %(default)s)') + ' contacting registries.') parser.add_argument( 'image', nargs=1, help='name or id of image to push') parser.add_argument( @@ -30,10 +28,6 @@ class Push(AbstractActionBase): ) parser.set_defaults(class_=cls, method='push') - def __init__(self, args): - """Construct Push class.""" - super().__init__(args) - def pull(self): """Store image elsewhere.""" try: diff --git a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py b/contrib/python/pypodman/pypodman/lib/actions/restart_action.py index d99d1ad65..415594920 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/restart_action.py @@ -23,10 +23,6 @@ class Restart(AbstractActionBase): 'targets', nargs='+', help='container id(s) to restart') parser.set_defaults(class_=cls, method='restart') - def __init__(self, args): - """Construct Restart class.""" - super().__init__(args) - def restart(self): """Restart container(s).""" try: diff --git a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py b/contrib/python/pypodman/pypodman/lib/actions/rm_action.py index e8074ef4e..99ff6c460 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/rm_action.py @@ -12,20 +12,14 @@ class Rm(AbstractActionBase): def subparser(cls, parent): """Add Rm command to parent parser.""" parser = parent.add_parser('rm', help='delete container(s)') - parser.add_argument( - '-f', + parser.add_flag( '--force', - action='store_true', - help=('force delete of running container(s).' - ' (default: %(default)s)')) + '-f', + help='force delete of running container(s).') parser.add_argument( 'targets', nargs='+', help='container id(s) to delete') parser.set_defaults(class_=cls, method='remove') - def __init__(self, args): - """Construct Rm class.""" - super().__init__(args) - def remove(self): """Remove container(s).""" for ident in self._args.targets: diff --git a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py b/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py index c6ba835cb..7c3d0bd79 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py @@ -12,19 +12,13 @@ class Rmi(AbstractActionBase): def subparser(cls, parent): """Add Rmi command to parent parser.""" parser = parent.add_parser('rmi', help='delete image(s)') - parser.add_argument( - '-f', + parser.add_flag( '--force', - action='store_true', - help=('force delete of image(s) and associated containers.' - ' (default: %(default)s)')) + '-f', + help='force delete of image(s) and associated containers.') parser.add_argument('targets', nargs='+', help='image id(s) to delete') parser.set_defaults(class_=cls, method='remove') - def __init__(self, args): - """Construct Rmi class.""" - super().__init__(args) - def remove(self): """Remove image(s).""" for ident in self._args.targets: diff --git a/contrib/python/pypodman/pypodman/lib/actions/search_action.py b/contrib/python/pypodman/pypodman/lib/actions/search_action.py index d2a585d92..b7b8b465d 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/search_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/search_action.py @@ -4,8 +4,8 @@ import sys from collections import OrderedDict import podman -from pypodman.lib import (AbstractActionBase, BooleanValidate, - PositiveIntAction, Report, ReportColumn) +from pypodman.lib import (AbstractActionBase, PositiveIntAction, Report, + ReportColumn) class FilterAction(argparse.Action): @@ -58,16 +58,16 @@ class FilterAction(argparse.Action): if val < 0: parser.error(msg) elif opt == 'is-automated': - try: - val = BooleanValidate()(val) - except ValueError: + if val.capitalize() in ('True', 'False'): + val = bool(val) + else: msg = ('{} option "is-automated"' ' must be True or False.'.format(self.dest)) parser.error(msg) elif opt == 'is-official': - try: - val = BooleanValidate()(val) - except ValueError: + if val.capitalize() in ('True', 'False'): + val = bool(val) + else: msg = ('{} option "is-official"' ' must be True or False.'.format(self.dest)) parser.error(msg) diff --git a/contrib/python/pypodman/pypodman/lib/actions/start_action.py b/contrib/python/pypodman/pypodman/lib/actions/start_action.py index f312fb3fa..5f88731dc 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/start_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/start_action.py @@ -2,7 +2,7 @@ import sys import podman -from pypodman.lib import AbstractActionBase, BooleanAction +from pypodman.lib import AbstractActionBase class Start(AbstractActionBase): @@ -12,12 +12,10 @@ class Start(AbstractActionBase): def subparser(cls, parent): """Add Start command to parent parser.""" parser = parent.add_parser('start', help='start container') - parser.add_argument( + parser.add_flag( '--attach', '-a', - action=BooleanAction, - default=False, - help="Attach container's STDOUT and STDERR (default: %(default)s)") + help="Attach container's STDOUT and STDERR.") parser.add_argument( '--detach-keys', metavar='KEY(s)', @@ -25,18 +23,14 @@ class Start(AbstractActionBase): help='Override the key sequence for detaching a container.' ' (format: a single character [a-Z] or ctrl-<value> where' ' <value> is one of: a-z, @, ^, [, , or _) (default: ^D)') - parser.add_argument( + parser.add_flag( '--interactive', '-i', - action=BooleanAction, - default=False, - help="Attach container's STDIN (default: %(default)s)") + help="Attach container's STDIN.") # TODO: Implement sig-proxy - parser.add_argument( + parser.add_flag( '--sig-proxy', - action=BooleanAction, - default=False, - help="Proxy received signals to the process (default: %(default)s)" + help="Proxy received signals to the process." ) parser.add_argument( 'containers', @@ -74,3 +68,4 @@ class Start(AbstractActionBase): file=sys.stderr, flush=True) return 1 + return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/version_action.py b/contrib/python/pypodman/pypodman/lib/actions/version_action.py index 12b6dc576..29a0cabe4 100644 --- a/contrib/python/pypodman/pypodman/lib/actions/version_action.py +++ b/contrib/python/pypodman/pypodman/lib/actions/version_action.py @@ -1,9 +1,7 @@ """Remote client command for reporting on Podman service.""" -import json import sys import podman -import yaml from pypodman.lib import AbstractActionBase @@ -17,10 +15,6 @@ class Version(AbstractActionBase): 'version', help='report version on podman service') parser.set_defaults(class_=cls, method='version') - def __init__(self, args): - """Construct Version class.""" - super().__init__(args) - def version(self): """Report on Podman Service.""" try: diff --git a/contrib/python/pypodman/pypodman/lib/parser_actions.py b/contrib/python/pypodman/pypodman/lib/parser_actions.py index 77ee14761..3ff12cab8 100644 --- a/contrib/python/pypodman/pypodman/lib/parser_actions.py +++ b/contrib/python/pypodman/pypodman/lib/parser_actions.py @@ -6,6 +6,7 @@ The constructors are very verbose but remain for IDE support. import argparse import copy import os +import signal # API defined by argparse.Action therefore shut up pylint # pragma pylint: disable=redefined-builtin @@ -13,22 +14,8 @@ import os # pragma pylint: disable=too-many-arguments -class BooleanValidate(): - """Validate value is boolean string.""" - - def __call__(self, value): - """Return True, False or raise ValueError.""" - val = value.capitalize() - if val == 'False': - return False - elif val == 'True': - return True - else: - raise ValueError('"{}" is not True or False'.format(value)) - - -class BooleanAction(argparse.Action): - """Convert and validate bool argument.""" +class ChangeAction(argparse.Action): + """Convert and validate change argument.""" def __init__(self, option_strings, @@ -40,8 +27,13 @@ class BooleanAction(argparse.Action): choices=None, required=False, help=None, - metavar='{True,False}'): - """Create BooleanAction object.""" + metavar='OPT=VALUE'): + """Create ChangeAction object.""" + help = (help or '') + ('Apply change(s) to the new image.' + ' May be given multiple times.') + if default is None: + default = [] + super().__init__( option_strings=option_strings, dest=dest, @@ -56,32 +48,37 @@ class BooleanAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): """Convert and Validate input.""" - try: - val = BooleanValidate()(values) - except ValueError: - parser.error('"{}" must be True or False.'.format(option_string)) - else: - setattr(namespace, self.dest, val) + items = getattr(namespace, self.dest, None) or [] + items = copy.copy(items) + choices = ('CMD', 'ENTRYPOINT', 'ENV', 'EXPOSE', 'LABEL', 'ONBUILD', + 'STOPSIGNAL', 'USER', 'VOLUME', 'WORKDIR') + + opt, _ = values.split('=', 1) + if opt not in choices: + parser.error('Option "{}" is not supported by argument "{}",' + ' valid options are: {}'.format( + opt, option_string, ', '.join(choices))) + items.append(values) + setattr(namespace, self.dest, items) -class ChangeAction(argparse.Action): - """Convert and validate change argument.""" + +class SignalAction(argparse.Action): + """Validate input as a signal.""" def __init__(self, option_strings, dest, nargs=None, const=None, - default=[], - type=None, + default=None, + type=str, choices=None, required=False, - help=None, - metavar='OPT=VALUE'): - """Create ChangeAction object.""" - help = (help or '') + ('Apply change(s) to the new image.' - ' May be given multiple times.') - + help='The signal to send.' + ' It may be given as a name or a number.', + metavar='SIGNAL'): + """Create SignalAction object.""" super().__init__( option_strings=option_strings, dest=dest, @@ -94,21 +91,40 @@ class ChangeAction(argparse.Action): help=help, metavar=metavar) - def __call__(self, parser, namespace, values, option_string=None): - """Convert and Validate input.""" - items = getattr(namespace, self.dest, None) or [] - items = copy.copy(items) + if hasattr(signal, "Signals"): - choices = ('CMD', 'ENTRYPOINT', 'ENV', 'EXPOSE', 'LABEL', 'ONBUILD', - 'STOPSIGNAL', 'USER', 'VOLUME', 'WORKDIR') + def _signal_number(signame): + cooked = 'SIG{}'.format(signame) + try: + return signal.Signals[cooked].value + except ValueError: + pass + else: - opt, val = values.split('=', 1) - if opt not in choices: - parser.error('Option "{}" is not supported by argument "{}",' - ' valid options are: {}'.format( - opt, option_string, ', '.join(choices))) - items.append(values) - setattr(namespace, self.dest, items) + def _signal_number(signame): + cooked = 'SIG{}'.format(signame) + for n, v in sorted(signal.__dict__.items()): + if n != cooked: + continue + if n.startswith("SIG") and not n.startswith("SIG_"): + return v + + self._signal_number = _signal_number + + def __call__(self, parser, namespace, values, option_string=None): + """Validate input is a signal for platform.""" + if values.isdigit(): + signum = int(values) + if signal.SIGRTMIN <= signum >= signal.SIGRTMAX: + raise ValueError('"{}" is not a valid signal. {}-{}'.format( + values, signal.SIGRTMIN, signal.SIGRTMAX)) + else: + signum = self._signal_number(values) + if signum is None: + parser.error( + '"{}" is not a valid signal,' + ' see your platform documentation.'.format(values)) + setattr(namespace, self.dest, signum) class UnitAction(argparse.Action): diff --git a/contrib/python/pypodman/pypodman/lib/podman_parser.py b/contrib/python/pypodman/pypodman/lib/podman_parser.py index 412c8c8fd..913546a91 100644 --- a/contrib/python/pypodman/pypodman/lib/podman_parser.py +++ b/contrib/python/pypodman/pypodman/lib/podman_parser.py @@ -48,6 +48,18 @@ class PodmanArgumentParser(argparse.ArgumentParser): super().__init__(**kwargs) + def add_flag(self, *args, **kwargs): + """Add flag to parser.""" + flags = [a for a in args if a[0] in self.prefix_chars] + dest = flags[0].lstrip(self.prefix_chars) + no_flag = '{0}{0}no-{1}'.format(self.prefix_chars, dest) + + group = self.add_mutually_exclusive_group(required=False) + group.add_argument(*flags, action='store_true', dest=dest, **kwargs) + group.add_argument(no_flag, action='store_false', dest=dest, **kwargs) + default = kwargs.get('default', False) + self.set_defaults(**{dest: default}) + def initialize_parser(self): """Initialize parser without causing recursion meltdown.""" self.add_argument( |