From 45fb935fe44a383ae14f16ab533281687d642c5e Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Wed, 9 Jan 2019 15:05:58 -0700 Subject: Move python code from contrib to it's own repo python-podman Signed-off-by: Jhon Honce --- contrib/python/pypodman/.pylintrc | 564 --------------------- contrib/python/pypodman/MANIFEST.in | 2 - contrib/python/pypodman/Makefile | 39 -- contrib/python/pypodman/README.md | 34 -- contrib/python/pypodman/docs/man1/pypodman.1 | 101 ---- contrib/python/pypodman/pypodman/__init__.py | 0 contrib/python/pypodman/pypodman/lib/__init__.py | 43 -- .../python/pypodman/pypodman/lib/action_base.py | 79 --- .../pypodman/pypodman/lib/actions/__init__.py | 54 -- .../pypodman/pypodman/lib/actions/_create_args.py | 401 --------------- .../pypodman/pypodman/lib/actions/attach_action.py | 68 --- .../pypodman/pypodman/lib/actions/commit_action.py | 99 ---- .../pypodman/pypodman/lib/actions/create_action.py | 55 -- .../pypodman/pypodman/lib/actions/export_action.py | 54 -- .../pypodman/lib/actions/history_action.py | 79 --- .../pypodman/pypodman/lib/actions/images_action.py | 86 ---- .../pypodman/pypodman/lib/actions/import_action.py | 69 --- .../pypodman/pypodman/lib/actions/info_action.py | 45 -- .../pypodman/lib/actions/inspect_action.py | 89 ---- .../pypodman/pypodman/lib/actions/kill_action.py | 49 -- .../pypodman/pypodman/lib/actions/logs_action.py | 61 --- .../pypodman/pypodman/lib/actions/mount_action.py | 78 --- .../pypodman/pypodman/lib/actions/pause_action.py | 43 -- .../pypodman/pypodman/lib/actions/pod/__init__.py | 24 - .../pypodman/lib/actions/pod/create_parser.py | 76 --- .../pypodman/lib/actions/pod/inspect_parser.py | 43 -- .../pypodman/lib/actions/pod/kill_parser.py | 57 --- .../pypodman/lib/actions/pod/pause_parser.py | 49 -- .../pypodman/lib/actions/pod/processes_parser.py | 94 ---- .../pypodman/lib/actions/pod/remove_parser.py | 54 -- .../pypodman/lib/actions/pod/restart_parser.py | 50 -- .../pypodman/lib/actions/pod/start_parser.py | 45 -- .../pypodman/lib/actions/pod/stop_parser.py | 44 -- .../pypodman/lib/actions/pod/top_parser.py | 35 -- .../pypodman/lib/actions/pod/unpause_parser.py | 50 -- .../pypodman/pypodman/lib/actions/pod_action.py | 36 -- .../pypodman/pypodman/lib/actions/port_action.py | 61 --- .../pypodman/pypodman/lib/actions/ps_action.py | 80 --- .../pypodman/pypodman/lib/actions/pull_action.py | 46 -- .../pypodman/pypodman/lib/actions/push_action.py | 50 -- .../pypodman/lib/actions/restart_action.py | 46 -- .../pypodman/pypodman/lib/actions/rm_action.py | 41 -- .../pypodman/pypodman/lib/actions/rmi_action.py | 40 -- .../pypodman/pypodman/lib/actions/run_action.py | 73 --- .../pypodman/pypodman/lib/actions/search_action.py | 160 ------ .../pypodman/pypodman/lib/actions/start_action.py | 71 --- .../pypodman/lib/actions/version_action.py | 35 -- .../python/pypodman/pypodman/lib/parser_actions.py | 247 --------- .../python/pypodman/pypodman/lib/podman_parser.py | 255 ---------- contrib/python/pypodman/pypodman/lib/report.py | 87 ---- contrib/python/pypodman/pypodman/main.py | 81 --- .../python/pypodman/pypodman/test/test_report.py | 23 - contrib/python/pypodman/requirements.txt | 5 - contrib/python/pypodman/setup.py | 45 -- 54 files changed, 4295 deletions(-) delete mode 100644 contrib/python/pypodman/.pylintrc delete mode 100644 contrib/python/pypodman/MANIFEST.in delete mode 100644 contrib/python/pypodman/Makefile delete mode 100644 contrib/python/pypodman/README.md delete mode 100644 contrib/python/pypodman/docs/man1/pypodman.1 delete mode 100644 contrib/python/pypodman/pypodman/__init__.py delete mode 100644 contrib/python/pypodman/pypodman/lib/__init__.py delete mode 100644 contrib/python/pypodman/pypodman/lib/action_base.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/__init__.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/_create_args.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/attach_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/commit_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/create_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/export_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/history_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/images_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/import_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/info_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/inspect_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/kill_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/logs_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/mount_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pause_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/__init__.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/inspect_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/top_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pod_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/port_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/ps_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/pull_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/push_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/restart_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/rm_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/rmi_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/run_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/search_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/start_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/actions/version_action.py delete mode 100644 contrib/python/pypodman/pypodman/lib/parser_actions.py delete mode 100644 contrib/python/pypodman/pypodman/lib/podman_parser.py delete mode 100644 contrib/python/pypodman/pypodman/lib/report.py delete mode 100755 contrib/python/pypodman/pypodman/main.py delete mode 100644 contrib/python/pypodman/pypodman/test/test_report.py delete mode 100644 contrib/python/pypodman/requirements.txt delete mode 100755 contrib/python/pypodman/setup.py (limited to 'contrib/python/pypodman') diff --git a/contrib/python/pypodman/.pylintrc b/contrib/python/pypodman/.pylintrc deleted file mode 100644 index a5628a6cf..000000000 --- a/contrib/python/pypodman/.pylintrc +++ /dev/null @@ -1,564 +0,0 @@ -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code. -extension-pkg-whitelist= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the -# number of processors available to use. -jobs=0 - -# Control the amount of potential inferred values when inferring a single -# object. This can help the performance when dealing with large functions or -# complex, nested conditions. -limit-inference-results=100 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages. -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once). You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use "--disable=all --enable=classes -# --disable=W". -disable=print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - use-symbolic-message-instead, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating, - deprecated-operator-function, - deprecated-urllib-function, - xreadlines-attribute, - deprecated-sys-function, - exception-escape, - comprehension-escape - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details. -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages. -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=sys.exit - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# Tells whether to warn about missing members when the owner of the attribute -# is inferred to be None. -ignore-none=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes. -max-spelling-suggestions=4 - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package.. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module. -max-module-lines=1000 - -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma, - dict-separator - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[BASIC] - -# Naming style matching correct argument names. -#argument-naming-style=snake_case - -# Regular expression matching correct argument names. Overrides argument- -# naming-style. -argument-rgx=[a-z_][a-z0-9_]{1,30}$ -argument-name-hint=[a-z_][a-z0-9_]{1,30}$ - -# Naming style matching correct attribute names. -attr-naming-style=snake_case - -# Regular expression matching correct attribute names. Overrides attr-naming- -# style. -#attr-rgx= - -# Bad variable names which should always be refused, separated by a comma. -bad-names=foo, - bar, - baz, - toto, - tutu, - tata - -# Naming style matching correct class attribute names. -class-attribute-naming-style=any - -# Regular expression matching correct class attribute names. Overrides class- -# attribute-naming-style. -#class-attribute-rgx= - -# Naming style matching correct class names. -class-naming-style=PascalCase - -# Regular expression matching correct class names. Overrides class-naming- -# style. -#class-rgx= - -# Naming style matching correct constant names. -const-naming-style=UPPER_CASE - -# Regular expression matching correct constant names. Overrides const-naming- -# style. -#const-rgx= - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Naming style matching correct function names. -function-naming-style=snake_case - -# Regular expression matching correct function names. Overrides function- -# naming-style. -#function-rgx= - -# Good variable names which should always be accepted, separated by a comma. -good-names=c, - e, - i, - j, - k, - r, - v, - ex, - Run, - _ - -# Include a hint for the correct naming format with invalid-name. -include-naming-hint=no - -# Naming style matching correct inline iteration names. -inlinevar-naming-style=any - -# Regular expression matching correct inline iteration names. Overrides -# inlinevar-naming-style. -#inlinevar-rgx= - -# Naming style matching correct method names. -method-naming-style=snake_case - -# Regular expression matching correct method names. Overrides method-naming- -# style. -#method-rgx= - -# Naming style matching correct module names. -module-naming-style=snake_case - -# Regular expression matching correct module names. Overrides module-naming- -# style. -#module-rgx= - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -# These decorators are taken in consideration only for invalid-name. -property-classes=abc.abstractproperty - -# Naming style matching correct variable names. -#variable-naming-style=snake_case - -# Regular expression matching correct variable names. Overrides variable- -# naming-style. -variable-rgx=[a-z_][a-z0-9_]{2,30}$ -variable-name-hint=[a-z_][a-z0-9_]{2,30}$ - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_, - _cb - -# A regular expression matching the name of dummy variables (i.e. expected to -# not be used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore. -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format. -logging-modules=logging - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma. -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled). -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled). -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled). -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[DESIGN] - -# Support argparse.Action constructor API -# Maximum number of arguments for function / method. -max-args=12 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in an if statement. -max-bool-expr=5 - -# Maximum number of branch for function / method body. -max-branches=12 - -# Maximum number of locals for function / method body. -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=10 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body. -max-returns=6 - -# Maximum number of statements in function / method body. -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=cls - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception". -overgeneral-exceptions=Exception diff --git a/contrib/python/pypodman/MANIFEST.in b/contrib/python/pypodman/MANIFEST.in deleted file mode 100644 index 72e638cb9..000000000 --- a/contrib/python/pypodman/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -prune test/ -include README.md diff --git a/contrib/python/pypodman/Makefile b/contrib/python/pypodman/Makefile deleted file mode 100644 index 230eee44d..000000000 --- a/contrib/python/pypodman/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python) -DESTDIR := / -PODMAN_VERSION ?= '0.11.1.1' - -.PHONY: python-pypodman -python-pypodman: - PODMAN_VERSION=$(PODMAN_VERSION) \ - $(PYTHON) setup.py sdist bdist - -.PHONY: lint -lint: - $(PYTHON) -m pylint pypodman - -.PHONY: integration -integration: - true - -.PHONY: install -install: - PODMAN_VERSION=$(PODMAN_VERSION) \ - $(PYTHON) setup.py install --root ${DESTDIR} - -.PHONY: upload -upload: - PODMAN_VERSION=$(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - -.PHONY: clobber -clobber: uninstall clean - -.PHONY: uninstall - $(PYTHON) -m pip uninstall --yes pypodman ||: - -.PHONY: clean -clean: - rm -rf pypodman.egg-info dist - find . -depth -name __pycache__ -exec rm -rf {} \; - find . -depth -name \*.pyc -exec rm -f {} \; - $(PYTHON) ./setup.py clean --all diff --git a/contrib/python/pypodman/README.md b/contrib/python/pypodman/README.md deleted file mode 100644 index 6991daffa..000000000 --- a/contrib/python/pypodman/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# pypodman - CLI for podman written in python - -## Status: Active Development - -See [libpod](https://github.com/containers/libpod/contrib/python/pypodman) - -## Releases - -To build the pypodman egg and install as user: - -```sh -cd ~/libpod/contrib/python/pypodman -python3 setup.py clean -a && python3 setup.py sdist bdist -python3 setup.py install --user -``` -Add `~/.local/bin` to your `PATH` to run pypodman command. - -## Running command: - -### Against local podman service -```sh -$ pypodman images -``` -### Against remote podman service -```sh -$ pypodman --host node001.example.org images -``` -### Full help system available -```sh -$ pypodman -h -``` -```sh -$ pypodman images -h -``` diff --git a/contrib/python/pypodman/docs/man1/pypodman.1 b/contrib/python/pypodman/docs/man1/pypodman.1 deleted file mode 100644 index 45472dab0..000000000 --- a/contrib/python/pypodman/docs/man1/pypodman.1 +++ /dev/null @@ -1,101 +0,0 @@ -.TH pypodman 1 2018-07-20 0.7.3 -.SH NAME -pypodman \- CLI management tool for containers and images -.SH SYNOPSIS -\f[B]pypodman\f[] [\f[I]global options\f[]] \f[I]command\f[] [\f[I]options\f[]] -.SH DESCRIPTION -pypodman is a simple client only tool to help with debugging issues when daemons -such as CRI runtime and the kubelet are not responding or failing. -.P -pypodman uses a VarLink API to commicate with a podman service running on either -the local or remote machine. pypodman uses ssh to create secure tunnels when -communicating with a remote service. -.SH GLOBAL OPTIONS -.PP -\f[B]\[en]help, \-h\f[] -.PP -Print usage statement. -.PP -\f[B]\[en]version\f[] -.PP -Print program version number and exit. -.PP -\f[B]\[en]config\-home\f[] -.PP -Directory that will be namespaced with \f[C]pypodman\f[] to hold -\f[C]pypodman.conf\f[]. -See FILES below for more details. -.PP -\f[B]\[en]log\-level\f[] -.PP -Log events above specified level: DEBUG, INFO, WARNING (default), ERROR, -or CRITICAL. -.PP -\f[B]\[en]run\-dir\f[] -.PP -Directory that will be namespaced with \f[C]pypodman\f[] to hold local socket -bindings. The default is `\f[C]$XDG_RUNTIME_DIR\\\f[]. -.PP -\f[B]\[en]user\f[] -.PP -Authenicating user on remote host. \f[C]pypodman\f[] defaults to the logged in -user. -.PP -\f[B]\[en]host\f[] -.PP -Name of remote host. There is no default, if not given \f[C]pypodman\f[] -attempts to connect to \f[C]\-\-remote\-socket\-path\f[] on local host. -.PP -\f[B]\[en]port\f[] -.PP -The optional port for \f[C]ssh\f[] to connect tunnel to on remote host. -Default is None and will allow \f[C]ssh\f[] to follow it's default configuration. -.PP -\f[B]\[en]remote\-socket\-path\f[] -.PP -Path on remote host for podman service's \f[C]AF_UNIX\f[] socket. The default is -\f[C]/run/podman/io.podman\f[]. -.PP -\f[B]\[en]identity\-file\f[] -.PP -The optional \f[C]ssh\f[] identity file to authenicate when tunnelling to remote -host. Default is None and will allow \f[C]ssh\f[] to follow it's default methods -for resolving the identity and private key using the logged in user. -.SH COMMANDS -.PP -See podman(1) (podman.1.md) -.SH FILES -.PP -\f[B]pypodman/pypodman.conf\f[] -(\f[C]Any\ element\ of\ XDG_CONFIG_DIRS\f[] and/or -\f[C]XDG_CONFIG_HOME\f[] and/or \f[B]\[en]config\-home\f[]) -.PP -pypodman.conf is one or more configuration files for running the pypodman -command. pypodman.conf is a TOML file with the stanza \f[C][default]\f[], with a -map of \f[C]option: value\f[]. -.PP -pypodman follows the XDG (freedesktop.org) conventions for resolving it's -configuration. The list below are read from top to bottom with later items -overwriting earlier. Any missing items are ignored. -.IP \[bu] 2 -\f[C]pypodman/pypodman.conf\f[] from any path element in -\f[C]XDG_CONFIG_DIRS\f[] or \f[C]\\etc\\xdg\f[] -.IP \[bu] 2 -\f[C]XDG_CONFIG_HOME\f[] or $HOME/.config + \f[C]pypodman/pypodman.conf\f[] -.IP \[bu] 2 -From \f[C]\-\-config\-home\f[] command line option + \f[C]pypodman/pypodman.conf\f[] -.IP \[bu] 2 -From environment variable prefixed with PODMAN_, for example: PODMAN_RUN_DIR -.IP \[bu] 2 -From command line option, for example: \[en]run\-dir -.PP -This should provide Operators the ability to setup basic configurations -and allow users to customize them. -.PP -\f[B]XDG_RUNTIME_DIR\f[] (\f[C]XDG_RUNTIME_DIR/io.podman\f[]) -.PP -Directory where pypodman stores non\-essential runtime files and other file -objects (such as sockets, named pipes, \&...). -.SH SEE ALSO -.PP -\f[C]podman(1)\f[], \f[C]libpod(8)\f[] diff --git a/contrib/python/pypodman/pypodman/__init__.py b/contrib/python/pypodman/pypodman/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/contrib/python/pypodman/pypodman/lib/__init__.py b/contrib/python/pypodman/pypodman/lib/__init__.py deleted file mode 100644 index d9a434254..000000000 --- a/contrib/python/pypodman/pypodman/lib/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Remote podman client support library.""" -import sys - -import podman -from pypodman.lib.action_base import AbstractActionBase -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 ChangeAction -assert PathAction -assert PositiveIntAction -assert SignalAction -assert UnitAction - -__all__ = [ - 'AbstractActionBase', - 'PodmanArgumentParser', - 'Report', - 'ReportColumn', -] - - -def query_model(model, identifiers=None): - """Retrieve all (default) or given model(s).""" - objs = [] - if identifiers is None: - objs.extend(model.list()) - else: - try: - for ident in identifiers: - objs.append(model.get(ident)) - except ( - podman.PodNotFound, - podman.ImageNotFound, - podman.ContainerNotFound, - ) as ex: - print( - '"{}" not found'.format(ex.name), file=sys.stderr, flush=True) - return objs diff --git a/contrib/python/pypodman/pypodman/lib/action_base.py b/contrib/python/pypodman/pypodman/lib/action_base.py deleted file mode 100644 index 5cba7ac5c..000000000 --- a/contrib/python/pypodman/pypodman/lib/action_base.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Base class for all actions of remote client.""" -import abc -from functools import lru_cache - -import podman - - -class AbstractActionBase(abc.ABC): - """Base class for all actions of remote client.""" - - @classmethod - @abc.abstractmethod - def subparser(cls, parent): - """Define parser for this action. Subclasses must implement. - - API: - Use set_defaults() to set attributes "class_" and "method". These will - be invoked as class_(parsed_args).method() - """ - parent.add_flag( - '--all', - help='list all items.') - parent.add_flag( - '--truncate', - '--trunc', - default=True, - help="Truncate id's and other long fields.") - parent.add_flag( - '--heading', - default=True, - help='Include table headings in the output.') - parent.add_flag( - '--quiet', - help='List only the IDs.') - - def __init__(self, args): - """Construct class.""" - # Dump all unset arguments before transmitting to service - self._args = args - self.opts = { - k: v - for k, v in vars(self._args).items() if v is not None - } - - @property - def remote_uri(self): - """URI for remote side of connection.""" - return self._args.remote_uri - - @property - def local_uri(self): - """URI for local side of connection.""" - return self._args.local_uri - - @property - def identity_file(self): - """Key for authenication.""" - return self._args.identity_file - - @property - @lru_cache(maxsize=1) - def client(self): - """Podman remote client for communicating.""" - if self._args.host is None: - return podman.Client(uri=self.local_uri) - return podman.Client( - uri=self.local_uri, - remote_uri=self.remote_uri, - identity_file=self.identity_file) - - def __repr__(self): - """Compute the “official” string representation of object.""" - return ("{}(local_uri='{}', remote_uri='{}'," - " identity_file='{}')").format( - self.__class__, - self.local_uri, - self.remote_uri, - self.identity_file, - ) diff --git a/contrib/python/pypodman/pypodman/lib/actions/__init__.py b/contrib/python/pypodman/pypodman/lib/actions/__init__.py deleted file mode 100644 index c0d77ddb1..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Module to export all the podman subcommands.""" -from pypodman.lib.actions.attach_action import Attach -from pypodman.lib.actions.commit_action import Commit -from pypodman.lib.actions.create_action import Create -from pypodman.lib.actions.export_action import Export -from pypodman.lib.actions.history_action import History -from pypodman.lib.actions.images_action import Images -from pypodman.lib.actions.import_action import Import -from pypodman.lib.actions.info_action import Info -from pypodman.lib.actions.inspect_action import Inspect -from pypodman.lib.actions.kill_action import Kill -from pypodman.lib.actions.logs_action import Logs -from pypodman.lib.actions.mount_action import Mount -from pypodman.lib.actions.pause_action import Pause -from pypodman.lib.actions.pod_action import Pod -from pypodman.lib.actions.port_action import Port -from pypodman.lib.actions.ps_action import Ps -from pypodman.lib.actions.pull_action import Pull -from pypodman.lib.actions.push_action import Push -from pypodman.lib.actions.restart_action import Restart -from pypodman.lib.actions.rm_action import Rm -from pypodman.lib.actions.rmi_action import Rmi -from pypodman.lib.actions.run_action import Run -from pypodman.lib.actions.search_action import Search -from pypodman.lib.actions.start_action import Start -from pypodman.lib.actions.version_action import Version - -__all__ = [ - 'Attach', - 'Commit', - 'Create', - 'Export', - 'History', - 'Images', - 'Import', - 'Info', - 'Inspect', - 'Kill', - 'Logs', - 'Mount', - 'Pause', - 'Pod', - 'Port', - 'Ps', - 'Pull', - 'Push', - 'Restart', - 'Rm', - 'Rmi', - 'Run', - 'Search', - 'Start', - 'Version', -] diff --git a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py b/contrib/python/pypodman/pypodman/lib/actions/_create_args.py deleted file mode 100644 index 8ab4292e8..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py +++ /dev/null @@ -1,401 +0,0 @@ -"""Implement common create container arguments together.""" - -from pypodman.lib import SignalAction, UnitAction - - -class CreateArguments(): - """Helper to add all the create flags to a command.""" - - @classmethod - def add_arguments(cls, parser): - """Add CreateArguments to parser.""" - parser.add_argument( - '--add-host', - action='append', - metavar='HOST', - help='Add a line to /etc/hosts.' - ' The option can be set multiple times.' - ' (format: hostname:ip)') - parser.add_argument( - '--annotation', - action='append', - help='Add an annotation to the container.' - 'The option can be set multiple times.' - '(format: key=value)') - parser.add_argument( - '--attach', - '-a', - action='append', - metavar='FD', - help=('Attach to STDIN, STDOUT or STDERR. The option can be set' - ' for each of stdin, stdout, and stderr.')) - parser.add_argument( - '--blkio-weight', - choices=range(10, 1000), - metavar='[10-1000]', - help=('Block IO weight (relative weight) accepts a' - ' weight value between 10 and 1000.')) - parser.add_argument( - '--blkio-weight-device', - action='append', - metavar='WEIGHT', - help='Block IO weight, relative device weight.' - ' (format: DEVICE_NAME:WEIGHT)') - parser.add_argument( - '--cap-add', - action='append', - metavar='CAP', - help=('Add Linux capabilities' - 'The option can be set multiple times.')) - parser.add_argument( - '--cap-drop', - action='append', - metavar='CAP', - help=('Drop Linux capabilities' - 'The option can be set multiple times.')) - parser.add_argument( - '--cgroup-parent', - metavar='PATH', - help='Path to cgroups under which the cgroup for the' - ' container will be created. If the path is not' - ' absolute, the path is considered to be relative' - ' to the cgroups path of the init process. Cgroups' - ' will be created if they do not already exist.') - parser.add_argument( - '--cidfile', - metavar='PATH', - help='Write the container ID to the file, on the remote host.') - parser.add_argument( - '--conmon-pidfile', - metavar='PATH', - help=('Write the pid of the conmon process to a file,' - ' on the remote host.')) - parser.add_argument( - '--cpu-period', - type=int, - metavar='PERIOD', - help=('Limit the CPU CFS (Completely Fair Scheduler) period.')) - parser.add_argument( - '--cpu-quota', - type=int, - metavar='QUOTA', - help=('Limit the CPU CFS (Completely Fair Scheduler) quota.')) - parser.add_argument( - '--cpu-rt-period', - type=int, - metavar='PERIOD', - help=('Limit the CPU real-time period in microseconds.')) - parser.add_argument( - '--cpu-rt-runtime', - type=int, - metavar='LIMIT', - help=('Limit the CPU real-time runtime in microseconds.')) - parser.add_argument( - '--cpu-shares', - type=int, - metavar='SHARES', - help=('CPU shares (relative weight)')) - parser.add_argument( - '--cpus', - type=float, - help=('Number of CPUs. The default is 0.0 which means no limit')) - parser.add_argument( - '--cpuset-cpus', - metavar='LIST', - help=('CPUs in which to allow execution (0-3, 0,1)')) - parser.add_argument( - '--cpuset-mems', - metavar='NODES', - help=('Memory nodes (MEMs) in which to allow execution (0-3, 0,1).' - ' Only effective on NUMA systems')) - parser.add_flag( - '--detach', - '-d', - help='Detached mode: run the container in the background and' - ' print the new container ID. (default: False)') - parser.add_argument( - '--detach-keys', - metavar='KEY(s)', - default=4, - help='Override the key sequence for detaching a container.' - ' (format: a single character [a-Z] or ctrl- where' - ' is one of: a-z, @, ^, [, , or _)') - parser.add_argument( - '--device', - action='append', - help=('Add a host device to the container' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--device-read-bps', - action='append', - metavar='LIMIT', - help=('Limit read rate (bytes per second) from a device' - ' (e.g. --device-read-bps=/dev/sda:1mb)' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--device-read-iops', - action='append', - metavar='LIMIT', - help=('Limit read rate (IO per second) from a device' - ' (e.g. --device-read-iops=/dev/sda:1000)' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--device-write-bps', - action='append', - metavar='LIMIT', - help=('Limit write rate (bytes per second) to a device' - ' (e.g. --device-write-bps=/dev/sda:1mb)' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--device-write-iops', - action='append', - metavar='LIMIT', - help=('Limit write rate (IO per second) to a device' - ' (e.g. --device-write-iops=/dev/sda:1000)' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--dns', - action='append', - metavar='SERVER', - help=('Set custom DNS servers.' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--dns-option', - action='append', - metavar='OPT', - help=('Set custom DNS options.' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--dns-search', - action='append', - metavar='DOMAIN', - help=('Set custom DNS search domains.' - 'The option can be set multiple times.'), - ) - parser.add_argument( - '--entrypoint', - help=('Overwrite the default ENTRYPOINT of the image.'), - ) - parser.add_argument( - '--env', - '-e', - action='append', - help=('Set environment variables.'), - ) - parser.add_argument( - '--env-file', - help=('Read in a line delimited file of environment variables,' - ' on the remote host.'), - ) - parser.add_argument( - '--expose', - action='append', - metavar='RANGE', - help=('Expose a port, or a range of ports' - ' (e.g. --expose=3300-3310) to set up port redirection.'), - ) - parser.add_argument( - '--gidmap', - metavar='MAP', - action='append', - help=('GID map for the user namespace'), - ) - parser.add_argument( - '--group-add', - action='append', - metavar='GROUP', - help=('Add additional groups to run as')) - parser.add_argument('--hostname', help='Container host name') - - # only way for argparse to handle these options. - vol_args = { - 'choices': ('bind', 'tmpfs', 'ignore'), - 'metavar': 'MODE', - 'type': str.lower, - 'help': 'Tells podman how to handle the builtin image volumes', - } - - volume_group = parser.add_mutually_exclusive_group() - volume_group.add_argument('--image-volume', **vol_args) - volume_group.add_argument('--builtin-volume', **vol_args) - - parser.add_flag( - '--interactive', - '-i', - 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') - parser.add_argument( - '--label', - '-l', - action='append', - help=('Add metadata to a container' - ' (e.g., --label com.example.key=value)')) - parser.add_argument( - '--label-file', help='Read in a line delimited file of labels') - parser.add_argument( - '--log-driver', - choices='json-file', - metavar='json-file', - default='json-file', - help='Logging driver for the container. (default: %(default)s)') - parser.add_argument( - '--log-opt', - action='append', - help='Logging driver specific options') - parser.add_argument( - '--memory', '-m', action=UnitAction, help='Memory limit') - parser.add_argument( - '--memory-reservation', - action=UnitAction, - help='Memory soft limit') - parser.add_argument( - '--memory-swap', - action=UnitAction, - help=('A limit value equal to memory plus swap.' - 'Must be used with the --memory flag')) - parser.add_argument( - '--memory-swappiness', - choices=range(0, 100), - metavar='[0-100]', - help="Tune a container's memory swappiness behavior") - parser.add_argument('--name', help='Assign a name to the container') - parser.add_argument( - '--network', - '--net', - metavar='BRIDGE', - help='Set the Network mode for the container.' - ' (format: bridge, host, container:UUID, ns:PATH, none)') - parser.add_flag( - '--oom-kill-disable', - help='Whether to disable OOM Killer for the container or not.') - parser.add_argument( - '--oom-score-adj', - choices=range(-1000, 1000), - metavar='[-1000-1000]', - help="Tune the host's OOM preferences for containers") - parser.add_argument( - '--pid', - help='Set the PID Namespace mode for the container.' - '(format: host, container:UUID, ns:PATH)') - parser.add_argument( - '--pids-limit', - type=int, - metavar='LIMIT', - 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_flag( - '--privileged', - 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_flag( - '--publish-all', - '-P', - help='Publish all exposed ports to random' - ' ports on the host interfaces.') - parser.add_flag( - '--quiet', - '-q', - help='Suppress output information when pulling images') - parser.add_flag( - '--read-only', - help="Mount the container's root filesystem as read only.") - parser.add_flag( - '--rm', - help='Automatically remove the container when it exits.') - parser.add_argument( - '--rootfs', - 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', - metavar='OPT', - help='Set security options.') - parser.add_argument( - '--shm-size', action=UnitAction, help='Size of /dev/shm') - parser.add_flag( - '--sig-proxy', - help='Proxy signals sent to the podman run' - ' command to the container process') - parser.add_argument( - '--stop-signal', - action=SignalAction, - default='TERM', - help='Signal to stop a container') - parser.add_argument( - '--stop-timeout', - metavar='TIMEOUT', - type=int, - default=10, - help='Seconds to wait on stopping container.') - parser.add_argument( - '--subgidname', - metavar='MAP', - help='Name for GID map from the /etc/subgid file') - parser.add_argument( - '--subuidname', - metavar='MAP', - help='Name for UID map from the /etc/subuid file') - parser.add_argument( - '--sysctl', - action='append', - help='Configure namespaced kernel parameters at runtime') - parser.add_argument( - '--tmpfs', - action='append', - metavar='MOUNT', - help='Create a tmpfs mount.' - ' (default: rw,noexec,nosuid,nodev,size=65536k.)') - parser.add_flag( - '--tty', - '-t', - help='Allocate a pseudo-TTY for standard input of container.') - parser.add_argument( - '--uidmap', - action='append', - metavar='MAP', - help='UID map for the user namespace') - parser.add_argument( - '--ulimit', - action='append', - metavar='OPT', - help='Ulimit options', - ) - parser.add_argument( - '--user', - '-u', - 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'), - type=str.lower, - help='Set the UTS mode for the container') - parser.add_argument('--volume', '-v', help='Create a bind mount.') - parser.add_argument( - '--volumes-from', - action='append', - help='Mount volumes from the specified container(s).') - parser.add_argument( - '--workdir', - '-w', - metavar='PATH', - help='Working directory inside the container') diff --git a/contrib/python/pypodman/pypodman/lib/actions/attach_action.py b/contrib/python/pypodman/pypodman/lib/actions/attach_action.py deleted file mode 100644 index e9829e894..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/attach_action.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Remote client command for attaching to a container.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Attach(AbstractActionBase): - """Class for attaching to a running container.""" - - @classmethod - def subparser(cls, parent): - """Add Attach command to parent parser.""" - parser = parent.add_parser('attach', help='attach to container') - parser.add_argument( - '--image', - help='image to instantiate and attach to', - ) - parser.add_argument( - 'command', - nargs='*', - help='image to instantiate and attach to', - ) - parser.set_defaults(class_=cls, method='attach') - - def __init__(self, args): - """Construct Attach class.""" - super().__init__(args) - if not args.image: - raise ValueError('You must supply one image id' - ' or name to be attached.') - - def attach(self): - """Attach to instantiated image.""" - args = { - 'detach': True, - 'tty': True, - } - if self._args.command: - args['command'] = self._args.command - - try: - try: - ident = self.client.images.pull(self._args.image) - img = self.client.images.get(ident) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - return 1 - - ctnr = img.create(**args) - ctnr.attach(eot=4) - - try: - ctnr.start() - print() - except (BrokenPipeError, KeyboardInterrupt): - print('\nContainer disconnected.') - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 diff --git a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py b/contrib/python/pypodman/pypodman/lib/actions/commit_action.py deleted file mode 100644 index c166e1aff..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Remote client command for creating image from container.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase, ChangeAction - - -class Commit(AbstractActionBase): - """Class for creating image from container.""" - - @classmethod - def subparser(cls, parent): - """Add Commit command to parent parser.""" - parser = parent.add_parser( - 'commit', - help='create image from container', - ) - parser.add_argument( - '--author', - help='Set the author for the committed image', - ) - parser.add_argument( - '--change', - '-c', - action=ChangeAction, - ) - parser.add_argument( - '--format', - '-f', - choices=('oci', 'docker'), - default='oci', - type=str.lower, - help='Set the format of the image manifest and metadata.' - ' (Ignored.)', - ) - parser.add_argument( - '--iidfile', - metavar='PATH', - help='Write the image ID to the file', - ) - parser.add_argument( - '--message', - '-m', - help='Set commit message for committed image' - ' (Only on docker images.)', - ) - parser.add_flag( - '--pause', - '-p', - help='Pause the container when creating an image', - ) - parser.add_flag( - '--quiet', - '-q', - help='Suppress output', - ) - parser.add_argument( - 'container', - nargs=1, - help='container to use as source', - ) - parser.add_argument( - 'image', - nargs=1, - help='image name to create', - ) - parser.set_defaults(class_=cls, method='commit') - - def commit(self): - """Create image from container.""" - try: - try: - ctnr = self.client.containers.get(self._args.container[0]) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - return 1 - else: - ident = ctnr.commit( - self.opts['image'][0], - change=self.opts.get('change', None), - message=self.opts.get('message', None), - pause=self.opts['pause'], - author=self.opts.get('author', None), - ) - - if not self.opts['quiet']: - print(ident) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/create_action.py b/contrib/python/pypodman/pypodman/lib/actions/create_action.py deleted file mode 100644 index 26a312bb1..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/create_action.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Remote client command for creating container from image.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - -from ._create_args import CreateArguments - - -class Create(AbstractActionBase): - """Class for creating container from image.""" - - @classmethod - def subparser(cls, parent): - """Add Create command to parent parser.""" - parser = parent.add_parser( - 'create', help='create container from image') - - CreateArguments.add_arguments(parser) - - parser.add_argument('image', nargs=1, help='source image id') - parser.add_argument( - 'command', - nargs=parent.REMAINDER, - help='command and args to run.', - ) - parser.set_defaults(class_=cls, method='create') - - def __init__(self, args): - """Construct Create class.""" - super().__init__(args) - - # image id used only on client - del self.opts['image'] - - def create(self): - """Create container.""" - try: - for ident in self._args.image: - try: - img = self.client.images.get(ident) - img.container(**self.opts) - print(ident) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/export_action.py b/contrib/python/pypodman/pypodman/lib/actions/export_action.py deleted file mode 100644 index 7ef178c4c..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/export_action.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Remote client command for export container filesystem to tarball.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Export(AbstractActionBase): - """Class for exporting container filesystem to tarball.""" - - @classmethod - def subparser(cls, parent): - """Add Export command to parent parser.""" - parser = parent.add_parser( - 'export', - help='export container to tarball', - ) - parser.add_argument( - '--output', - '-o', - metavar='PATH', - nargs=1, - required=True, - help='Write to this file on host', - ) - parser.add_argument( - 'container', - nargs=1, - help='container to use as source', - ) - parser.set_defaults(class_=cls, method='export') - - def export(self): - """Create tarball from container filesystem.""" - try: - try: - ctnr = self.client.containers.get(self._args.container[0]) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - return 1 - else: - ctnr.export(self._args.output[0]) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/history_action.py b/contrib/python/pypodman/pypodman/lib/actions/history_action.py deleted file mode 100644 index 76c3ad756..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/history_action.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Remote client for reporting image history.""" -import json -from collections import OrderedDict - -import humanize - -import podman -from pypodman.lib import AbstractActionBase, Report, ReportColumn - - -class History(AbstractActionBase): - """Class for reporting Image History.""" - - @classmethod - def subparser(cls, parent): - """Add History command to parent parser.""" - parser = parent.add_parser('history', help='report image history') - super().subparser(parser) - parser.add_flag( - '--human', - '-H', - help='Display sizes and dates in human readable format.') - parser.add_argument( - '--format', - choices=('json', 'table'), - help="Alter the output for a format like 'json' or 'table'." - " (default: table)") - parser.add_argument( - 'image', nargs='+', help='image for history report') - parser.set_defaults(class_=cls, method='history') - - def __init__(self, args): - """Construct History class.""" - super().__init__(args) - - self.columns = OrderedDict({ - 'id': - ReportColumn('id', 'ID', 12), - 'created': - ReportColumn('created', 'CREATED', 11), - 'createdBy': - ReportColumn('createdBy', 'CREATED BY', 45), - 'size': - ReportColumn('size', 'SIZE', 8), - 'comment': - ReportColumn('comment', 'COMMENT', 0) - }) - - def history(self): - """Report image history.""" - rows = list() - for ident in self._args.image: - for details in self.client.images.get(ident).history(): - fields = dict(details._asdict()) - - if self._args.human: - fields.update({ - 'size': - humanize.naturalsize(details.size), - 'created': - humanize.naturaldate( - podman.datetime_parse(details.created)), - }) - del fields['tags'] - - rows.append(fields) - - if self._args.quiet: - for row in rows: - ident = row['id'][:12] if self._args.truncate else row['id'] - print(ident) - elif self._args.format == 'json': - print(json.dumps(rows, indent=2), flush=True) - else: - with Report(self.columns, heading=self._args.heading) as report: - report.layout( - rows, self.columns.keys(), truncate=self._args.truncate) - for row in rows: - report.row(**row) diff --git a/contrib/python/pypodman/pypodman/lib/actions/images_action.py b/contrib/python/pypodman/pypodman/lib/actions/images_action.py deleted file mode 100644 index 21376eeeb..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/images_action.py +++ /dev/null @@ -1,86 +0,0 @@ -"""Remote client commands dealing with images.""" -import operator -from collections import OrderedDict - -import humanize - -import podman -from pypodman.lib import AbstractActionBase, Report, ReportColumn - - -class Images(AbstractActionBase): - """Class for Image manipulation.""" - - @classmethod - def subparser(cls, parent): - """Add Images commands to parent parser.""" - parser = parent.add_parser('images', help='list images') - super().subparser(parser) - parser.add_argument( - '--sort', - choices=['created', 'id', 'repository', 'size', 'tag'], - default='created', - type=str.lower, - help=('Change sort ordered of displayed images.' - ' (default: %(default)s)')) - - parser.add_flag( - '--digests', - help='Include digests with images.') - parser.set_defaults(class_=cls, method='list') - - def __init__(self, args): - """Construct Images class.""" - super().__init__(args) - - self.columns = OrderedDict({ - 'name': - ReportColumn('name', 'REPOSITORY', 0), - 'tag': - ReportColumn('tag', 'TAG', 10), - 'id': - ReportColumn('id', 'IMAGE ID', 12), - 'created': - ReportColumn('created', 'CREATED', 12), - 'size': - ReportColumn('size', 'SIZE', 8), - 'repoDigests': - ReportColumn('repoDigests', 'DIGESTS', 35), - }) - - def list(self): - """List images.""" - images = sorted( - self.client.images.list(), - key=operator.attrgetter(self._args.sort)) - if not images: - return - - rows = list() - for image in images: - fields = dict(image) - fields.update({ - 'created': - humanize.naturaldate(podman.datetime_parse(image.created)), - 'size': - humanize.naturalsize(int(image.size)), - 'repoDigests': - ' '.join(image.repoDigests), - }) - - for r in image.repoTags: - name, tag = r.rsplit(':', 1) - fields.update({ - 'name': name, - 'tag': tag, - }) - rows.append(fields) - - if not self._args.digests: - del self.columns['repoDigests'] - - with Report(self.columns, heading=self._args.heading) as report: - report.layout( - rows, self.columns.keys(), truncate=self._args.truncate) - for row in rows: - report.row(**row) diff --git a/contrib/python/pypodman/pypodman/lib/actions/import_action.py b/contrib/python/pypodman/pypodman/lib/actions/import_action.py deleted file mode 100644 index 43448144a..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/import_action.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Remote client command to import tarball as image filesystem.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase, ChangeAction - - -class Import(AbstractActionBase): - """Class for importing tarball as image filesystem.""" - - @classmethod - def subparser(cls, parent): - """Add Import command to parent parser.""" - parser = parent.add_parser( - 'import', - help='import tarball as image filesystem', - ) - parser.add_argument( - '--change', - '-c', - action=ChangeAction, - ) - parser.add_argument( - '--message', - '-m', - help='Set commit message for imported image.', - ) - parser.add_argument( - 'source', - metavar='PATH', - nargs=1, - help='tarball to use as source on remote system', - ) - parser.add_argument( - 'reference', - metavar='TAG', - nargs='*', - help='Optional tag for image. (default: None)', - ) - parser.set_defaults(class_=cls, method='import_') - - def import_(self): - """Import tarball as image filesystem.""" - # ImportImage() validates it's parameters therefore we need to create - # pristine dict() for keywords - options = {} - if 'message' in self.opts: - options['message'] = self.opts['message'] - if 'change' in self.opts and self.opts['change']: - options['changes'] = self.opts['change'] - - reference = self.opts['reference'][0] if 'reference' in self.opts\ - else None - - try: - ident = self.client.images.import_image( - self.opts['source'][0], - reference, - **options, - ) - print(ident) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/info_action.py b/contrib/python/pypodman/pypodman/lib/actions/info_action.py deleted file mode 100644 index 3c854a358..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/info_action.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Remote client command for reporting on Podman service.""" -import json -import sys - -import podman -import yaml -from pypodman.lib import AbstractActionBase - - -class Info(AbstractActionBase): - """Class for reporting on Podman Service.""" - - @classmethod - def subparser(cls, parent): - """Add Info command to parent parser.""" - parser = parent.add_parser( - 'info', help='report info on podman service') - parser.add_argument( - '--format', - choices=('json', 'yaml'), - help="Alter the output for a format like 'json' or 'yaml'." - " (default: yaml)") - parser.set_defaults(class_=cls, method='info') - - def info(self): - """Report on Podman Service.""" - try: - info = self.client.system.info() - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - else: - if self._args.format == 'json': - print(json.dumps(info._asdict(), indent=2), flush=True) - else: - print( - yaml.dump( - dict(info._asdict()), - canonical=False, - default_flow_style=False), - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py b/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py deleted file mode 100644 index ca5ad2215..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py +++ /dev/null @@ -1,89 +0,0 @@ -"""Remote client command for inspecting podman objects.""" -import json -import logging -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Inspect(AbstractActionBase): - """Class for inspecting podman objects.""" - - @classmethod - def subparser(cls, parent): - """Add Inspect command to parent parser.""" - parser = parent.add_parser('inspect', help='inspect objects') - parser.add_argument( - '--type', - '-t', - choices=('all', 'container', 'image'), - default='all', - type=str.lower, - help='Type of object to inspect', - ) - parser.add_flag( - '--size', - help='Display the total file size if the type is a container.') - parser.add_argument( - 'objects', - nargs='+', - help='objects to inspect', - ) - parser.set_defaults(class_=cls, method='inspect') - - def _get_container(self, ident): - try: - logging.debug("Getting container %s", ident) - ctnr = self.client.containers.get(ident) - except podman.ContainerNotFound: - pass - else: - return ctnr.inspect() - - def _get_image(self, ident): - try: - logging.debug("Getting image %s", ident) - img = self.client.images.get(ident) - except podman.ImageNotFound: - pass - else: - return img.inspect() - - def inspect(self): - """Inspect provided podman objects.""" - output = [] - try: - for ident in self._args.objects: - obj = None - - if self._args.type in ('all', 'container'): - obj = self._get_container(ident) - if obj is None and self._args.type in ('all', 'image'): - obj = self._get_image(ident) - - if obj is None: - if self._args.type == 'container': - msg = 'Container "{}" not found'.format(ident) - elif self._args.type == 'image': - msg = 'Image "{}" not found'.format(ident) - else: - msg = 'Object "{}" not found'.format(ident) - print(msg, file=sys.stderr, flush=True) - else: - fields = obj._asdict() - if not self._args.size: - try: - del fields['sizerootfs'] - except KeyError: - pass - output.append(fields) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - else: - print(json.dumps(output, indent=2)) diff --git a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py b/contrib/python/pypodman/pypodman/lib/actions/kill_action.py deleted file mode 100644 index e8fb4e74d..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Remote client command for signaling podman containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase, SignalAction - - -class Kill(AbstractActionBase): - """Class for sending signal to main process in container.""" - - @classmethod - def subparser(cls, parent): - """Add Kill command to parent parser.""" - parser = parent.add_parser('kill', help='signal container') - parser.add_argument( - '--signal', - '-s', - action=SignalAction, - default=9, - help='Signal to send to the container. (default: %(default)s)') - parser.add_argument( - 'containers', - nargs='+', - help='containers to signal', - ) - parser.set_defaults(class_=cls, method='kill') - - def kill(self): - """Signal provided containers.""" - try: - for ident in self._args.containers: - try: - ctnr = self.client.containers.get(ident) - ctnr.kill(self._args.signal) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - else: - print(ident) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 diff --git a/contrib/python/pypodman/pypodman/lib/actions/logs_action.py b/contrib/python/pypodman/pypodman/lib/actions/logs_action.py deleted file mode 100644 index 91ff7bb08..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/logs_action.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Remote client command for retrieving container logs.""" -import argparse -import logging -import sys -from collections import deque - -import podman -from pypodman.lib import AbstractActionBase, PositiveIntAction - - -class Logs(AbstractActionBase): - """Class for retrieving logs from container.""" - - @classmethod - def subparser(cls, parent): - """Add Logs command to parent parser.""" - parser = parent.add_parser('logs', help='retrieve logs from container') - parser.add_argument( - '--tail', - metavar='LINES', - action=PositiveIntAction, - help='Output the specified number of LINES at the end of the logs') - parser.add_argument( - 'container', - nargs=1, - help='retrieve container logs', - ) - parser.set_defaults(class_=cls, method='logs') - - def __init__(self, args): - """Construct Logs class.""" - super().__init__(args) - - def logs(self): - """Retrieve logs from containers.""" - try: - ident = self._args.container[0] - try: - logging.debug('Get container "%s" logs', ident) - ctnr = self.client.containers.get(ident) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - else: - if self._args.tail: - logs = iter(deque(ctnr.logs(), maxlen=self._args.tail)) - else: - logs = ctnr.logs() - - for line in logs: - sys.stdout.write(line) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 diff --git a/contrib/python/pypodman/pypodman/lib/actions/mount_action.py b/contrib/python/pypodman/pypodman/lib/actions/mount_action.py deleted file mode 100644 index 905eda6da..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/mount_action.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Remote client command for retrieving mounts from containers.""" -import sys -from collections import OrderedDict - -import podman -from pypodman.lib import AbstractActionBase, Report, ReportColumn - - -class Mount(AbstractActionBase): - """Class for retrieving mounts from container.""" - - @classmethod - def subparser(cls, parent): - """Add mount command to parent parser.""" - parser = parent.add_parser( - 'mount', help='retrieve mounts from containers.') - super().subparser(parser) - parser.add_argument( - 'containers', - nargs='*', - help='containers to list ports', - ) - parser.set_defaults(class_=cls, method='mount') - - def __init__(self, args): - """Construct Mount class.""" - super().__init__(args) - - self.columns = OrderedDict({ - 'id': - ReportColumn('id', 'CONTAINER ID', 14), - 'destination': - ReportColumn('destination', 'DESTINATION', 0) - }) - - def mount(self): - """Retrieve mounts from containers.""" - try: - ctnrs = [] - if not self._args.containers: - ctnrs = self.client.containers.list() - else: - for ident in self._args.containers: - try: - ctnrs.append(self.client.containers.get(ident)) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - - if not ctnrs: - print( - 'Unable to find any containers.', file=sys.stderr, flush=True) - return 1 - - rows = list() - for ctnr in ctnrs: - details = ctnr.inspect() - rows.append({ - 'id': ctnr.id, - 'destination': details.graphdriver['data']['mergeddir'] - }) - - with Report(self.columns, heading=self._args.heading) as report: - report.layout( - rows, self.columns.keys(), truncate=self._args.truncate) - for row in rows: - report.row(**row) diff --git a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py b/contrib/python/pypodman/pypodman/lib/actions/pause_action.py deleted file mode 100644 index 7dc02f7fe..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Remote client command for pausing processes in containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Pause(AbstractActionBase): - """Class for pausing processes in container.""" - - @classmethod - def subparser(cls, parent): - """Add Pause command to parent parser.""" - parser = parent.add_parser('pause', help='pause container processes') - parser.add_argument( - 'containers', - nargs='+', - help='containers to pause', - ) - parser.set_defaults(class_=cls, method='pause') - - def pause(self): - """Pause provided containers.""" - try: - for ident in self._args.containers: - try: - ctnr = self.client.containers.get(ident) - ctnr.pause() - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - else: - print(ident) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/__init__.py b/contrib/python/pypodman/pypodman/lib/actions/pod/__init__.py deleted file mode 100644 index 91c54f417..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Provide subparsers for pod commands.""" -from pypodman.lib.actions.pod.create_parser import CreatePod -from pypodman.lib.actions.pod.inspect_parser import InspectPod -from pypodman.lib.actions.pod.kill_parser import KillPod -from pypodman.lib.actions.pod.pause_parser import PausePod -from pypodman.lib.actions.pod.processes_parser import ProcessesPod -from pypodman.lib.actions.pod.remove_parser import RemovePod -from pypodman.lib.actions.pod.start_parser import StartPod -from pypodman.lib.actions.pod.stop_parser import StopPod -from pypodman.lib.actions.pod.top_parser import TopPod -from pypodman.lib.actions.pod.unpause_parser import UnpausePod - -__all__ = [ - 'CreatePod', - 'InspectPod', - 'KillPod', - 'PausePod', - 'ProcessesPod', - 'RemovePod', - 'StartPod', - 'StopPod', - 'TopPod', - 'UnpausePod', -] diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py deleted file mode 100644 index 4e0bde777..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Remote client command for creating pod.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class CreatePod(AbstractActionBase): - """Implement Create Pod command.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Create command to parent parser.""" - parser = parent.add_parser('create', help='create pod') - super().subparser(parser) - - parser.add_argument( - '--cgroup-parent', - dest='cgroupparent', - type=str, - help='Path to cgroups under which the' - ' cgroup for the pod will be created.') - parser.add_flag( - '--infra', - help='Create an infra container and associate it with the pod.') - parser.add_argument( - '-l', - '--label', - dest='labels', - action='append', - type=str, - help='Add metadata to a pod (e.g., --label=com.example.key=value)') - parser.add_argument( - '-n', - '--name', - dest='ident', - type=str, - help='Assign name to the pod') - parser.add_argument( - '--share', - choices=('ipc', 'net', 'pid', 'user', 'uts'), - help='Comma deliminated list of kernel namespaces to share') - - parser.set_defaults(class_=cls, method='create') - - # TODO: Add golang CLI arguments not included in API. - # parser.add_argument( - # '--infra-command', - # default='/pause', - # help='Command to run to start the infra container.' - # '(default: %(default)s)') - # parser.add_argument( - # '--infra-image', - # default='k8s.gcr.io/pause:3.1', - # help='Image to create for the infra container.' - # '(default: %(default)s)') - # parser.add_argument( - # '--podidfile', - # help='Write the pod ID to given file name on remote host') - - def create(self): - """Create Pod from given options.""" - config = {} - for key in ('ident', 'cgroupparent', 'infra', 'labels', 'share'): - config[key] = self.opts.get(key) - - try: - pod = self.client.pods.create(**config) - except podman.ErrorOccurred as ex: - sys.stdout.flush() - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - else: - print(pod.id) diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/inspect_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/inspect_parser.py deleted file mode 100644 index 3c42d636c..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/inspect_parser.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Remote client command for inspecting pods.""" -import json -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class InspectPod(AbstractActionBase): - """Class for reporting on pods and their containers.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Inspect command to parent parser.""" - parser = parent.add_parser( - 'inspect', - help='configuration and state information about a given pod') - parser.add_argument('pod', nargs='+', help='pod(s) to inspect') - parser.set_defaults(class_=cls, method='inspect') - - def inspect(self): - """Report on provided pods.""" - output = {} - try: - for ident in self._args.pod: - try: - pod = self.client.pods.get(ident) - except podman.PodNotFound: - print( - 'Pod "{}" not found.'.format(ident), - file=sys.stdout, - flush=True) - output.update(pod.inspect()._asdict()) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - else: - print(json.dumps(output, indent=2)) - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py deleted file mode 100644 index 9b6229939..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Remote client command for signaling pods and their containers.""" -import signal -import sys - -import podman -from pypodman.lib import AbstractActionBase, SignalAction -from pypodman.lib import query_model as query_pods - - -class KillPod(AbstractActionBase): - """Class for sending signal to processes in pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Kill command to parent parser.""" - parser = parent.add_parser('kill', help='signal containers in pod') - - parser.add_flag( - '--all', - '-a', - help='Sends signal to all pods.') - parser.add_argument( - '-s', - '--signal', - action=SignalAction, - 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') - - def __init__(self, args): - """Construct Pod Kill object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, but not both') - super().__init__(args) - - def kill(self): - """Signal provided pods.""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.kill(self._args.signal) - print(pod.id) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found.'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py deleted file mode 100644 index c751314ca..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Remote client command for pausing processes in pod.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class PausePod(AbstractActionBase): - """Class for pausing containers in pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Pause command to parent parser.""" - parser = parent.add_parser('pause', help='pause containers in pod') - 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') - - def __init__(self, args): - """Construct Pod Pause object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, but not both') - super().__init__(args) - - def pause(self): - """Pause containers in provided Pod.""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.pause() - print(pod.id) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py deleted file mode 100644 index 855e313c7..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Report on pod's containers' processes.""" -import operator -from collections import OrderedDict - -from pypodman.lib import AbstractActionBase, Report, ReportColumn - - -class ProcessesPod(AbstractActionBase): - """Report on Pod's processes.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Ps command to parent parser.""" - parser = parent.add_parser('ps', help='list processes of pod') - super().subparser(parser) - - parser.add_flag( - '--ctr-names', - help='Include container name in the info field.') - parser.add_flag( - '--ctr-ids', - help='Include container ID in the info field.') - parser.add_flag( - '--ctr-status', - help='Include container status in the info field.') - parser.add_argument( - '--format', - choices=('json'), - help='Pretty-print containers to JSON') - parser.add_argument( - '--sort', - choices=('created', 'id', 'name', 'status', 'count'), - default='created', - type=str.lower, - help='Sort on given field. (default: %(default)s)') - parser.add_argument('--filter', help='Not Implemented') - parser.set_defaults(class_=cls, method='processes') - - def __init__(self, args): - """Construct ProcessesPod class.""" - if args.sort == 'created': - args.sort = 'createdat' - elif args.sort == 'count': - args.sort = 'numberofcontainers' - - super().__init__(args) - - self.columns = OrderedDict({ - 'id': - ReportColumn('id', 'POD ID', 14), - 'name': - ReportColumn('name', 'NAME', 30), - 'status': - ReportColumn('status', 'STATUS', 8), - 'numberofcontainers': - ReportColumn('numberofcontainers', 'NUMBER OF CONTAINERS', 0), - 'info': - ReportColumn('info', 'CONTAINER INFO', 0), - }) - - def processes(self): - """List pods.""" - pods = sorted( - self.client.pods.list(), key=operator.attrgetter(self._args.sort)) - if not pods: - return - - rows = list() - for pod in pods: - fields = dict(pod) - if self._args.ctr_ids \ - or self._args.ctr_names \ - or self._args.ctr_status: - keys = ('id', 'name', 'status', 'info') - info = [] - for ctnr in pod.containersinfo: - ctnr_info = [] - if self._args.ctr_ids: - ctnr_info.append(ctnr['id']) - if self._args.ctr_names: - ctnr_info.append(ctnr['name']) - if self._args.ctr_status: - ctnr_info.append(ctnr['status']) - info.append("[ {} ]".format(" ".join(ctnr_info))) - fields.update({'info': " ".join(info)}) - else: - keys = ('id', 'name', 'status', 'numberofcontainers') - - rows.append(fields) - - with Report(self.columns, heading=self._args.heading) as report: - report.layout(rows, keys, truncate=self._args.truncate) - for row in rows: - report.row(**row) diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py deleted file mode 100644 index 289325d14..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Remote client command for deleting pod and containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class RemovePod(AbstractActionBase): - """Class for removing pod and containers from storage.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Rm command to parent parser.""" - parser = parent.add_parser('rm', help='Delete pod and container(s)') - parser.add_flag( - '--all', - '-a', - help='Remove all pods.') - parser.add_flag( - '--force', - '-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') - - def __init__(self, args): - """Construct RemovePod object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, but not both') - super().__init__(args) - - def remove(self): - """Remove pod and container(s).""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.remove(self._args.force) - print(pod.id) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found.'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize, - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py deleted file mode 100644 index 53f45b6de..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Remote client command for restarting pod and container(s).""" -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class RestartPod(AbstractActionBase): - """Class for restarting containers in Pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Restart command to parent parser.""" - parser = parent.add_parser('restart', help='restart containers in pod') - 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') - - def __init__(self, args): - """Construct RestartPod object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, not both') - super().__init__(args) - - def restart(self): - """Restart pod and container(s).""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.restart() - print(pod.id) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found.'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py deleted file mode 100644 index ff62b839e..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Remote client command for starting pod and container(s).""" - -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class StartPod(AbstractActionBase): - """Class for starting pod and container(s).""" - - @classmethod - def subparser(cls, parent): - """Add Pod Start command to parent parser.""" - parser = parent.add_parser('start', help='start pod') - 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') - - def __init__(self, args): - """Construct StartPod object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, but not both') - super().__init__(args) - - def start(self): - """Start pod and container(s).""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.start() - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py deleted file mode 100644 index cbf2bf1e7..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Remote client command for stopping pod and container(s).""" -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class StopPod(AbstractActionBase): - """Class for stopping pod and container(s).""" - - @classmethod - def subparser(cls, parent): - """Add Pod Stop command to parent parser.""" - parser = parent.add_parser('stop', help='stop pod') - 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') - - def __init__(self, args): - """Contruct StopPod object.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, not both') - super().__init__(args) - - def stop(self): - """Stop pod and container(s).""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.stop() - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/top_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/top_parser.py deleted file mode 100644 index f27d60f14..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/top_parser.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Remote client command for reporting on pod and container(s).""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class TopPod(AbstractActionBase): - """Report on containers in Pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Top command to parent parser.""" - parser = parent.add_parser('top', help='report on containers in pod') - parser.add_argument('pod', nargs=1, help='Pod to report on.') - parser.set_defaults(class_=cls, method='top') - - def top(self): - """Report on pod and container(s).""" - try: - for ident in self._args.pod: - pod = self.client.pods.get(ident) - print(pod.top()) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found.'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py deleted file mode 100644 index 5186cf9cc..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Remote client command for unpausing processes in pod.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase -from pypodman.lib import query_model as query_pods - - -class UnpausePod(AbstractActionBase): - """Class for unpausing containers in pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Unpause command to parent parser.""" - parser = parent.add_parser('unpause', help='unpause pod') - 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') - - def __init__(self, args): - """Construct Pod Unpause class.""" - if args.all and args.pod: - raise ValueError('You may give a pod or use --all, but not both') - super().__init__(args) - - def unpause(self): - """Unpause containers in provided Pod.""" - idents = None if self._args.all else self._args.pod - pods = query_pods(self.client.pods, idents) - - for pod in pods: - try: - pod.unpause() - print(pod.id) - except podman.PodNotFound as ex: - print( - 'Pod "{}" not found'.format(ex.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as ex: - print( - '{}'.format(ex.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py b/contrib/python/pypodman/pypodman/lib/actions/pod_action.py deleted file mode 100644 index 4b8997a05..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Remote client command for pod subcommands.""" -import inspect -import logging -import sys - -from pypodman.lib import AbstractActionBase - -# pylint: disable=wildcard-import -# pylint: disable=unused-wildcard-import -from .pod import * - - -class Pod(AbstractActionBase): - """Class for creating a pod.""" - - @classmethod - def subparser(cls, parent): - """Add Pod Create command to parent parser.""" - pod_parser = parent.add_parser( - 'pod', - help='pod commands.' - ' For subcommands, see: %(prog)s pod --help') - subparser = pod_parser.add_subparsers() - - # pull in plugin(s) code for each subcommand - for name, obj in inspect.getmembers( - sys.modules['pypodman.lib.actions.pod'], - predicate=inspect.isclass): - if hasattr(obj, 'subparser'): - try: - obj.subparser(subparser) - except NameError as e: - logging.critical(e) - logging.warning( - 'See subparser configuration for Class "%s"', name) - sys.exit(3) diff --git a/contrib/python/pypodman/pypodman/lib/actions/port_action.py b/contrib/python/pypodman/pypodman/lib/actions/port_action.py deleted file mode 100644 index 6913f3813..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/port_action.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Remote client command for retrieving ports from containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Port(AbstractActionBase): - """Class for retrieving ports from container.""" - - @classmethod - def subparser(cls, parent): - """Add Port command to parent parser.""" - parser = parent.add_parser( - 'port', help='retrieve ports from containers') - parser.add_flag( - '--all', - '-a', - help='List all known port mappings for running containers') - parser.add_argument( - 'containers', - nargs='*', - help='containers to list ports', - ) - parser.set_defaults(class_=cls, method='port') - - def __init__(self, args): - """Construct Port class.""" - if not args.all and not args.containers: - raise ValueError('You must supply at least one' - ' container id or name, or --all.') - super().__init__(args) - - def port(self): - """Retrieve ports from containers.""" - try: - ctnrs = [] - if self._args.all: - ctnrs = self.client.containers.list() - else: - for ident in self._args.containers: - try: - ctnrs.append(self.client.containers.get(ident)) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - - for ctnr in ctnrs: - print("{}\n{}".format(ctnr.id, ctnr.ports)) - - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - return 0 diff --git a/contrib/python/pypodman/pypodman/lib/actions/ps_action.py b/contrib/python/pypodman/pypodman/lib/actions/ps_action.py deleted file mode 100644 index 62ceb2e67..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/ps_action.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Remote client commands dealing with containers.""" -import operator -from collections import OrderedDict - -import humanize - -import podman -from pypodman.lib import AbstractActionBase, Report, ReportColumn - - -class Ps(AbstractActionBase): - """Class for Container manipulation.""" - - @classmethod - def subparser(cls, parent): - """Add Images command to parent parser.""" - parser = parent.add_parser('ps', help='list containers') - super().subparser(parser) - - parser.add_argument( - '--sort', - choices=('createdat', 'id', 'image', 'names', 'runningfor', 'size', - 'status'), - default='createdat', - type=str.lower, - help=('Change sort ordered of displayed containers.' - ' (default: %(default)s)')) - parser.set_defaults(class_=cls, method='list') - - def __init__(self, args): - """Construct Ps class.""" - super().__init__(args) - - self.columns = OrderedDict({ - 'id': - ReportColumn('id', 'CONTAINER ID', 12), - 'image': - ReportColumn('image', 'IMAGE', 31), - 'command': - ReportColumn('column', 'COMMAND', 20), - 'createdat': - ReportColumn('createdat', 'CREATED', 12), - 'status': - ReportColumn('status', 'STATUS', 10), - 'ports': - ReportColumn('ports', 'PORTS', 0), - 'names': - ReportColumn('names', 'NAMES', 18) - }) - - def list(self): - """List containers.""" - if self._args.all: - ictnrs = self.client.containers.list() - else: - ictnrs = filter( - lambda c: podman.FoldedString(c['status']) == 'running', - self.client.containers.list()) - - # TODO: Verify sorting on dates and size - ctnrs = sorted(ictnrs, key=operator.attrgetter(self._args.sort)) - if not ctnrs: - return - - rows = list() - for ctnr in ctnrs: - fields = dict(ctnr) - fields.update({ - 'command': - ' '.join(ctnr.command), - 'createdat': - humanize.naturaldate(podman.datetime_parse(ctnr.createdat)), - }) - rows.append(fields) - - with Report(self.columns, heading=self._args.heading) as report: - report.layout( - rows, self.columns.keys(), truncate=self._args.truncate) - for row in rows: - report.row(**row) diff --git a/contrib/python/pypodman/pypodman/lib/actions/pull_action.py b/contrib/python/pypodman/pypodman/lib/actions/pull_action.py deleted file mode 100644 index d8fbfc1f0..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/pull_action.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Remote client command for pulling images.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Pull(AbstractActionBase): - """Class for retrieving images from repository.""" - - @classmethod - def subparser(cls, parent): - """Add Pull command to parent parser.""" - parser = parent.add_parser( - 'pull', - help='retrieve image from repository', - ) - parser.add_argument( - 'targets', - nargs='+', - help='image id(s) to retrieve.', - ) - parser.set_defaults(class_=cls, method='pull') - - def __init__(self, args): - """Construct Pull class.""" - super().__init__(args) - - def pull(self): - """Retrieve image.""" - for ident in self._args.targets: - try: - self.client.images.pull(ident) - print(ident) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/push_action.py b/contrib/python/pypodman/pypodman/lib/actions/push_action.py deleted file mode 100644 index 8e86ca335..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/push_action.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Remote client command for pushing image elsewhere.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Push(AbstractActionBase): - """Class for pushing images to repository.""" - - @classmethod - def subparser(cls, parent): - """Add Push command to parent parser.""" - parser = parent.add_parser( - 'push', - help='push image elsewhere', - ) - parser.add_flag( - '--tlsverify', - help='Require HTTPS and verify certificates when' - ' contacting registries.') - parser.add_argument( - 'image', nargs=1, help='name or id of image to push') - parser.add_argument( - 'tag', - nargs=1, - help='destination image id', - ) - parser.set_defaults(class_=cls, method='push') - - def pull(self): - """Store image elsewhere.""" - try: - try: - img = self.client.images.get(self._args.image[0]) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - else: - img.push(self._args.tag[0], tlsverify=self._args.tlsverify) - print(self._args.image[0]) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py b/contrib/python/pypodman/pypodman/lib/actions/restart_action.py deleted file mode 100644 index 415594920..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Remote client command for restarting containers.""" -import logging -import sys - -import podman -from pypodman.lib import AbstractActionBase, PositiveIntAction - - -class Restart(AbstractActionBase): - """Class for Restarting containers.""" - - @classmethod - def subparser(cls, parent): - """Add Restart command to parent parser.""" - parser = parent.add_parser('restart', help='restart container(s)') - parser.add_argument( - '--timeout', - action=PositiveIntAction, - default=10, - help='Timeout to wait before forcibly stopping the container' - ' (default: %(default)s seconds)') - parser.add_argument( - 'targets', nargs='+', help='container id(s) to restart') - parser.set_defaults(class_=cls, method='restart') - - def restart(self): - """Restart container(s).""" - try: - for ident in self._args.targets: - try: - ctnr = self.client.containers.get(ident) - logging.debug('Restarting Container %s', ctnr.id) - ctnr.restart(timeout=self._args.timeout) - print(ident) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py b/contrib/python/pypodman/pypodman/lib/actions/rm_action.py deleted file mode 100644 index 99ff6c460..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Remote client command for deleting containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Rm(AbstractActionBase): - """Class for removing containers from storage.""" - - @classmethod - def subparser(cls, parent): - """Add Rm command to parent parser.""" - parser = parent.add_parser('rm', help='delete container(s)') - parser.add_flag( - '--force', - '-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 remove(self): - """Remove container(s).""" - for ident in self._args.targets: - try: - ctnr = self.client.containers.get(ident) - ctnr.remove(self._args.force) - print(ident) - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py b/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py deleted file mode 100644 index 7c3d0bd79..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Remote client command for deleting images.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Rmi(AbstractActionBase): - """Class for removing images from storage.""" - - @classmethod - def subparser(cls, parent): - """Add Rmi command to parent parser.""" - parser = parent.add_parser('rmi', help='delete image(s)') - parser.add_flag( - '--force', - '-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 remove(self): - """Remove image(s).""" - for ident in self._args.targets: - try: - img = self.client.images.get(ident) - img.remove(self._args.force) - print(ident) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/run_action.py b/contrib/python/pypodman/pypodman/lib/actions/run_action.py deleted file mode 100644 index 6a6b3cb2c..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/run_action.py +++ /dev/null @@ -1,73 +0,0 @@ -"""Remote client command for run a command in a new container.""" -import logging -import sys - -import podman -from pypodman.lib import AbstractActionBase - -from ._create_args import CreateArguments - - -class Run(AbstractActionBase): - """Class for running a command in a container.""" - - @classmethod - def subparser(cls, parent): - """Add Run command to parent parser.""" - parser = parent.add_parser('run', help='Run container from image') - - CreateArguments.add_arguments(parser) - - parser.add_argument('image', nargs=1, help='source image id.') - parser.add_argument( - 'command', - nargs=parent.REMAINDER, - help='command and args to run.', - ) - parser.set_defaults(class_=cls, method='run') - - def __init__(self, args): - """Construct Run class.""" - super().__init__(args) - if args.detach and args.rm: - raise ValueError('Incompatible options: --detach and --rm') - - # image id used only on client - del self.opts['image'] - - def run(self): - """Run container.""" - for ident in self._args.image: - try: - try: - img = self.client.images.get(ident) - ctnr = img.container(**self.opts) - except podman.ImageNotFound as e: - sys.stdout.flush() - print( - 'Image {} not found.'.format(e.name), - file=sys.stderr, - flush=True) - continue - else: - logging.debug('New container created "{}"'.format(ctnr.id)) - - if self._args.detach: - ctnr.start() - print(ctnr.id) - else: - ctnr.attach(eot=4) - ctnr.start() - print(ctnr.id) - - if self._args.rm: - ctnr.remove(force=True) - except (BrokenPipeError, KeyboardInterrupt): - print('\nContainer "{}" disconnected.'.format(ctnr.id)) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - 'Run for container "{}" failed: {} {}'.format( - ctnr.id, repr(e), e.reason.capitalize()), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/search_action.py b/contrib/python/pypodman/pypodman/lib/actions/search_action.py deleted file mode 100644 index b7b8b465d..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/search_action.py +++ /dev/null @@ -1,160 +0,0 @@ -"""Remote client command for searching registries for an image.""" -import argparse -import sys -from collections import OrderedDict - -import podman -from pypodman.lib import (AbstractActionBase, PositiveIntAction, Report, - ReportColumn) - - -class FilterAction(argparse.Action): - """Parse filter argument components.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar='FILTER'): - """Create FilterAction object.""" - help = (help or '') + (' (format: stars=##' - ' or is-automated=[True|False]' - ' or is-official=[True|False])') - super().__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - """ - Convert and Validate input. - - Note: side effects - 1) self.dest value is set to subargument dest - 2) new attribute self.dest + '_value' is created with 2nd value. - """ - opt, val = values.split('=', 1) - if opt == 'stars': - msg = ('{} option "stars" requires' - ' a positive integer').format(self.dest) - try: - val = int(val) - except ValueError: - parser.error(msg) - - if val < 0: - parser.error(msg) - elif opt == 'is-automated': - 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': - 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) - else: - msg = ('{} only supports one of the following options:\n' - ' stars, is-automated, or is-official').format(self.dest) - parser.error(msg) - setattr(namespace, self.dest, opt) - setattr(namespace, self.dest + '_value', val) - - -class Search(AbstractActionBase): - """Class for searching registries for an image.""" - - @classmethod - def subparser(cls, parent): - """Add Search command to parent parser.""" - parser = parent.add_parser('search', help='search for images') - super().subparser(parser) - parser.add_argument( - '--filter', - '-f', - action=FilterAction, - help='Filter output based on conditions provided.') - parser.add_argument( - '--limit', - action=PositiveIntAction, - default=25, - help='Limit the number of results.' - ' (default: %(default)s)') - parser.add_argument('term', nargs=1, help='search term for image') - parser.set_defaults(class_=cls, method='search') - - def __init__(self, args): - """Construct Search class.""" - super().__init__(args) - - self.columns = OrderedDict({ - 'name': - ReportColumn('name', 'NAME', 44), - 'description': - ReportColumn('description', 'DESCRIPTION', 44), - 'star_count': - ReportColumn('star_count', 'STARS', 5), - 'is_official': - ReportColumn('is_official', 'OFFICIAL', 8), - 'is_automated': - ReportColumn('is_automated', 'AUTOMATED', 9), - }) - - def search(self): - """Search registries for image.""" - try: - rows = list() - for entry in self.client.images.search( - self._args.term[0], limit=self._args.limit): - - if self._args.filter == 'is-official': - if self._args.filter_value != entry.is_official: - continue - elif self._args.filter == 'is-automated': - if self._args.filter_value != entry.is_automated: - continue - elif self._args.filter == 'stars': - if self._args.filter_value > entry.star_count: - continue - - fields = dict(entry._asdict()) - - status = '[OK]' if entry.is_official else '' - fields['is_official'] = status - - status = '[OK]' if entry.is_automated else '' - fields['is_automated'] = status - - if self._args.truncate: - fields.update({'name': entry.name[-44:]}) - rows.append(fields) - - with Report(self.columns, heading=self._args.heading) as report: - report.layout( - rows, self.columns.keys(), truncate=self._args.truncate) - for row in rows: - report.row(**row) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) diff --git a/contrib/python/pypodman/pypodman/lib/actions/start_action.py b/contrib/python/pypodman/pypodman/lib/actions/start_action.py deleted file mode 100644 index 5f88731dc..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/start_action.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Remote client command for starting containers.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Start(AbstractActionBase): - """Class for starting container.""" - - @classmethod - def subparser(cls, parent): - """Add Start command to parent parser.""" - parser = parent.add_parser('start', help='start container') - parser.add_flag( - '--attach', - '-a', - help="Attach container's STDOUT and STDERR.") - parser.add_argument( - '--detach-keys', - metavar='KEY(s)', - default=4, - help='Override the key sequence for detaching a container.' - ' (format: a single character [a-Z] or ctrl- where' - ' is one of: a-z, @, ^, [, , or _) (default: ^D)') - parser.add_flag( - '--interactive', - '-i', - help="Attach container's STDIN.") - # TODO: Implement sig-proxy - parser.add_flag( - '--sig-proxy', - help="Proxy received signals to the process." - ) - parser.add_argument( - 'containers', - nargs='+', - help='containers to start', - ) - parser.set_defaults(class_=cls, method='start') - - def start(self): - """Start provided containers.""" - stdin = sys.stdin if self.opts['interactive'] else None - stdout = sys.stdout if self.opts['attach'] else None - - try: - for ident in self._args.containers: - try: - ctnr = self.client.containers.get(ident) - ctnr.attach( - eot=self.opts['detach_keys'], - stdin=stdin, - stdout=stdout) - ctnr.start() - except podman.ContainerNotFound as e: - sys.stdout.flush() - print( - 'Container "{}" not found'.format(e.name), - file=sys.stderr, - flush=True) - else: - print(ident) - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - 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 deleted file mode 100644 index 29a0cabe4..000000000 --- a/contrib/python/pypodman/pypodman/lib/actions/version_action.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Remote client command for reporting on Podman service.""" -import sys - -import podman -from pypodman.lib import AbstractActionBase - - -class Version(AbstractActionBase): - """Class for reporting on Podman Service.""" - - @classmethod - def subparser(cls, parent): - """Add Version command to parent parser.""" - parser = parent.add_parser( - 'version', help='report version on podman service') - parser.set_defaults(class_=cls, method='version') - - def version(self): - """Report on Podman Service.""" - try: - info = self.client.system.info() - except podman.ErrorOccurred as e: - sys.stdout.flush() - print( - '{}'.format(e.reason).capitalize(), - file=sys.stderr, - flush=True) - return 1 - else: - version = info._asdict()['podman'] - host = info._asdict()['host'] - print("Version {}".format(version['podman_version'])) - print("Go Version {}".format(version['go_version'])) - print("Git Commit {}".format(version['git_commit'])) - print("OS/Arch {}/{}".format(host["os"], host["arch"])) diff --git a/contrib/python/pypodman/pypodman/lib/parser_actions.py b/contrib/python/pypodman/pypodman/lib/parser_actions.py deleted file mode 100644 index 3ff12cab8..000000000 --- a/contrib/python/pypodman/pypodman/lib/parser_actions.py +++ /dev/null @@ -1,247 +0,0 @@ -""" -Supplimental argparse.Action converters and validaters. - -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 -# pragma pylint: disable=too-few-public-methods -# pragma pylint: disable=too-many-arguments - - -class ChangeAction(argparse.Action): - """Convert and validate change argument.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - 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.') - if default is None: - default = [] - - super().__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - 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) - - 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 SignalAction(argparse.Action): - """Validate input as a signal.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=str, - choices=None, - required=False, - 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, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - if hasattr(signal, "Signals"): - - def _signal_number(signame): - cooked = 'SIG{}'.format(signame) - try: - return signal.Signals[cooked].value - except ValueError: - pass - else: - - 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): - """Validate number given is positive integer, with optional suffix.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar='UNIT'): - """Create UnitAction object.""" - help = (help or metavar or dest)\ - + ' (format: [], where unit = b, k, m or g)' - super().__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - """Validate input as a UNIT.""" - try: - val = int(values) - except ValueError: - if not values[:-1].isdigit(): - msg = ('{} must be a positive integer,' - ' with optional suffix').format(option_string) - parser.error(msg) - if not values[-1] in ('b', 'k', 'm', 'g'): - msg = '{} only supports suffices of: b, k, m, g'.format( - option_string) - parser.error(msg) - else: - if val <= 0: - msg = '{} must be a positive integer'.format(option_string) - parser.error(msg) - - setattr(namespace, self.dest, values) - - -class PositiveIntAction(argparse.Action): - """Validate number given is positive integer.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=int, - choices=None, - required=False, - help='Must be a positive integer.', - metavar=None): - """Create PositiveIntAction object.""" - super().__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - """Validate input.""" - if values > 0: - setattr(namespace, self.dest, values) - return - - msg = '{} must be a positive integer'.format(option_string) - parser.error(msg) - - -class PathAction(argparse.Action): - """Expand user- and relative-paths.""" - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar='PATH'): - """Create PathAction object.""" - super().__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - """Resolve full path value on local filesystem.""" - setattr(namespace, self.dest, - os.path.abspath(os.path.expanduser(values))) diff --git a/contrib/python/pypodman/pypodman/lib/podman_parser.py b/contrib/python/pypodman/pypodman/lib/podman_parser.py deleted file mode 100644 index 913546a91..000000000 --- a/contrib/python/pypodman/pypodman/lib/podman_parser.py +++ /dev/null @@ -1,255 +0,0 @@ -"""Parse configuration while building subcommands.""" -import argparse -import getpass -import inspect -import logging -import os -import shutil -import sys -from contextlib import suppress -from pathlib import Path - -import pkg_resources -import pytoml - -from .parser_actions import PathAction, PositiveIntAction - -# TODO: setup.py and obtain __version__ from rpm.spec -try: - __version__ = pkg_resources.get_distribution('pypodman').version -except Exception: # pylint: disable=broad-except - __version__ = '0.0.0' - - -class HelpFormatter(argparse.RawDescriptionHelpFormatter): - """Set help width to screen size.""" - - def __init__(self, *args, **kwargs): - """Construct HelpFormatter using screen width.""" - if 'width' not in kwargs: - try: - size = shutil.get_terminal_size() - kwargs['width'] = size.columns - except Exception: # pylint: disable=broad-except - kwargs['width'] = 80 - - super().__init__(*args, **kwargs) - - -class PodmanArgumentParser(argparse.ArgumentParser): - """Default remote podman configuration.""" - - def __init__(self, **kwargs): - """Construct the parser.""" - kwargs['add_help'] = True - kwargs['description'] = ('Portable and simple management' - ' tool for containers and images') - kwargs['formatter_class'] = HelpFormatter - - 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( - '--version', - action='version', - version='%(prog)s v. ' + __version__) - self.add_argument( - '--log-level', - choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], - default='WARNING', - type=str.upper, - help='set logging level for events. (default: %(default)s)', - ) - self.add_argument( - '--run-dir', - metavar='DIRECTORY', - help=('directory to place local socket bindings.' - ' (default: XDG_RUNTIME_DIR/pypodman)')) - self.add_argument( - '--username', - '-l', - help='Authenicating user on remote host. (default: {})'.format( - getpass.getuser())) - self.add_argument( - '--host', help='name of remote host. (default: None)') - self.add_argument( - '--port', - '-p', - action=PositiveIntAction, - help='port for ssh tunnel to remote host. (default: 22)') - self.add_argument( - '--remote-socket-path', - metavar='PATH', - help=('path of podman socket on remote host' - ' (default: /run/podman/io.podman)')) - self.add_argument( - '--identity-file', - '-i', - action=PathAction, - help='path to ssh identity file. (default: ~user/.ssh/id_dsa)') - self.add_argument( - '--config-home', - metavar='DIRECTORY', - action=PathAction, - help=('home of configuration "pypodman.conf".' - ' (default: XDG_CONFIG_HOME/pypodman)')) - - actions_parser = self.add_subparsers( - dest='subparser_name', help='commands') - # For create/exec/run: don't process options intended for subcommand - actions_parser.REMAINDER = argparse.REMAINDER - - # import buried here to prevent import loops - import pypodman.lib.actions # pylint: disable=cyclic-import - assert pypodman.lib.actions - - # pull in plugin(s) code for each subcommand - for name, obj in inspect.getmembers( - sys.modules['pypodman.lib.actions'], - predicate=inspect.isclass): - if hasattr(obj, 'subparser'): - try: - obj.subparser(actions_parser) - except NameError as e: - logging.critical(e) - logging.warning( - 'See subparser configuration for Class "%s"', name) - sys.exit(3) - - def parse_args(self, args=None, namespace=None): - """Parse command line arguments, backed by env var and config_file.""" - self.initialize_parser() - cooked = super().parse_args(args, namespace) - return self.resolve_configuration(cooked) - - def resolve_configuration(self, args): - """Find and fill in any arguments not passed on command line.""" - args.xdg_runtime_dir = os.environ.get('XDG_RUNTIME_DIR', '/tmp') - args.xdg_config_home = os.environ.get('XDG_CONFIG_HOME', - os.path.expanduser('~/.config')) - args.xdg_config_dirs = os.environ.get('XDG_CONFIG_DIRS', '/etc/xdg') - - # Configuration file(s) are optional, - # required arguments may be provided elsewhere - config = {'default': {}} - dirs = args.xdg_config_dirs.split(':') - dirs.extend((args.xdg_config_home, args.config_home)) - for dir_ in dirs: - if dir_ is None: - continue - with suppress(OSError): - cnf = Path(dir_, 'pypodman', 'pypodman.conf') - with cnf.open() as stream: - config.update(pytoml.load(stream)) - - def reqattr(name, value): - """Raise an error if value is unset.""" - if value: - setattr(args, name, value) - return value - return self.error( - 'Required argument "{}" is not configured.'.format(name)) - - reqattr( - 'run_dir', - getattr(args, 'run_dir') - or os.environ.get('PODMAN_RUN_DIR') - or config['default'].get('run_dir') - or str(Path(args.xdg_runtime_dir, 'pypodman')) - ) # yapf: disable - - setattr( - args, - 'host', - getattr(args, 'host') - or os.environ.get('PODMAN_HOST') - or config['default'].get('host') - ) # yapf:disable - - reqattr( - 'username', - getattr(args, 'username') - or os.environ.get('PODMAN_USER') - or config['default'].get('username') - or os.environ.get('USER') - or os.environ.get('LOGNAME') - or getpass.getuser() - ) # yapf:disable - - reqattr( - 'port', - getattr(args, 'port') - or os.environ.get('PODMAN_PORT') - or config['default'].get('port', None) - or 22 - ) # yapf:disable - - reqattr( - 'remote_socket_path', - getattr(args, 'remote_socket_path') - or os.environ.get('PODMAN_REMOTE_SOCKET_PATH') - or config['default'].get('remote_socket_path') - or '/run/podman/io.podman' - ) # yapf:disable - - reqattr( - 'log_level', - getattr(args, 'log_level') - or os.environ.get('PODMAN_LOG_LEVEL') - or config['default'].get('log_level') - or logging.WARNING - ) # yapf:disable - - setattr( - args, - 'identity_file', - getattr(args, 'identity_file') - or os.environ.get('PODMAN_IDENTITY_FILE') - or config['default'].get('identity_file') - or os.path.expanduser('~{}/.ssh/id_dsa'.format(args.username)) - ) # yapf:disable - - if not os.path.isfile(args.identity_file): - args.identity_file = None - - if args.host: - args.local_socket_path = str(Path(args.run_dir, 'podman.socket')) - else: - args.local_socket_path = args.remote_socket_path - - args.local_uri = 'unix:{}'.format(args.local_socket_path) - - if args.host: - components = ['ssh://', args.username, '@', args.host] - if args.port: - components.extend((':', str(args.port))) - components.append(args.remote_socket_path) - - args.remote_uri = ''.join(components) - return args - - def exit(self, status=0, message=None): - """Capture message and route to logger.""" - if message: - log = logging.info if status == 0 else logging.error - log(message) - super().exit(status) - - def error(self, message): - """Capture message and route to logger.""" - logging.error('%s: %s', self.prog, message) - logging.error("Try '%s --help' for more information.", self.prog) - super().exit(2) diff --git a/contrib/python/pypodman/pypodman/lib/report.py b/contrib/python/pypodman/pypodman/lib/report.py deleted file mode 100644 index b689390fd..000000000 --- a/contrib/python/pypodman/pypodman/lib/report.py +++ /dev/null @@ -1,87 +0,0 @@ -"""Report Manager.""" -import string -import sys -from collections import namedtuple - - -class ReportFormatter(string.Formatter): - """Custom formatter to default missing keys to ''.""" - - def get_value(self, key, args, kwargs): - """Map missing key to value ''.""" - try: - if isinstance(key, int): - return args[key] - else: - return kwargs[key] - except KeyError: - return '' - - -class ReportColumn(namedtuple('ReportColumn', 'key display width default')): - """Hold attributes of output column.""" - - __slots__ = () - - def __new__(cls, key, display, width, default=None): - """Add defaults for attributes.""" - return super(ReportColumn, cls).__new__(cls, key, display, width, - default) - - -class Report(): - """Report Manager.""" - - def __init__(self, columns, heading=True, epilog=None, file=sys.stdout): - """Construct Report. - - columns is a mapping for named fields to column headings. - headers True prints headers on table. - epilog will be printed when the report context is closed. - """ - self._columns = columns - self._file = file - self._format_string = None - self._formatter = ReportFormatter() - self._heading = heading - self.epilog = epilog - - def row(self, **fields): - """Print row for report.""" - if self._heading: - hdrs = {k: v.display for (k, v) in self._columns.items()} - print( - self._formatter.format(self._format_string, **hdrs), - flush=True, - file=self._file, - ) - self._heading = False - - fields = {k: str(v) for k, v in fields.items()} - print(self._formatter.format(self._format_string, **fields)) - - def __enter__(self): - """Return `self` upon entering the runtime context.""" - return self - - def __exit__(self, exc_type, exc_value, traceback): - """Leave Report context and print epilog if provided.""" - if self.epilog: - print(self.epilog, flush=True, file=self._file) - - def layout(self, iterable, keys, truncate=True): - """Use data and headings build format for table to fit.""" - fmt = [] - - for key in keys: - slice_ = [str(i.get(key, '')) for i in iterable] - data_len = len(max(slice_, key=len)) - - info = self._columns.get(key, - ReportColumn(key, key.upper(), data_len)) - display_len = max(data_len, len(info.display)) - if truncate and info.width != 0: - display_len = info.width - - fmt.append('{{{0}:{1}.{1}}}'.format(key, display_len)) - self._format_string = ' '.join(fmt) diff --git a/contrib/python/pypodman/pypodman/main.py b/contrib/python/pypodman/pypodman/main.py deleted file mode 100755 index e512dc483..000000000 --- a/contrib/python/pypodman/pypodman/main.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Remote podman client.""" -import logging -import os -import sys -from subprocess import CalledProcessError - -from pypodman.lib import PodmanArgumentParser - - -def main(): - """Entry point.""" - # Setup logging so we use stderr and can change logging level later - # Do it now before there is any chance of a default setup hardcoding crap. - log = logging.getLogger() - fmt = logging.Formatter('%(asctime)s | %(levelname)-8s | %(message)s', - '%Y-%m-%d %H:%M:%S %Z') - stderr = logging.StreamHandler(stream=sys.stderr) - stderr.setFormatter(fmt) - log.addHandler(stderr) - log.setLevel(logging.WARNING) - - parser = PodmanArgumentParser() - args = parser.parse_args() - - log.setLevel(args.log_level) - logging.debug( - 'Logging initialized at level %s', - logging.getLevelName(logging.getLogger().getEffectiveLevel())) - - def want_tb(): - """Add traceback when logging events.""" - return log.getEffectiveLevel() == logging.DEBUG - - try: - if not os.path.exists(args.run_dir): - os.makedirs(args.run_dir) - except PermissionError as e: - logging.critical(e, exc_info=want_tb()) - sys.exit(6) - - # class_(args).method() are set by the sub-command's parser - returncode = None - try: - obj = args.class_(args) - except AttributeError: - parser.print_help(sys.stderr) - sys.exit(1) - except ValueError as e: - print(e, file=sys.stderr, flush=True) - sys.exit(1) - except Exception as e: # pylint: disable=broad-except - logging.critical(repr(e), exc_info=want_tb()) - logging.warning('See subparser "%s" configuration.', - args.subparser_name) - sys.exit(5) - - try: - returncode = getattr(obj, args.method)() - except KeyboardInterrupt: - pass - except AttributeError as e: - logging.critical(e, exc_info=want_tb()) - logging.warning('See subparser "%s" configuration.', - args.subparser_name) - returncode = 3 - except ( - CalledProcessError, - ConnectionError, - ConnectionRefusedError, - ConnectionResetError, - TimeoutError, - ) as e: - logging.critical(e, exc_info=want_tb()) - logging.info('Review connection arguments for correctness.') - returncode = 4 - - return 0 if returncode is None else returncode - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/contrib/python/pypodman/pypodman/test/test_report.py b/contrib/python/pypodman/pypodman/test/test_report.py deleted file mode 100644 index 280a9a954..000000000 --- a/contrib/python/pypodman/pypodman/test/test_report.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import absolute_import - -import unittest - -from report import Report, ReportColumn - - -class TestReport(unittest.TestCase): - def setUp(self): - pass - - def test_report_column(self): - rc = ReportColumn('k', 'v', 3) - self.assertEqual(rc.key, 'k') - self.assertEqual(rc.display, 'v') - self.assertEqual(rc.width, 3) - self.assertIsNone(rc.default) - - rc = ReportColumn('k', 'v', 3, 'd') - self.assertEqual(rc.key, 'k') - self.assertEqual(rc.display, 'v') - self.assertEqual(rc.width, 3) - self.assertEqual(rc.default, 'd') diff --git a/contrib/python/pypodman/requirements.txt b/contrib/python/pypodman/requirements.txt deleted file mode 100644 index ba01ed36e..000000000 --- a/contrib/python/pypodman/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -humanize -podman -pytoml -PyYAML -setuptools>=39 diff --git a/contrib/python/pypodman/setup.py b/contrib/python/pypodman/setup.py deleted file mode 100755 index f07e89201..000000000 --- a/contrib/python/pypodman/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python - -import os - -from setuptools import find_packages, setup - -root = os.path.abspath(os.path.dirname(__file__)) - -with open(os.path.join(root, 'README.md')) as me: - readme = me.read() - -with open(os.path.join(root, 'requirements.txt')) as r: - requirements = r.read().splitlines() - - -setup( - name='pypodman', - version=os.environ.get('PODMAN_VERSION', '0.0.0'), - description='A client for communicating with a Podman server', - author_email='jhonce@redhat.com', - author='Jhon Honce', - license='Apache Software License', - long_description=readme, - entry_points={'console_scripts': [ - 'pypodman = pypodman.main:main', - ]}, - include_package_data=True, - install_requires=requirements, - packages=find_packages(exclude=['test']), - python_requires='>=3', - zip_safe=True, - url='http://github.com/containers/libpod', - keywords='varlink libpod podman pypodman', - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python :: 3.4', - 'Topic :: System :: Systems Administration', - 'Topic :: Utilities', - ]) -- cgit v1.2.3-54-g00ecf