summaryrefslogtreecommitdiff
path: root/contrib/python/podman
diff options
context:
space:
mode:
authorJhon Honce <jhonce@redhat.com>2019-01-09 15:05:58 -0700
committerJhon Honce <jhonce@redhat.com>2019-01-10 11:27:50 -0700
commit45fb935fe44a383ae14f16ab533281687d642c5e (patch)
treef40e0fd8fae389398a5aa6d35888944cde9f03d8 /contrib/python/podman
parent2169b9fe14516b724b257437ed97e32046a4d611 (diff)
downloadpodman-45fb935fe44a383ae14f16ab533281687d642c5e.tar.gz
podman-45fb935fe44a383ae14f16ab533281687d642c5e.tar.bz2
podman-45fb935fe44a383ae14f16ab533281687d642c5e.zip
Move python code from contrib to it's own repo python-podman
Signed-off-by: Jhon Honce <jhonce@redhat.com>
Diffstat (limited to 'contrib/python/podman')
-rw-r--r--contrib/python/podman/.pylintrc564
-rw-r--r--contrib/python/podman/CHANGES.txt1
-rw-r--r--contrib/python/podman/LICENSE.txt13
-rw-r--r--contrib/python/podman/MANIFEST.in3
-rw-r--r--contrib/python/podman/Makefile40
-rw-r--r--contrib/python/podman/README.md44
-rw-r--r--contrib/python/podman/examples/eg_attach.py18
-rw-r--r--contrib/python/podman/examples/eg_containers_by_image.py16
-rw-r--r--contrib/python/podman/examples/eg_image_list.py10
-rw-r--r--contrib/python/podman/examples/eg_inspect_fedora.py16
-rw-r--r--contrib/python/podman/examples/eg_latest_containers.py19
-rw-r--r--contrib/python/podman/examples/eg_new_image.py32
-rwxr-xr-xcontrib/python/podman/examples/run_example.sh43
-rw-r--r--contrib/python/podman/podman/__init__.py29
-rw-r--r--contrib/python/podman/podman/client.py212
-rw-r--r--contrib/python/podman/podman/libs/__init__.py75
-rw-r--r--contrib/python/podman/podman/libs/_containers_attach.py79
-rw-r--r--contrib/python/podman/podman/libs/_containers_start.py82
-rw-r--r--contrib/python/podman/podman/libs/containers.py248
-rw-r--r--contrib/python/podman/podman/libs/errors.py77
-rw-r--r--contrib/python/podman/podman/libs/images.py164
-rw-r--r--contrib/python/podman/podman/libs/pods.py163
-rw-r--r--contrib/python/podman/podman/libs/system.py40
-rw-r--r--contrib/python/podman/podman/libs/tunnel.py190
-rw-r--r--contrib/python/podman/requirements.txt4
-rwxr-xr-xcontrib/python/podman/setup.py38
-rw-r--r--contrib/python/podman/test/__init__.py0
-rw-r--r--contrib/python/podman/test/podman_testcase.py112
-rw-r--r--contrib/python/podman/test/retry_decorator.py43
-rw-r--r--contrib/python/podman/test/test_client.py35
-rw-r--r--contrib/python/podman/test/test_containers.py244
-rw-r--r--contrib/python/podman/test/test_images.py174
-rw-r--r--contrib/python/podman/test/test_libs.py53
-rw-r--r--contrib/python/podman/test/test_pods_ctnrs.py66
-rw-r--r--contrib/python/podman/test/test_pods_no_ctnrs.py94
-rwxr-xr-xcontrib/python/podman/test/test_runner.sh156
-rw-r--r--contrib/python/podman/test/test_system.py63
-rw-r--r--contrib/python/podman/test/test_tunnel.py86
-rw-r--r--contrib/python/podman/tox.ini8
39 files changed, 0 insertions, 3354 deletions
diff --git a/contrib/python/podman/.pylintrc b/contrib/python/podman/.pylintrc
deleted file mode 100644
index a5628a6cf..000000000
--- a/contrib/python/podman/.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*(# )?<?https?://\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/podman/CHANGES.txt b/contrib/python/podman/CHANGES.txt
deleted file mode 100644
index 2bac1c867..000000000
--- a/contrib/python/podman/CHANGES.txt
+++ /dev/null
@@ -1 +0,0 @@
-v0.1.0, 2018-05-11 -- Initial release.
diff --git a/contrib/python/podman/LICENSE.txt b/contrib/python/podman/LICENSE.txt
deleted file mode 100644
index decfce56d..000000000
--- a/contrib/python/podman/LICENSE.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2018 Red Hat, Inc
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/contrib/python/podman/MANIFEST.in b/contrib/python/podman/MANIFEST.in
deleted file mode 100644
index a5897de50..000000000
--- a/contrib/python/podman/MANIFEST.in
+++ /dev/null
@@ -1,3 +0,0 @@
-prune test/
-include README.md
-include requirements.txt
diff --git a/contrib/python/podman/Makefile b/contrib/python/podman/Makefile
deleted file mode 100644
index 0cbfe2fb3..000000000
--- a/contrib/python/podman/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python)
-DESTDIR ?= /
-PODMAN_VERSION ?= '0.11.1.1'
-
-.PHONY: python-podman
-python-podman:
- PODMAN_VERSION=$(PODMAN_VERSION) \
- $(PYTHON) setup.py sdist bdist
-
-.PHONY: lint
-lint:
- $(PYTHON) -m pylint podman
-
-.PHONY: integration
-integration:
- test/test_runner.sh -v
-
-.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 --verbose --repository-url https://test.pypi.org/legacy/ dist/*
-
-.PHONY: clobber
-clobber: uninstall clean
-
-.PHONY: uninstall
-uninstall:
- $(PYTHON) -m pip uninstall --yes podman ||:
-
-.PHONY: clean
-clean:
- rm -rf podman.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/podman/README.md b/contrib/python/podman/README.md
deleted file mode 100644
index 3254064b0..000000000
--- a/contrib/python/podman/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# podman - pythonic library for working with varlink interface to Podman
-
-## Status: Active Development
-
-See [libpod](https://github.com/containers/libpod)
-
-## Releases
-
-To build the podman egg and install as user:
-
-```sh
-cd ~/libpod/contrib/python/podman
-python3 setup.py clean -a && python3 setup.py sdist bdist
-python3 setup.py install --user
-```
-
-## Code snippets/examples:
-
-### Show images in storage
-
-```python
-import podman
-
-with podman.Client() as client:
- list(map(print, client.images.list()))
-```
-
-### Show containers created since midnight
-
-```python
-from datetime import datetime, time, timezone
-
-import podman
-
-midnight = datetime.combine(datetime.today(), time.min, tzinfo=timezone.utc)
-
-with podman.Client() as client:
- for c in client.containers.list():
- created_at = podman.datetime_parse(c.createdat)
-
- if created_at > midnight:
- print('Container {}: image: {} created at: {}'.format(
- c.id[:12], c.image[:32], podman.datetime_format(created_at)))
-```
diff --git a/contrib/python/podman/examples/eg_attach.py b/contrib/python/podman/examples/eg_attach.py
deleted file mode 100644
index f5070dc53..000000000
--- a/contrib/python/podman/examples/eg_attach.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Run top on Alpine container."""
-
-import podman
-
-print('{}\n'.format(__doc__))
-
-with podman.Client() as client:
- id = client.images.pull('alpine:latest')
- img = client.images.get(id)
- cntr = img.create(detach=True, tty=True, command=['/usr/bin/top'])
- cntr.attach(eot=4)
-
- try:
- cntr.start()
- print()
- except (BrokenPipeError, KeyboardInterrupt):
- print('\nContainer disconnected.')
diff --git a/contrib/python/podman/examples/eg_containers_by_image.py b/contrib/python/podman/examples/eg_containers_by_image.py
deleted file mode 100644
index bf4fdebf1..000000000
--- a/contrib/python/podman/examples/eg_containers_by_image.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Show containers grouped by image id."""
-
-from itertools import groupby
-
-import podman
-
-print('{}\n'.format(__doc__))
-
-with podman.Client() as client:
- ctnrs = sorted(client.containers.list(), key=lambda k: k.imageid)
- for key, grp in groupby(ctnrs, key=lambda k: k.imageid):
- print('Image: {}'.format(key))
- for c in grp:
- print(' : container: {} created at: {}'.format(
- c.id[:12], podman.datetime_format(c.createdat)))
diff --git a/contrib/python/podman/examples/eg_image_list.py b/contrib/python/podman/examples/eg_image_list.py
deleted file mode 100644
index ef31fd708..000000000
--- a/contrib/python/podman/examples/eg_image_list.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Show all images on system."""
-
-import podman
-
-print('{}\n'.format(__doc__))
-
-with podman.Client() as client:
- for img in client.images.list():
- print(img)
diff --git a/contrib/python/podman/examples/eg_inspect_fedora.py b/contrib/python/podman/examples/eg_inspect_fedora.py
deleted file mode 100644
index b5bbba46d..000000000
--- a/contrib/python/podman/examples/eg_inspect_fedora.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Pull Fedora and inspect image and container."""
-
-import podman
-
-print('{}\n'.format(__doc__))
-
-with podman.Client() as client:
- id = client.images.pull('registry.fedoraproject.org/fedora:28')
- img = client.images.get(id)
- print(img.inspect())
-
- cntr = img.create()
- print(cntr.inspect())
-
- cntr.remove()
diff --git a/contrib/python/podman/examples/eg_latest_containers.py b/contrib/python/podman/examples/eg_latest_containers.py
deleted file mode 100644
index 446f670dd..000000000
--- a/contrib/python/podman/examples/eg_latest_containers.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Show all containers created since midnight."""
-
-from datetime import datetime, time, timezone
-
-import podman
-
-print('{}\n'.format(__doc__))
-
-
-midnight = datetime.combine(datetime.today(), time.min, tzinfo=timezone.utc)
-
-with podman.Client() as client:
- for c in client.containers.list():
- created_at = podman.datetime_parse(c.createdat)
-
- if created_at > midnight:
- print('{}: image: {} createdAt: {}'.format(
- c.id[:12], c.image[:32], podman.datetime_format(created_at)))
diff --git a/contrib/python/podman/examples/eg_new_image.py b/contrib/python/podman/examples/eg_new_image.py
deleted file mode 100644
index 21e076dcb..000000000
--- a/contrib/python/podman/examples/eg_new_image.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-"""Example: Create new image from container."""
-
-import sys
-
-import podman
-
-
-def print_history(details):
- """Format history data from an image, in a table."""
- for i, r in enumerate(details):
- print(
- '{}: {} {} {}'.format(i, r.id[:12],
- podman.datetime_format(r.created), r.tags),
- sep='\n')
- print("-" * 25)
-
-
-print('{}\n'.format(__doc__))
-
-with podman.Client() as client:
- ctnr = next(
- (c for c in client.containers.list() if 'alpine' in c['image']), None)
-
- if ctnr:
- print_history(client.images.get(ctnr.imageid).history())
-
- # Make changes as we save the container to a new image
- id = ctnr.commit('alpine-ash', changes=['CMD=/bin/ash'])
- print_history(client.images.get(id).history())
- else:
- print('Unable to find "alpine" container.', file=sys.stderr)
diff --git a/contrib/python/podman/examples/run_example.sh b/contrib/python/podman/examples/run_example.sh
deleted file mode 100755
index d81ddf456..000000000
--- a/contrib/python/podman/examples/run_example.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-export PYTHONPATH=..
-
-function examples {
- for file in $@; do
- python3 -c "import ast; f=open('"${file}"'); t=ast.parse(f.read()); print(ast.get_docstring(t) + ' -- "${file}"')"
- done
-}
-
-while getopts "lh" arg; do
- case $arg in
- l ) examples $(ls eg_*.py); exit 0 ;;
- h ) echo 1>&2 $0 [-l] [-h] filename ; exit 2 ;;
- esac
-done
-shift $((OPTIND-1))
-
-# podman needs to play some games with resources
-if [[ $(id -u) != 0 ]]; then
- echo 1>&2 $0 must be run as root.
- exit 2
-fi
-
-if ! systemctl --quiet is-active io.podman.socket; then
- echo 1>&2 'podman is not running. systemctl enable --now io.podman.socket'
- exit 1
-fi
-
-function cleanup {
- podman rm $1 >/dev/null 2>&1
-}
-
-# Setup storage with an image and container
-podman pull alpine:latest >/tmp/podman.output 2>&1
-CTNR=$(podman create alpine)
-trap "cleanup $CTNR" EXIT
-
-if [[ -f $1 ]]; then
- python3 $1
-else
- python3 $1.py
-fi
diff --git a/contrib/python/podman/podman/__init__.py b/contrib/python/podman/podman/__init__.py
deleted file mode 100644
index 1cdb72773..000000000
--- a/contrib/python/podman/podman/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""A client for communicating with a Podman server."""
-import pkg_resources
-
-from .client import Client
-from .libs import FoldedString, datetime_format, datetime_parse
-from .libs.errors import (ContainerNotFound, ErrorOccurred, ImageNotFound,
- NoContainerRunning, NoContainersInPod,
- PodContainerError, PodmanError, PodNotFound)
-
-assert FoldedString
-
-try:
- __version__ = pkg_resources.get_distribution('podman').version
-except Exception: # pylint: disable=broad-except
- __version__ = '0.0.0'
-
-__all__ = [
- 'Client',
- 'ContainerNotFound',
- 'datetime_format',
- 'datetime_parse',
- 'ErrorOccurred',
- 'ImageNotFound',
- 'NoContainerRunning',
- 'NoContainersInPod',
- 'PodContainerError',
- 'PodmanError',
- 'PodNotFound',
-]
diff --git a/contrib/python/podman/podman/client.py b/contrib/python/podman/podman/client.py
deleted file mode 100644
index ad603166e..000000000
--- a/contrib/python/podman/podman/client.py
+++ /dev/null
@@ -1,212 +0,0 @@
-"""A client for communicating with a Podman varlink service."""
-import errno
-import logging
-import os
-from urllib.parse import urlparse
-
-from varlink import Client as VarlinkClient
-from varlink import VarlinkError
-
-from .libs import cached_property
-from .libs.containers import Containers
-from .libs.errors import error_factory
-from .libs.images import Images
-from .libs.system import System
-from .libs.tunnel import Context, Portal, Tunnel
-from .libs.pods import Pods
-
-
-class BaseClient():
- """Context manager for API workers to access varlink."""
-
- def __init__(self, context):
- """Construct Client."""
- self._client = None
- self._iface = None
- self._context = context
-
- def __call__(self):
- """Support being called for old API."""
- return self
-
- @classmethod
- def factory(cls,
- uri=None,
- interface='io.podman',
- *args,
- **kwargs):
- """Construct a Client based on input."""
- log_level = os.environ.get('LOG_LEVEL')
- if log_level is not None:
- logging.basicConfig(level=logging.getLevelName(log_level.upper()))
-
- if uri is None:
- raise ValueError('uri is required and cannot be None')
- if interface is None:
- raise ValueError('interface is required and cannot be None')
-
- unsupported = set(kwargs.keys()).difference(
- ('uri', 'interface', 'remote_uri', 'identity_file'))
- if unsupported:
- raise ValueError('Unknown keyword arguments: {}'.format(
- ', '.join(unsupported)))
-
- local_path = urlparse(uri).path
- if local_path == '':
- raise ValueError('path is required for uri,'
- ' expected format "unix://path_to_socket"')
-
- if kwargs.get('remote_uri') is None:
- return LocalClient(Context(uri, interface))
-
- required = ('{} is required, expected format'
- ' "ssh://user@hostname[:port]/path_to_socket".')
-
- # Remote access requires the full tuple of information
- if kwargs.get('remote_uri') is None:
- raise ValueError(required.format('remote_uri'))
-
- remote = urlparse(kwargs['remote_uri'])
- if remote.username is None:
- raise ValueError(required.format('username'))
- if remote.path == '':
- raise ValueError(required.format('path'))
- if remote.hostname is None:
- raise ValueError(required.format('hostname'))
-
- return RemoteClient(
- Context(
- uri,
- interface,
- local_path,
- remote.path,
- remote.username,
- remote.hostname,
- remote.port,
- kwargs.get('identity_file'),
- ))
-
-
-class LocalClient(BaseClient):
- """Context manager for API workers to access varlink."""
-
- def __enter__(self):
- """Enter context for LocalClient."""
- self._client = VarlinkClient(address=self._context.uri)
- self._iface = self._client.open(self._context.interface)
- return self._iface
-
- def __exit__(self, e_type, e, e_traceback):
- """Cleanup context for LocalClient."""
- if hasattr(self._client, 'close'):
- self._client.close()
- self._iface.close()
-
- if isinstance(e, VarlinkError):
- raise error_factory(e)
-
-
-class RemoteClient(BaseClient):
- """Context manager for API workers to access remote varlink."""
-
- def __init__(self, context):
- """Construct RemoteCLient."""
- super().__init__(context)
- self._portal = Portal()
-
- def __enter__(self):
- """Context manager for API workers to access varlink."""
- tunnel = self._portal.get(self._context.uri)
- if tunnel is None:
- tunnel = Tunnel(self._context).bore()
- self._portal[self._context.uri] = tunnel
-
- try:
- self._client = VarlinkClient(address=self._context.uri)
- self._iface = self._client.open(self._context.interface)
- return self._iface
- except Exception:
- tunnel.close()
- raise
-
- def __exit__(self, e_type, e, e_traceback):
- """Cleanup context for RemoteClient."""
- if hasattr(self._client, 'close'):
- self._client.close()
- self._iface.close()
-
- # set timer to shutdown ssh tunnel
- # self._portal.get(self._context.uri).close()
- if isinstance(e, VarlinkError):
- raise error_factory(e)
-
-
-class Client():
- """A client for communicating with a Podman varlink service.
-
- Example:
-
- >>> import podman
- >>> c = podman.Client()
- >>> c.system.versions
-
- Example remote podman:
-
- >>> import podman
- >>> c = podman.Client(uri='unix:/tmp/podman.sock',
- remote_uri='ssh://user@host/run/podman/io.podman',
- identity_file='~/.ssh/id_rsa')
- """
-
- def __init__(self,
- uri='unix:/run/podman/io.podman',
- interface='io.podman',
- **kwargs):
- """Construct a podman varlink Client.
-
- uri from default systemd unit file.
- interface from io.podman.varlink, do not change unless
- you are a varlink guru.
- """
- self._client = BaseClient.factory(uri, interface, **kwargs)
-
- address = "{}-{}".format(uri, interface)
- # Quick validation of connection data provided
- try:
- if not System(self._client).ping():
- raise ConnectionRefusedError(
- errno.ECONNREFUSED,
- ('Failed varlink connection "{}"').format(address))
- except FileNotFoundError:
- raise ConnectionError(
- errno.ECONNREFUSED,
- ('Failed varlink connection "{}".'
- ' Is podman socket or service running?').format(address))
-
- def __enter__(self):
- """Return `self` upon entering the runtime context."""
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- """Raise any exception triggered within the runtime context."""
- pass
-
- @cached_property
- def system(self):
- """Manage system model for podman."""
- return System(self._client)
-
- @cached_property
- def images(self):
- """Manage images model for libpod."""
- return Images(self._client)
-
- @cached_property
- def containers(self):
- """Manage containers model for libpod."""
- return Containers(self._client)
-
- @cached_property
- def pods(self):
- """Manage pods model for libpod."""
- return Pods(self._client)
diff --git a/contrib/python/podman/podman/libs/__init__.py b/contrib/python/podman/podman/libs/__init__.py
deleted file mode 100644
index 5193313ed..000000000
--- a/contrib/python/podman/podman/libs/__init__.py
+++ /dev/null
@@ -1,75 +0,0 @@
-"""Support files for podman API implementation."""
-import collections
-import datetime
-import functools
-
-from dateutil.parser import parse as dateutil_parse
-
-__all__ = [
- 'cached_property',
- 'datetime_format',
- 'datetime_parse',
- 'fold_keys',
-]
-
-
-def cached_property(fn):
- """Decorate property to cache return value."""
- return property(functools.lru_cache(maxsize=8)(fn))
-
-
-class ConfigDict(collections.UserDict):
- """Silently ignore None values, only take key once."""
-
- def __init__(self, **kwargs):
- """Construct dictionary."""
- super().__init__(kwargs)
-
- def __setitem__(self, key, value):
- """Store unique, not None values."""
- if value is None:
- return
-
- if super().__contains__(key):
- return
-
- super().__setitem__(key, value)
-
-
-class FoldedString(collections.UserString):
- """Foldcase sequences value."""
-
- def __init__(self, seq):
- super().__init__(seq)
- self.data.casefold()
-
-
-def fold_keys(): # noqa: D202
- """Fold case of dictionary keys."""
-
- @functools.wraps(fold_keys)
- def wrapped(mapping):
- """Fold case of dictionary keys."""
- return {k.casefold(): v for (k, v) in mapping.items()}
-
- return wrapped
-
-
-def datetime_parse(string):
- """Convert timestamps to datetime.
-
- tzinfo aware, if provided.
- """
- return dateutil_parse(string.upper(), fuzzy=True)
-
-
-def datetime_format(dt):
- """Format datetime in consistent style."""
- if isinstance(dt, str):
- return datetime_parse(dt).isoformat()
-
- if isinstance(dt, datetime.datetime):
- return dt.isoformat()
-
- raise ValueError('Unable to format {}. Type {} not supported.'.format(
- dt, type(dt)))
diff --git a/contrib/python/podman/podman/libs/_containers_attach.py b/contrib/python/podman/podman/libs/_containers_attach.py
deleted file mode 100644
index 94247d349..000000000
--- a/contrib/python/podman/podman/libs/_containers_attach.py
+++ /dev/null
@@ -1,79 +0,0 @@
-"""Exported method Container.attach()."""
-
-import collections
-import fcntl
-import logging
-import struct
-import sys
-import termios
-
-
-class Mixin:
- """Publish attach() for inclusion in Container class."""
-
- def attach(self, eot=4, stdin=None, stdout=None):
- """Attach to container's PID1 stdin and stdout.
-
- stderr is ignored.
- PseudoTTY work is done in start().
- """
- if stdin is None:
- stdin = sys.stdin.fileno()
- elif hasattr(stdin, 'fileno'):
- stdin = stdin.fileno()
-
- if stdout is None:
- stdout = sys.stdout.fileno()
- elif hasattr(stdout, 'fileno'):
- stdout = stdout.fileno()
-
- with self._client() as podman:
- attach = podman.GetAttachSockets(self._id)
-
- # This is the UDS where all the IO goes
- io_socket = attach['sockets']['io_socket']
- assert len(io_socket) <= 107,\
- 'Path length for sockets too long. {} > 107'.format(
- len(io_socket)
- )
-
- # This is the control socket where resizing events are sent to conmon
- # attach['sockets']['control_socket']
- self.pseudo_tty = collections.namedtuple(
- 'PseudoTTY',
- ['stdin', 'stdout', 'io_socket', 'control_socket', 'eot'])(
- stdin,
- stdout,
- attach['sockets']['io_socket'],
- attach['sockets']['control_socket'],
- eot,
- )
-
- @property
- def resize_handler(self):
- """Send the new window size to conmon."""
-
- def wrapped(signum, frame): # pylint: disable=unused-argument
- packed = fcntl.ioctl(self.pseudo_tty.stdout, termios.TIOCGWINSZ,
- struct.pack('HHHH', 0, 0, 0, 0))
- rows, cols, _, _ = struct.unpack('HHHH', packed)
- logging.debug('Resize window(%dx%d) using %s', rows, cols,
- self.pseudo_tty.control_socket)
-
- # TODO: Need some kind of timeout in case pipe is blocked
- with open(self.pseudo_tty.control_socket, 'w') as skt:
- # send conmon window resize message
- skt.write('1 {} {}\n'.format(rows, cols))
-
- return wrapped
-
- @property
- def log_handler(self):
- """Send command to reopen log to conmon."""
-
- def wrapped(signum, frame): # pylint: disable=unused-argument
- with open(self.pseudo_tty.control_socket, 'w') as skt:
- # send conmon reopen log message
- skt.write('2\n')
-
- return wrapped
diff --git a/contrib/python/podman/podman/libs/_containers_start.py b/contrib/python/podman/podman/libs/_containers_start.py
deleted file mode 100644
index 20130f5d6..000000000
--- a/contrib/python/podman/podman/libs/_containers_start.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""Exported method Container.start()."""
-import logging
-import os
-import select
-import signal
-import socket
-import sys
-import termios
-import tty
-
-CONMON_BUFSZ = 8192
-
-
-class Mixin:
- """Publish start() for inclusion in Container class."""
-
- def start(self):
- """Start container, return container on success.
-
- Will block if container has been detached.
- """
- with self._client() as podman:
- logging.debug('Starting Container "%s"', self._id)
- results = podman.StartContainer(self._id)
- logging.debug('Started Container "%s"', results['container'])
-
- if not hasattr(self, 'pseudo_tty') or self.pseudo_tty is None:
- return self._refresh(podman)
-
- logging.debug('Setting up PseudoTTY for Container "%s"',
- results['container'])
-
- try:
- # save off the old settings for terminal
- tcoldattr = termios.tcgetattr(self.pseudo_tty.stdin)
- tty.setraw(self.pseudo_tty.stdin)
-
- # initialize container's window size
- self.resize_handler(None, sys._getframe(0))
-
- # catch any resizing events and send the resize info
- # to the control fifo "socket"
- signal.signal(signal.SIGWINCH, self.resize_handler)
-
- except termios.error:
- tcoldattr = None
-
- try:
- # TODO: Is socket.SOCK_SEQPACKET supported in Windows?
- with socket.socket(socket.AF_UNIX,
- socket.SOCK_SEQPACKET) as skt:
- # Prepare socket for use with conmon/container
- skt.connect(self.pseudo_tty.io_socket)
-
- sources = [skt, self.pseudo_tty.stdin]
- while sources:
- logging.debug('Waiting on sources: %s', sources)
- readable, _, _ = select.select(sources, [], [])
-
- if skt in readable:
- data = skt.recv(CONMON_BUFSZ)
- if data:
- # Remove source marker when writing
- os.write(self.pseudo_tty.stdout, data[1:])
- else:
- sources.remove(skt)
-
- if self.pseudo_tty.stdin in readable:
- data = os.read(self.pseudo_tty.stdin, CONMON_BUFSZ)
- if data:
- skt.sendall(data)
-
- if self.pseudo_tty.eot in data:
- sources.clear()
- else:
- sources.remove(self.pseudo_tty.stdin)
- finally:
- if tcoldattr:
- termios.tcsetattr(self.pseudo_tty.stdin, termios.TCSADRAIN,
- tcoldattr)
- signal.signal(signal.SIGWINCH, signal.SIG_DFL)
- return self._refresh(podman)
diff --git a/contrib/python/podman/podman/libs/containers.py b/contrib/python/podman/podman/libs/containers.py
deleted file mode 100644
index 7adecea8f..000000000
--- a/contrib/python/podman/podman/libs/containers.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"""Models for manipulating containers and storage."""
-import collections
-import getpass
-import json
-import logging
-import signal
-import time
-
-from . import fold_keys
-from ._containers_attach import Mixin as AttachMixin
-from ._containers_start import Mixin as StartMixin
-
-
-class Container(AttachMixin, StartMixin, collections.UserDict):
- """Model for a container."""
-
- def __init__(self, client, ident, data, refresh=True):
- """Construct Container Model."""
- super(Container, self).__init__(data)
- self._client = client
- self._id = ident
-
- if refresh:
- with client() as podman:
- self._refresh(podman)
- else:
- for k, v in self.data.items():
- setattr(self, k, v)
- if 'containerrunning' in self.data:
- setattr(self, 'running', self.data['containerrunning'])
- self.data['running'] = self.data['containerrunning']
-
- assert self._id == data['id'],\
- 'Requested container id({}) does not match store id({})'.format(
- self._id, data['id']
- )
-
- def _refresh(self, podman, tries=1):
- try:
- ctnr = podman.GetContainer(self._id)
- except BrokenPipeError:
- logging.debug('Failed GetContainer(%s) try %d/3', self._id, tries)
- if tries > 3:
- raise
- else:
- with self._client() as pman:
- self._refresh(pman, tries + 1)
- else:
- super().update(ctnr['container'])
-
- for k, v in self.data.items():
- setattr(self, k, v)
- if 'containerrunning' in self.data:
- setattr(self, 'running', self.data['containerrunning'])
- self.data['running'] = self.data['containerrunning']
-
- return self
-
- def refresh(self):
- """Refresh status fields for this container."""
- with self._client() as podman:
- return self._refresh(podman)
-
- def processes(self):
- """Show processes running in container."""
- with self._client() as podman:
- results = podman.ListContainerProcesses(self._id)
- yield from results['container']
-
- def changes(self):
- """Retrieve container changes."""
- with self._client() as podman:
- results = podman.ListContainerChanges(self._id)
- return results['container']
-
- def kill(self, sig=signal.SIGTERM, wait=25):
- """Send signal to container.
-
- default signal is signal.SIGTERM.
- wait n of seconds, 0 waits forever.
- """
- with self._client() as podman:
- podman.KillContainer(self._id, sig)
- timeout = time.time() + wait
- while True:
- self._refresh(podman)
- if self.status != 'running': # pylint: disable=no-member
- return self
-
- if wait and timeout < time.time():
- raise TimeoutError()
-
- time.sleep(0.5)
-
- def inspect(self):
- """Retrieve details about containers."""
- with self._client() as podman:
- results = podman.InspectContainer(self._id)
- obj = json.loads(results['container'], object_hook=fold_keys())
- return collections.namedtuple('ContainerInspect', obj.keys())(**obj)
-
- def export(self, target):
- """Export container from store to tarball.
-
- TODO: should there be a compress option, like images?
- """
- with self._client() as podman:
- results = podman.ExportContainer(self._id, target)
- return results['tarfile']
-
- def commit(self, image_name, **kwargs):
- """Create image from container.
-
- Keyword arguments:
- author -- change image's author
- message -- change image's message, docker format only.
- pause -- pause container during commit
- change -- Additional properties to change
-
- Change examples:
- CMD=/usr/bin/zsh
- ENTRYPOINT=/bin/sh date
- ENV=TEST=test_containers.TestContainers.test_commit
- EXPOSE=8888/tcp
- LABEL=unittest=test_commit
- USER=bozo:circus
- VOLUME=/data
- WORKDIR=/data/application
-
- All changes overwrite existing values.
- See inspect() to obtain current settings.
- """
- author = kwargs.get('author', None) or getpass.getuser()
- change = kwargs.get('change', None) or []
- message = kwargs.get('message', None) or ''
- pause = kwargs.get('pause', None) or True
-
- for c in change:
- if c.startswith('LABEL=') and c.count('=') < 2:
- raise ValueError(
- 'LABEL should have the format: LABEL=label=value, not {}'.
- format(c))
-
- with self._client() as podman:
- results = podman.Commit(self._id, image_name, change, author,
- message, pause)
- return results['image']
-
- def stop(self, timeout=25):
- """Stop container, return id on success."""
- with self._client() as podman:
- podman.StopContainer(self._id, timeout)
- return self._refresh(podman)
-
- def remove(self, force=False):
- """Remove container, return id on success.
-
- force=True, stop running container.
- """
- with self._client() as podman:
- results = podman.RemoveContainer(self._id, force)
- return results['container']
-
- def restart(self, timeout=25):
- """Restart container with timeout, return id on success."""
- with self._client() as podman:
- podman.RestartContainer(self._id, timeout)
- return self._refresh(podman)
-
- def rename(self, target): # pylint: disable=unused-argument
- """Rename container, return id on success."""
- with self._client() as podman:
- # TODO: Need arguments
- results = podman.RenameContainer()
- # TODO: fixup objects cached information
- return results['container']
-
- def resize_tty(self, width, height): # pylint: disable=unused-argument
- """Resize container tty."""
- with self._client() as podman:
- # TODO: magic re: attach(), arguments
- podman.ResizeContainerTty()
-
- def pause(self):
- """Pause container, return id on success."""
- with self._client() as podman:
- podman.PauseContainer(self._id)
- return self._refresh(podman)
-
- def unpause(self):
- """Unpause container, return id on success."""
- with self._client() as podman:
- podman.UnpauseContainer(self._id)
- return self._refresh(podman)
-
- def update_container(self, *args, **kwargs): \
- # pylint: disable=unused-argument
- """TODO: Update container..., return id on success."""
- with self._client() as podman:
- podman.UpdateContainer()
- return self._refresh(podman)
-
- def wait(self):
- """Wait for container to finish, return 'returncode'."""
- with self._client() as podman:
- results = podman.WaitContainer(self._id)
- return int(results['exitcode'])
-
- def stats(self):
- """Retrieve resource stats from the container."""
- with self._client() as podman:
- results = podman.GetContainerStats(self._id)
- obj = results['container']
- return collections.namedtuple('StatDetail', obj.keys())(**obj)
-
- def logs(self, *args, **kwargs): # pylint: disable=unused-argument
- """Retrieve container logs."""
- with self._client() as podman:
- results = podman.GetContainerLogs(self._id)
- yield from results['container']
-
-
-class Containers():
- """Model for Containers collection."""
-
- def __init__(self, client):
- """Construct model for Containers collection."""
- self._client = client
-
- def list(self):
- """List of containers in the container store."""
- with self._client() as podman:
- results = podman.ListContainers()
- for cntr in results['containers']:
- yield Container(self._client, cntr['id'], cntr, refresh=False)
-
- def delete_stopped(self):
- """Delete all stopped containers."""
- with self._client() as podman:
- results = podman.DeleteStoppedContainers()
- return results['containers']
-
- def get(self, id_):
- """Retrieve container details from store."""
- with self._client() as podman:
- cntr = podman.GetContainer(id_)
- return Container(self._client, cntr['container']['id'],
- cntr['container'])
diff --git a/contrib/python/podman/podman/libs/errors.py b/contrib/python/podman/podman/libs/errors.py
deleted file mode 100644
index 2821d3597..000000000
--- a/contrib/python/podman/podman/libs/errors.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""Error classes and wrappers for VarlinkError."""
-from varlink import VarlinkError
-
-
-class VarlinkErrorProxy(VarlinkError):
- """Class to Proxy VarlinkError methods."""
-
- def __init__(self, message, namespaced=False):
- """Construct proxy from Exception."""
- super().__init__(message.as_dict(), namespaced)
- self._message = message
- self.__module__ = 'libpod'
-
- def __getattr__(self, method):
- """Return attribute from proxied Exception."""
- if hasattr(self._message, method):
- return getattr(self._message, method)
-
- try:
- return self._message.parameters()[method]
- except KeyError:
- raise AttributeError('No such attribute: {}'.format(method))
-
-
-class ContainerNotFound(VarlinkErrorProxy):
- """Raised when Client cannot find requested container."""
-
-
-class ImageNotFound(VarlinkErrorProxy):
- """Raised when Client cannot find requested image."""
-
-
-class PodNotFound(VarlinkErrorProxy):
- """Raised when Client cannot find requested image."""
-
-
-class PodContainerError(VarlinkErrorProxy):
- """Raised when a container fails requested pod operation."""
-
-
-class NoContainerRunning(VarlinkErrorProxy):
- """Raised when no container is running in pod."""
-
-
-class NoContainersInPod(VarlinkErrorProxy):
- """Raised when Client fails to connect to runtime."""
-
-
-class ErrorOccurred(VarlinkErrorProxy):
- """Raised when an error occurs during the execution.
-
- See error() to see actual error text.
- """
-
-
-class PodmanError(VarlinkErrorProxy):
- """Raised when Client fails to connect to runtime."""
-
-
-ERROR_MAP = {
- 'io.podman.ContainerNotFound': ContainerNotFound,
- 'io.podman.ErrorOccurred': ErrorOccurred,
- 'io.podman.ImageNotFound': ImageNotFound,
- 'io.podman.NoContainerRunning': NoContainerRunning,
- 'io.podman.NoContainersInPod': NoContainersInPod,
- 'io.podman.PodContainerError': PodContainerError,
- 'io.podman.PodNotFound': PodNotFound,
- 'io.podman.RuntimeError': PodmanError,
-}
-
-
-def error_factory(exception):
- """Map Exceptions to a discrete type."""
- try:
- return ERROR_MAP[exception.error()](exception)
- except KeyError:
- return exception
diff --git a/contrib/python/podman/podman/libs/images.py b/contrib/python/podman/podman/libs/images.py
deleted file mode 100644
index 29ebe2c0f..000000000
--- a/contrib/python/podman/podman/libs/images.py
+++ /dev/null
@@ -1,164 +0,0 @@
-"""Models for manipulating images in/to/from storage."""
-import collections
-import copy
-import json
-import logging
-
-from . import ConfigDict, fold_keys
-from .containers import Container
-
-
-class Image(collections.UserDict):
- """Model for an Image."""
-
- def __init__(self, client, id, data):
- """Construct Image Model."""
- super().__init__(data)
- for k, v in data.items():
- setattr(self, k, v)
-
- self._id = id
- self._client = client
-
- assert self._id == data['id'],\
- 'Requested image id({}) does not match store id({})'.format(
- self._id, data['id']
- )
-
- @staticmethod
- def _split_token(values=None, sep='='):
- if not values:
- return {}
- return {
- k: v1 for k, v1 in (v0.split(sep, 1) for v0 in values)
- }
-
- def create(self, *args, **kwargs):
- """Create container from image.
-
- Pulls defaults from image.inspect()
- """
- details = self.inspect()
-
- config = ConfigDict(image_id=self._id, **kwargs)
- config['command'] = details.config.get('cmd')
- config['env'] = self._split_token(details.config.get('env'))
- config['image'] = copy.deepcopy(details.repotags[0])
- config['labels'] = copy.deepcopy(details.labels)
- config['net_mode'] = 'bridge'
- config['network'] = 'bridge'
-
- logging.debug('Image %s: create config: %s', self._id, config)
- with self._client() as podman:
- id_ = podman.CreateContainer(config)['container']
- cntr = podman.GetContainer(id_)
- return Container(self._client, id_, cntr['container'])
-
- container = create
-
- def export(self, dest, compressed=False):
- """Write image to dest, return id on success."""
- with self._client() as podman:
- results = podman.ExportImage(self._id, dest, compressed)
- return results['image']
-
- def history(self):
- """Retrieve image history."""
- with self._client() as podman:
- for r in podman.HistoryImage(self._id)['history']:
- yield collections.namedtuple('HistoryDetail', r.keys())(**r)
-
- def inspect(self):
- """Retrieve details about image."""
- with self._client() as podman:
- results = podman.InspectImage(self._id)
- obj = json.loads(results['image'], object_hook=fold_keys())
- return collections.namedtuple('ImageInspect', obj.keys())(**obj)
-
- def push(self, target, tlsverify=True):
- """Copy image to target, return id on success."""
- with self._client() as podman:
- results = podman.PushImage(self._id, target, tlsverify)
- return results['image']
-
- def remove(self, force=False):
- """Delete image, return id on success.
-
- force=True, stop any running containers using image.
- """
- with self._client() as podman:
- results = podman.RemoveImage(self._id, force)
- return results['image']
-
- def tag(self, tag):
- """Tag image."""
- with self._client() as podman:
- results = podman.TagImage(self._id, tag)
- return results['image']
-
-
-class Images():
- """Model for Images collection."""
-
- def __init__(self, client):
- """Construct model for Images collection."""
- self._client = client
-
- def list(self):
- """List all images in the libpod image store."""
- with self._client() as podman:
- results = podman.ListImages()
- for img in results['images']:
- yield Image(self._client, img['id'], img)
-
- def build(self, dockerfile=None, tags=None, **kwargs):
- """Build container from image.
-
- See podman-build.1.md for kwargs details.
- """
- if dockerfile is None:
- raise ValueError('"dockerfile" is a required argument.')
- elif not hasattr(dockerfile, '__iter__'):
- raise ValueError('"dockerfile" is required to be an iter.')
-
- if tags is None:
- raise ValueError('"tags" is a required argument.')
- elif not hasattr(tags, '__iter__'):
- raise ValueError('"tags" is required to be an iter.')
-
- config = ConfigDict(dockerfile=dockerfile, tags=tags, **kwargs)
- with self._client() as podman:
- result = podman.BuildImage(config)
- return self.get(result['image']['id']), \
- (line for line in result['image']['logs'])
-
- def delete_unused(self):
- """Delete Images not associated with a container."""
- with self._client() as podman:
- results = podman.DeleteUnusedImages()
- return results['images']
-
- def import_image(self, source, reference, message='', changes=None):
- """Read image tarball from source and save in image store."""
- with self._client() as podman:
- results = podman.ImportImage(source, reference, message, changes)
- return results['image']
-
- def pull(self, source):
- """Copy image from registry to image store."""
- with self._client() as podman:
- results = podman.PullImage(source)
- return results['id']
-
- def search(self, id_, limit=25):
- """Search registries for id."""
- with self._client() as podman:
- results = podman.SearchImage(id_, limit)
- for img in results['images']:
- yield collections.namedtuple('ImageSearch', img.keys())(**img)
-
- def get(self, id_):
- """Get Image from id."""
- with self._client() as podman:
- result = podman.GetImage(id_)
- return Image(self._client, result['image']['id'], result['image'])
diff --git a/contrib/python/podman/podman/libs/pods.py b/contrib/python/podman/podman/libs/pods.py
deleted file mode 100644
index 2a85f2624..000000000
--- a/contrib/python/podman/podman/libs/pods.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""Model for accessing details of Pods from podman service."""
-import collections
-import json
-import signal
-import time
-
-from . import ConfigDict, FoldedString, fold_keys
-
-
-class Pod(collections.UserDict):
- """Model for a Pod."""
-
- def __init__(self, client, ident, data):
- """Construct Pod model."""
- super().__init__(data)
-
- self._ident = ident
- self._client = client
-
- with client() as podman:
- self._refresh(podman)
-
- def _refresh(self, podman):
- pod = podman.GetPod(self._ident)
- super().update(pod['pod'])
-
- for k, v in self.data.items():
- setattr(self, k, v)
- return self
-
- def inspect(self):
- """Retrieve details about pod."""
- with self._client() as podman:
- results = podman.InspectPod(self._ident)
- obj = json.loads(results['pod'], object_hook=fold_keys())
- obj['id'] = obj['config']['id']
- return collections.namedtuple('PodInspect', obj.keys())(**obj)
-
- def kill(self, signal_=signal.SIGTERM, wait=25):
- """Send signal to all containers in pod.
-
- default signal is signal.SIGTERM.
- wait n of seconds, 0 waits forever.
- """
- with self._client() as podman:
- podman.KillPod(self._ident, signal_)
- timeout = time.time() + wait
- while True:
- # pylint: disable=maybe-no-member
- self._refresh(podman)
- running = FoldedString(self.status)
- if running != 'running':
- break
-
- if wait and timeout < time.time():
- raise TimeoutError()
-
- time.sleep(0.5)
- return self
-
- def pause(self):
- """Pause all containers in the pod."""
- with self._client() as podman:
- podman.PausePod(self._ident)
- return self._refresh(podman)
-
- def refresh(self):
- """Refresh status fields for this pod."""
- with self._client() as podman:
- return self._refresh(podman)
-
- def remove(self, force=False):
- """Remove pod and its containers returning pod ident.
-
- force=True, stop any running container.
- """
- with self._client() as podman:
- results = podman.RemovePod(self._ident, force)
- return results['pod']
-
- def restart(self):
- """Restart all containers in the pod."""
- with self._client() as podman:
- podman.RestartPod(self._ident)
- return self._refresh(podman)
-
- def stats(self):
- """Stats on all containers in the pod."""
- with self._client() as podman:
- results = podman.GetPodStats(self._ident)
- for obj in results['containers']:
- yield collections.namedtuple('ContainerStats', obj.keys())(**obj)
-
- def start(self):
- """Start all containers in the pod."""
- with self._client() as podman:
- podman.StartPod(self._ident)
- return self._refresh(podman)
-
- def stop(self):
- """Stop all containers in the pod."""
- with self._client() as podman:
- podman.StopPod(self._ident)
- return self._refresh(podman)
-
- def top(self):
- """Display stats for all containers."""
- with self._client() as podman:
- results = podman.TopPod(self._ident)
- return results['pod']
-
- def unpause(self):
- """Unpause all containers in the pod."""
- with self._client() as podman:
- podman.UnpausePod(self._ident)
- return self._refresh(podman)
-
- def wait(self):
- """Wait for all containers to exit."""
- with self._client() as podman:
- results = podman.WaitPod(self._ident)
- return results['pod']
-
-
-class Pods():
- """Model for accessing pods."""
-
- def __init__(self, client):
- """Construct pod model."""
- self._client = client
-
- def create(self,
- ident=None,
- cgroupparent=None,
- labels=None,
- share=None,
- infra=False):
- """Create a new empty pod."""
- config = ConfigDict(
- name=ident,
- cgroupParent=cgroupparent,
- labels=labels,
- share=share,
- infra=infra,
- )
-
- with self._client() as podman:
- result = podman.CreatePod(config)
- details = podman.GetPod(result['pod'])
- return Pod(self._client, result['pod'], details['pod'])
-
- def get(self, ident):
- """Get Pod from ident."""
- with self._client() as podman:
- result = podman.GetPod(ident)
- return Pod(self._client, result['pod']['id'], result['pod'])
-
- def list(self):
- """List all pods."""
- with self._client() as podman:
- results = podman.ListPods()
- for pod in results['pods']:
- yield Pod(self._client, pod['id'], pod)
diff --git a/contrib/python/podman/podman/libs/system.py b/contrib/python/podman/podman/libs/system.py
deleted file mode 100644
index c611341e4..000000000
--- a/contrib/python/podman/podman/libs/system.py
+++ /dev/null
@@ -1,40 +0,0 @@
-"""Models for accessing details from varlink server."""
-import collections
-
-import pkg_resources
-
-from . import cached_property
-
-
-class System():
- """Model for accessing system resources."""
-
- def __init__(self, client):
- """Construct system model."""
- self._client = client
-
- @cached_property
- def versions(self):
- """Access versions."""
- with self._client() as podman:
- vers = podman.GetVersion()['version']
-
- client = '0.0.0'
- try:
- client = pkg_resources.get_distribution('podman').version
- except Exception: # pylint: disable=broad-except
- pass
- vers['client_version'] = client
- return collections.namedtuple('Version', vers.keys())(**vers)
-
- def info(self):
- """Return podman info."""
- with self._client() as podman:
- info = podman.GetInfo()['info']
- return collections.namedtuple('Info', info.keys())(**info)
-
- def ping(self):
- """Return True if server awake."""
- with self._client() as podman:
- response = podman.Ping()
- return response['ping']['message'] == 'OK'
diff --git a/contrib/python/podman/podman/libs/tunnel.py b/contrib/python/podman/podman/libs/tunnel.py
deleted file mode 100644
index ac1dff594..000000000
--- a/contrib/python/podman/podman/libs/tunnel.py
+++ /dev/null
@@ -1,190 +0,0 @@
-"""Cache for SSH tunnels."""
-import collections
-import getpass
-import logging
-import os
-import subprocess
-import threading
-import time
-import weakref
-from contextlib import suppress
-
-import psutil
-
-Context = collections.namedtuple('Context', (
- 'uri',
- 'interface',
- 'local_socket',
- 'remote_socket',
- 'username',
- 'hostname',
- 'port',
- 'identity_file',
-))
-Context.__new__.__defaults__ = (None, ) * len(Context._fields)
-
-
-class Portal(collections.MutableMapping):
- """Expiring container for tunnels."""
-
- def __init__(self, sweap=25):
- """Construct portal, reap tunnels every sweap seconds."""
- self.data = collections.OrderedDict()
- self.sweap = sweap
- self.ttl = sweap * 2
- self.lock = threading.RLock()
- self._schedule_reaper()
-
- def __getitem__(self, key):
- """Given uri return tunnel and update TTL."""
- with self.lock:
- value, _ = self.data[key]
- self.data[key] = (value, time.time() + self.ttl)
- self.data.move_to_end(key)
- return value
-
- def __setitem__(self, key, value):
- """Store given tunnel keyed with uri."""
- if not isinstance(value, Tunnel):
- raise ValueError('Portals only support Tunnels.')
-
- with self.lock:
- self.data[key] = (value, time.time() + self.ttl)
- self.data.move_to_end(key)
-
- def __delitem__(self, key):
- """Remove and close tunnel from portal."""
- with self.lock:
- value, _ = self.data[key]
- del self.data[key]
- value.close()
- del value
-
- def __iter__(self):
- """Iterate tunnels."""
- with self.lock:
- values = self.data.values()
-
- for tunnel, _ in values:
- yield tunnel
-
- def __len__(self):
- """Return number of tunnels in portal."""
- with self.lock:
- return len(self.data)
-
- def _schedule_reaper(self):
- timer = threading.Timer(interval=self.sweap, function=self.reap)
- timer.setName('PortalReaper')
- timer.setDaemon(True)
- timer.start()
-
- def reap(self):
- """Remove tunnels who's TTL has expired."""
- now = time.time()
- with self.lock:
- reaped_data = self.data.copy()
- for entry in reaped_data.items():
- if entry[1][1] < now:
- del self.data[entry[0]]
- else:
- # StopIteration as soon as possible
- break
- self._schedule_reaper()
-
-
-class Tunnel():
- """SSH tunnel."""
-
- def __init__(self, context):
- """Construct Tunnel."""
- self.context = context
- self._closed = True
-
- @property
- def closed(self):
- """Is tunnel closed."""
- return self._closed
-
- def bore(self):
- """Create SSH tunnel from given context."""
- cmd = ['ssh', '-fNT']
-
- if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
- cmd.append('-v')
- else:
- cmd.append('-q')
-
- if self.context.port:
- cmd.extend(('-p', str(self.context.port)))
-
- cmd.extend(('-L', '{}:{}'.format(self.context.local_socket,
- self.context.remote_socket)))
- if self.context.identity_file:
- cmd.extend(('-i', self.context.identity_file))
-
- cmd.append('{}@{}'.format(self.context.username,
- self.context.hostname))
-
- logging.debug('Opening tunnel "%s", cmd "%s"', self.context.uri,
- ' '.join(cmd))
-
- tunnel = subprocess.Popen(cmd, close_fds=True)
- # The return value of Popen() has no long term value as that process
- # has already exited by the time control is returned here. This is a
- # side effect of the -f option. wait() will be called to clean up
- # resources.
- for _ in range(300):
- # TODO: Make timeout configurable
- if os.path.exists(self.context.local_socket) \
- or tunnel.returncode is not None:
- break
- with suppress(subprocess.TimeoutExpired):
- # waiting for either socket to be created
- # or first child to exit
- tunnel.wait(0.5)
- else:
- raise TimeoutError(
- 'Failed to create tunnel "{}", using: "{}"'.format(
- self.context.uri, ' '.join(cmd)))
- if tunnel.returncode is not None and tunnel.returncode != 0:
- raise subprocess.CalledProcessError(tunnel.returncode,
- ' '.join(cmd))
- tunnel.wait()
-
- self._closed = False
- weakref.finalize(self, self.close)
- return self
-
- def close(self):
- """Close SSH tunnel."""
- logging.debug('Closing tunnel "%s"', self.context.uri)
-
- if self._closed:
- return
-
- # Find all ssh instances for user with uri tunnel the hard way...
- targets = [
- p
- for p in psutil.process_iter(attrs=['name', 'username', 'cmdline'])
- if p.info['username'] == getpass.getuser()
- and p.info['name'] == 'ssh'
- and self.context.local_socket in ' '.join(p.info['cmdline'])
- ] # yapf: disable
-
- # ask nicely for ssh to quit, reap results
- for proc in targets:
- proc.terminate()
- _, alive = psutil.wait_procs(targets, timeout=300)
-
- # kill off the uncooperative, then report any stragglers
- for proc in alive:
- proc.kill()
- _, alive = psutil.wait_procs(targets, timeout=300)
-
- for proc in alive:
- logging.info('process %d survived SIGKILL, giving up.', proc.pid)
-
- with suppress(OSError):
- os.remove(self.context.local_socket)
- self._closed = True
diff --git a/contrib/python/podman/requirements.txt b/contrib/python/podman/requirements.txt
deleted file mode 100644
index 1caf5e286..000000000
--- a/contrib/python/podman/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-psutil
-python-dateutil
-setuptools>=39
-varlink
diff --git a/contrib/python/podman/setup.py b/contrib/python/podman/setup.py
deleted file mode 100755
index 9d54bb3ac..000000000
--- a/contrib/python/podman/setup.py
+++ /dev/null
@@ -1,38 +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='podman',
- version=os.environ.get('PODMAN_VERSION', '0.0.0'),
- description='A library for communicating with a Podman server',
- author='Jhon Honce',
- author_email='jhonce@redhat.com',
- license='Apache Software License',
- long_description=readme,
- 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',
- classifiers=[
- 'Development Status :: 3 - Alpha',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Programming Language :: Python :: 3.4',
- 'Topic :: Software Development',
- ])
diff --git a/contrib/python/podman/test/__init__.py b/contrib/python/podman/test/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/contrib/python/podman/test/__init__.py
+++ /dev/null
diff --git a/contrib/python/podman/test/podman_testcase.py b/contrib/python/podman/test/podman_testcase.py
deleted file mode 100644
index da73c1024..000000000
--- a/contrib/python/podman/test/podman_testcase.py
+++ /dev/null
@@ -1,112 +0,0 @@
-"""Base for podman tests."""
-import contextlib
-import functools
-import itertools
-import os
-import subprocess
-import time
-import unittest
-
-from varlink import VarlinkError
-
-MethodNotImplemented = 'org.varlink.service.MethodNotImplemented'
-
-
-class PodmanTestCase(unittest.TestCase):
- """Hide the sausage making of initializing storage."""
-
- @classmethod
- def setUpClass(cls):
- """Fixture to setup podman test case."""
- if hasattr(PodmanTestCase, 'alpine_process'):
- PodmanTestCase.tearDownClass()
-
- def run_cmd(*args):
- cmd = list(itertools.chain(*args))
- try:
- pid = subprocess.Popen(
- cmd,
- close_fds=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = pid.communicate()
- except OSError as e:
- print('{}: {}({})'.format(cmd, e.strerror, e.returncode))
- except ValueError as e:
- print('{}: {}'.format(cmd, e.message))
- raise
- else:
- return out.strip()
-
- tmpdir = os.environ.get('TMPDIR', '/tmp')
- podman_args = [
- '--storage-driver=vfs',
- '--cgroup-manager=cgroupfs',
- '--root={}/crio'.format(tmpdir),
- '--runroot={}/crio-run'.format(tmpdir),
- '--cni-config-dir={}/cni/net.d'.format(tmpdir),
- ]
-
- run_podman = functools.partial(run_cmd, ['podman'], podman_args)
-
- id = run_podman(['pull', 'alpine'])
- setattr(PodmanTestCase, 'alpine_id', id)
-
- run_podman(['pull', 'busybox'])
- run_podman(['images'])
-
- run_cmd(['rm', '-f', '{}/alpine_gold.tar'.format(tmpdir)])
- run_podman([
- 'save', '--output', '{}/alpine_gold.tar'.format(tmpdir), 'alpine'
- ])
-
- PodmanTestCase.alpine_log = open(
- os.path.join('/tmp/', 'alpine.log'), 'w')
-
- cmd = ['podman']
- cmd.extend(podman_args)
- # cmd.extend(['run', '-d', 'alpine', 'sleep', '500'])
- cmd.extend(['run', '-dt', 'alpine', '/bin/sh'])
- PodmanTestCase.alpine_process = subprocess.Popen(
- cmd,
- stdout=PodmanTestCase.alpine_log,
- stderr=subprocess.STDOUT,
- )
-
- PodmanTestCase.busybox_log = open(
- os.path.join('/tmp/', 'busybox.log'), 'w')
-
- cmd = ['podman']
- cmd.extend(podman_args)
- cmd.extend(['create', 'busybox'])
- PodmanTestCase.busybox_process = subprocess.Popen(
- cmd,
- stdout=PodmanTestCase.busybox_log,
- stderr=subprocess.STDOUT,
- )
- # give podman time to start ctnr
- time.sleep(2)
-
- # Close our handle of file
- PodmanTestCase.alpine_log.close()
- PodmanTestCase.busybox_log.close()
-
- @classmethod
- def tearDownClass(cls):
- """Fixture to clean up after podman unittest."""
- try:
- PodmanTestCase.alpine_process.kill()
- assert 0 == PodmanTestCase.alpine_process.wait(500)
- delattr(PodmanTestCase, 'alpine_process')
-
- PodmanTestCase.busybox_process.kill()
- assert 0 == PodmanTestCase.busybox_process.wait(500)
- except Exception as e:
- print('Exception: {}'.format(e))
- raise
-
- @contextlib.contextmanager
- def assertRaisesNotImplemented(self):
- """Sugar for unimplemented varlink methods."""
- with self.assertRaisesRegex(VarlinkError, MethodNotImplemented):
- yield
diff --git a/contrib/python/podman/test/retry_decorator.py b/contrib/python/podman/test/retry_decorator.py
deleted file mode 100644
index 31e06f382..000000000
--- a/contrib/python/podman/test/retry_decorator.py
+++ /dev/null
@@ -1,43 +0,0 @@
-"""Decorator to retry failed method."""
-import functools
-import time
-
-
-def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, print_=None):
- """Retry calling the decorated function using an exponential backoff.
-
- Specialized for our unittests
- from:
- http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
- original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
-
- :param ExceptionToCheck: the exception to check. may be a tuple of
- exceptions to check
- :type ExceptionToCheck: Exception or tuple
- :param tries: number of times to try (not retry) before giving up
- :type tries: int
- :param delay: initial delay between retries in seconds
- :type delay: int
- :param backoff: backoff multiplier e.g. value of 2 will double the delay
- each retry
- :type backoff: int
- """
- def deco_retry(f):
- @functools.wraps(f)
- def f_retry(*args, **kwargs):
- mtries, mdelay = tries, delay
- while mtries > 1:
- try:
- return f(*args, **kwargs)
- except ExceptionToCheck as e:
- if print_:
- print_('{}, Retrying in {} seconds...'.format(
- str(e), mdelay))
- time.sleep(mdelay)
- mtries -= 1
- mdelay *= backoff
- return f(*args, **kwargs)
-
- return f_retry # true decorator
-
- return deco_retry
diff --git a/contrib/python/podman/test/test_client.py b/contrib/python/podman/test/test_client.py
deleted file mode 100644
index 3fc6d39dc..000000000
--- a/contrib/python/podman/test/test_client.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from __future__ import absolute_import
-
-import unittest
-from unittest.mock import patch
-
-import podman
-from podman.client import BaseClient, Client, LocalClient, RemoteClient
-
-
-class TestClient(unittest.TestCase):
- def setUp(self):
- pass
-
- @patch('podman.libs.system.System.ping', return_value=True)
- def test_local(self, mock_ping):
- p = Client(
- uri='unix:/run/podman',
- interface='io.podman',
- )
-
- self.assertIsInstance(p._client, LocalClient)
- self.assertIsInstance(p._client, BaseClient)
-
- mock_ping.assert_called_once_with()
-
- @patch('podman.libs.system.System.ping', return_value=True)
- def test_remote(self, mock_ping):
- p = Client(
- uri='unix:/run/podman',
- interface='io.podman',
- remote_uri='ssh://user@hostname/run/podman/podman',
- identity_file='~/.ssh/id_rsa')
-
- self.assertIsInstance(p._client, BaseClient)
- mock_ping.assert_called_once_with()
diff --git a/contrib/python/podman/test/test_containers.py b/contrib/python/podman/test/test_containers.py
deleted file mode 100644
index 5201956e8..000000000
--- a/contrib/python/podman/test/test_containers.py
+++ /dev/null
@@ -1,244 +0,0 @@
-import os
-import signal
-import unittest
-from pathlib import Path
-from test.podman_testcase import PodmanTestCase
-from test.retry_decorator import retry
-
-import podman
-
-
-class TestContainers(PodmanTestCase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- def setUp(self):
- self.tmpdir = os.environ['TMPDIR']
- self.host = os.environ['PODMAN_HOST']
-
- self.pclient = podman.Client(self.host)
- self.loadCache()
-
- def tearDown(self):
- pass
-
- def loadCache(self):
- self.containers = list(self.pclient.containers.list())
-
- self.alpine_ctnr = next(
- iter([c for c in self.containers if 'alpine' in c['image']] or []),
- None)
-
- if self.alpine_ctnr and self.alpine_ctnr.status != 'running':
- self.alpine_ctnr.start()
-
- def test_list(self):
- self.assertGreaterEqual(len(self.containers), 2)
- self.assertIsNotNone(self.alpine_ctnr)
- self.assertIn('alpine', self.alpine_ctnr.image)
-
- def test_delete_stopped(self):
- before = len(self.containers)
-
- self.alpine_ctnr.stop()
- target = self.alpine_ctnr.id
- actual = self.pclient.containers.delete_stopped()
- self.assertIn(target, actual)
-
- self.loadCache()
- after = len(self.containers)
-
- self.assertLess(after, before)
- TestContainers.setUpClass()
-
- def test_get(self):
- actual = self.pclient.containers.get(self.alpine_ctnr.id)
- for k in ['id', 'status', 'ports']:
- self.assertEqual(actual[k], self.alpine_ctnr[k])
-
- with self.assertRaises(podman.ContainerNotFound):
- self.pclient.containers.get("bozo")
-
- def test_attach(self):
- # StringIO does not support fileno() so we had to go old school
- input = os.path.join(self.tmpdir, 'test_attach.stdin')
- output = os.path.join(self.tmpdir, 'test_attach.stdout')
-
- with open(input, 'w+') as mock_in, open(output, 'w+') as mock_out:
- # double quote is indeed in the expected place
- mock_in.write('echo H"ello, World"; exit\n')
- mock_in.seek(0, 0)
-
- ctnr = self.pclient.images.get(self.alpine_ctnr.image).container(
- detach=True, tty=True)
- ctnr.attach(stdin=mock_in.fileno(), stdout=mock_out.fileno())
- ctnr.start()
-
- mock_out.flush()
- mock_out.seek(0, 0)
- output = mock_out.read()
- self.assertIn('Hello', output)
-
- ctnr.remove(force=True)
-
- def test_processes(self):
- actual = list(self.alpine_ctnr.processes())
- self.assertGreaterEqual(len(actual), 2)
-
- def test_start_stop_wait(self):
- ctnr = self.alpine_ctnr.stop()
- self.assertFalse(ctnr['running'])
-
- ctnr.start()
- self.assertTrue(ctnr.running)
-
- ctnr.stop()
- self.assertFalse(ctnr['containerrunning'])
-
- actual = ctnr.wait()
- self.assertGreaterEqual(actual, 0)
-
- def test_changes(self):
- actual = self.alpine_ctnr.changes()
-
- self.assertListEqual(
- sorted(['changed', 'added', 'deleted']), sorted(
- list(actual.keys())))
-
- # TODO: brittle, depends on knowing history of ctnr
- self.assertGreaterEqual(len(actual['changed']), 0)
- self.assertGreaterEqual(len(actual['added']), 0)
- self.assertEqual(len(actual['deleted']), 0)
-
- def test_kill(self):
- self.assertTrue(self.alpine_ctnr.running)
- ctnr = self.alpine_ctnr.kill(signal.SIGKILL)
- self.assertFalse(ctnr.running)
-
- def test_inspect(self):
- actual = self.alpine_ctnr.inspect()
- self.assertEqual(actual.id, self.alpine_ctnr.id)
- # TODO: Datetime values from inspect missing offset in CI instance
- # self.assertEqual(
- # datetime_parse(actual.created),
- # datetime_parse(self.alpine_ctnr.createdat))
-
- def test_export(self):
- target = os.path.join(self.tmpdir, 'alpine_export_ctnr.tar')
-
- actual = self.alpine_ctnr.export(target)
- self.assertEqual(actual, target)
- self.assertTrue(os.path.isfile(target))
- self.assertGreater(os.path.getsize(target), 0)
-
- def test_commit(self):
- # TODO: Test for STOPSIGNAL when supported by OCI
- # TODO: Test for message when supported by OCI
- details = self.pclient.images.get(self.alpine_ctnr.image).inspect()
- changes = ['ENV=' + i for i in details.config['env']]
- changes.append('CMD=/usr/bin/zsh')
- changes.append('ENTRYPOINT=/bin/sh date')
- changes.append('ENV=TEST=test_containers.TestContainers.test_commit')
- changes.append('EXPOSE=80')
- changes.append('EXPOSE=8888')
- changes.append('LABEL=unittest=test_commit')
- changes.append('USER=bozo:circus')
- changes.append('VOLUME=/data')
- changes.append('WORKDIR=/data/application')
-
- id = self.alpine_ctnr.commit(
- 'alpine3', author='Bozo the clown', change=changes, pause=True)
- img = self.pclient.images.get(id)
- self.assertIsNotNone(img)
-
- details = img.inspect()
- self.assertEqual(details.author, 'Bozo the clown')
- self.assertListEqual(['/usr/bin/zsh'], details.config['cmd'])
- self.assertListEqual(['/bin/sh date'],
- details.config['entrypoint'])
- self.assertIn('TEST=test_containers.TestContainers.test_commit',
- details.config['env'])
- self.assertTrue(
- [e for e in details.config['env'] if 'PATH=' in e])
- self.assertDictEqual({
- '80': {},
- '8888': {},
- }, details.config['exposedports'])
- self.assertDictEqual({'unittest': 'test_commit'}, details.labels)
- self.assertEqual('bozo:circus', details.config['user'])
- self.assertEqual({'/data': {}}, details.config['volumes'])
- self.assertEqual('/data/application',
- details.config['workingdir'])
-
- def test_remove(self):
- before = len(self.containers)
-
- with self.assertRaises(podman.ErrorOccurred):
- self.alpine_ctnr.remove()
-
- self.assertEqual(
- self.alpine_ctnr.id, self.alpine_ctnr.remove(force=True))
- self.loadCache()
- after = len(self.containers)
-
- self.assertLess(after, before)
- TestContainers.setUpClass()
-
- def test_restart(self):
- self.assertTrue(self.alpine_ctnr.running)
- before = self.alpine_ctnr.runningfor
-
- ctnr = self.alpine_ctnr.restart()
- self.assertTrue(ctnr.running)
-
- after = self.alpine_ctnr.runningfor
-
- # TODO: restore check when restart zeros counter
- # self.assertLess(after, before)
-
- def test_rename(self):
- with self.assertRaisesNotImplemented():
- self.alpine_ctnr.rename('new_alpine')
-
- def test_resize_tty(self):
- with self.assertRaisesNotImplemented():
- self.alpine_ctnr.resize_tty(132, 43)
-
- def test_pause_unpause(self):
- self.assertTrue(self.alpine_ctnr.running)
-
- ctnr = self.alpine_ctnr.pause()
- self.assertEqual(ctnr.status, 'paused')
-
- ctnr = self.alpine_ctnr.unpause()
- self.assertTrue(ctnr.running)
- self.assertTrue(ctnr.status, 'running')
-
- # creating cgoups can be flakey
- @retry(podman.libs.errors.ErrorOccurred, tries=4, delay=2, print_=print)
- def test_stats(self):
- try:
- self.assertTrue(self.alpine_ctnr.running)
-
- actual = self.alpine_ctnr.stats()
- self.assertEqual(self.alpine_ctnr.id, actual.id)
- self.assertEqual(self.alpine_ctnr.names, actual.name)
- except Exception:
- info = Path('/proc/self/mountinfo')
- with info.open() as fd:
- print('{} {}'.format(self.alpine_ctnr.id, info))
- print(fd.read())
-
- def test_logs(self):
- self.assertTrue(self.alpine_ctnr.running)
- actual = list(self.alpine_ctnr.logs())
- self.assertIsNotNone(actual)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/contrib/python/podman/test/test_images.py b/contrib/python/podman/test/test_images.py
deleted file mode 100644
index af6d4741e..000000000
--- a/contrib/python/podman/test/test_images.py
+++ /dev/null
@@ -1,174 +0,0 @@
-import itertools
-import os
-import unittest
-from collections import Counter
-from datetime import datetime, timezone
-from test.podman_testcase import PodmanTestCase
-
-import podman
-from podman import FoldedString
-
-
-class TestImages(PodmanTestCase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- def setUp(self):
- self.tmpdir = os.environ['TMPDIR']
- self.host = os.environ['PODMAN_HOST']
-
- self.pclient = podman.Client(self.host)
- self.images = self.loadCache()
-
- def tearDown(self):
- pass
-
- def loadCache(self):
- with podman.Client(self.host) as pclient:
- self.images = list(pclient.images.list())
-
- self.alpine_image = next(
- iter([
- i for i in self.images
- if 'docker.io/library/alpine:latest' in i['repoTags']
- ] or []), None)
-
- return self.images
-
- def test_list(self):
- actual = self.loadCache()
- self.assertGreaterEqual(len(actual), 2)
- self.assertIsNotNone(self.alpine_image)
-
- @unittest.skip('TODO: missing buildah json file')
- def test_build(self):
- path = os.path.join(self.tmpdir, 'ctnr', 'Dockerfile')
- img, logs = self.pclient.images.build(
- dockerfile=[path],
- tags=['alpine-unittest'],
- )
- self.assertIsNotNone(img)
- self.assertIn('localhost/alpine-unittest:latest', img.repoTags)
- self.assertLess(
- podman.datetime_parse(img.created), datetime.now(timezone.utc))
- self.assertTrue(logs)
-
- def test_create(self):
- img_details = self.alpine_image.inspect()
-
- actual = self.alpine_image.container(command=['sleep', '1h'])
- self.assertIsNotNone(actual)
- self.assertEqual(FoldedString(actual.status), 'configured')
-
- ctnr = actual.start()
- self.assertEqual(FoldedString(ctnr.status), 'running')
-
- ctnr_details = ctnr.inspect()
- for e in img_details.config['env']:
- self.assertIn(e, ctnr_details.config['env'])
-
- def test_export(self):
- path = os.path.join(self.tmpdir, 'alpine_export.tar')
- target = 'oci-archive:{}:latest'.format(path)
-
- actual = self.alpine_image.export(target, False)
- self.assertTrue(actual)
- self.assertTrue(os.path.isfile(path))
-
- def test_get(self):
- actual = self.pclient.images.get(self.alpine_image.id)
- self.assertEqual(actual, self.alpine_image)
-
- def test_history(self):
- records = []
- bucket = Counter()
- for record in self.alpine_image.history():
- self.assertIn(record.id, (self.alpine_image.id, '<missing>'))
- bucket[record.id] += 1
- records.append(record)
-
- self.assertGreater(bucket[self.alpine_image.id], 0)
- self.assertEqual(sum(bucket.values()), len(records))
-
- def test_inspect(self):
- actual = self.alpine_image.inspect()
- self.assertEqual(actual.id, self.alpine_image.id)
-
- def test_push(self):
- path = '{}/alpine_push'.format(self.tmpdir)
- target = 'dir:{}'.format(path)
- self.alpine_image.push(target, tlsverify=False)
-
- self.assertTrue(os.path.isfile(os.path.join(path, 'manifest.json')))
- self.assertTrue(os.path.isfile(os.path.join(path, 'version')))
-
- def test_tag(self):
- self.assertEqual(self.alpine_image.id,
- self.alpine_image.tag('alpine:fubar'))
- self.loadCache()
- self.assertIn('localhost/alpine:fubar', self.alpine_image.repoTags)
-
- def test_remove(self):
- before = self.loadCache()
-
- # assertRaises doesn't follow the import name :(
- with self.assertRaises(podman.ErrorOccurred):
- self.alpine_image.remove()
-
- actual = self.alpine_image.remove(force=True)
- self.assertEqual(self.alpine_image.id, actual)
- after = self.loadCache()
-
- self.assertLess(len(after), len(before))
- TestImages.setUpClass()
- self.loadCache()
-
- def test_import_delete_unused(self):
- before = self.loadCache()
- # create unused image, so we have something to delete
- source = os.path.join(self.tmpdir, 'alpine_gold.tar')
- new_img = self.pclient.images.import_image(
- source,
- 'alpine2:latest',
- 'unittest.test_import',
- )
- after = self.loadCache()
-
- self.assertEqual(len(before) + 1, len(after))
- self.assertIsNotNone(
- next(iter([i for i in after if new_img in i['id']] or []), None))
-
- actual = self.pclient.images.delete_unused()
- self.assertIn(new_img, actual)
-
- after = self.loadCache()
- self.assertGreaterEqual(len(before), len(after))
-
- TestImages.setUpClass()
- self.loadCache()
-
- def test_pull(self):
- before = self.loadCache()
- actual = self.pclient.images.pull('prom/busybox:latest')
- after = self.loadCache()
-
- self.assertEqual(len(before) + 1, len(after))
- self.assertIsNotNone(
- next(iter([i for i in after if actual in i['id']] or []), None))
-
- def test_search(self):
- actual = self.pclient.images.search('alpine', 25)
- names, length = itertools.tee(actual)
-
- for img in names:
- self.assertIn('alpine', img.name)
- self.assertTrue(0 < len(list(length)) <= 25)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/contrib/python/podman/test/test_libs.py b/contrib/python/podman/test/test_libs.py
deleted file mode 100644
index 202bed1d8..000000000
--- a/contrib/python/podman/test/test_libs.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import datetime
-import unittest
-
-import podman
-
-
-class TestLibs(unittest.TestCase):
- def setUp(self):
- pass
-
- def tearDown(self):
- pass
-
- def test_parse(self):
- expected = datetime.datetime.strptime(
- '2018-05-08T14:12:53.797795-0700', '%Y-%m-%dT%H:%M:%S.%f%z')
- for v in [
- '2018-05-08T14:12:53.797795191-07:00',
- '2018-05-08T14:12:53.797795-07:00',
- '2018-05-08T14:12:53.797795-0700',
- '2018-05-08 14:12:53.797795191 -0700 MST',
- ]:
- actual = podman.datetime_parse(v)
- self.assertEqual(actual, expected)
-
- expected = datetime.datetime.strptime(
- '2018-05-08T14:12:53.797795-0000', '%Y-%m-%dT%H:%M:%S.%f%z')
- for v in [
- '2018-05-08T14:12:53.797795191Z',
- '2018-05-08T14:12:53.797795191z',
- ]:
- actual = podman.datetime_parse(v)
- self.assertEqual(actual, expected)
-
- actual = podman.datetime_parse(datetime.datetime.now().isoformat())
- self.assertIsNotNone(actual)
-
- def test_parse_fail(self):
- for v in [
- 'There is no time here.',
- ]:
- with self.assertRaises(ValueError):
- podman.datetime_parse(v)
-
- def test_format(self):
- expected = '2018-05-08T18:24:52.753227-07:00'
- dt = podman.datetime_parse(expected)
- actual = podman.datetime_format(dt)
- self.assertEqual(actual, expected)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/contrib/python/podman/test/test_pods_ctnrs.py b/contrib/python/podman/test/test_pods_ctnrs.py
deleted file mode 100644
index 009e30720..000000000
--- a/contrib/python/podman/test/test_pods_ctnrs.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import os
-from test.podman_testcase import PodmanTestCase
-
-import podman
-from podman import FoldedString
-
-pod = None
-
-
-class TestPodsCtnrs(PodmanTestCase):
- @classmethod
- def setUpClass(cls):
- # Populate storage
- super().setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- def setUp(self):
- self.tmpdir = os.environ['TMPDIR']
- self.host = os.environ['PODMAN_HOST']
-
- self.pclient = podman.Client(self.host)
-
- def test_010_populate(self):
- global pod
-
- pod = self.pclient.pods.create('pod1')
- self.assertEqual('pod1', pod.name)
-
- img = self.pclient.images.get('docker.io/library/alpine:latest')
- ctnr = img.container(pod=pod.id)
-
- pod.refresh()
- self.assertEqual('1', pod.numberofcontainers)
- self.assertEqual(ctnr.id, pod.containersinfo[0]['id'])
-
- def test_015_one_shot(self):
- global pod
-
- details = pod.inspect()
- state = FoldedString(details.containers[0]['state'])
- self.assertEqual(state, 'configured')
-
- pod = pod.start()
- status = FoldedString(pod.containersinfo[0]['status'])
- # Race on whether container is still running or finished
- self.assertIn(status, ('stopped', 'exited', 'running'))
-
- pod = pod.restart()
- status = FoldedString(pod.containersinfo[0]['status'])
- self.assertIn(status, ('stopped', 'exited', 'running'))
-
- # Pod kill is broken, so use stop for now
- killed = pod.stop()
- self.assertEqual(pod, killed)
-
- def test_999_remove(self):
- global pod
-
- ident = pod.remove(force=True)
- self.assertEqual(ident, pod.id)
-
- with self.assertRaises(StopIteration):
- next(self.pclient.pods.list())
diff --git a/contrib/python/podman/test/test_pods_no_ctnrs.py b/contrib/python/podman/test/test_pods_no_ctnrs.py
deleted file mode 100644
index 48b4f74e4..000000000
--- a/contrib/python/podman/test/test_pods_no_ctnrs.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import os
-import unittest
-
-import podman
-import varlink
-
-ident = None
-pod = None
-
-
-class TestPodsNoCtnrs(unittest.TestCase):
- def setUp(self):
- self.tmpdir = os.environ['TMPDIR']
- self.host = os.environ['PODMAN_HOST']
-
- self.pclient = podman.Client(self.host)
-
- def test_010_create(self):
- global ident
-
- actual = self.pclient.pods.create('pod0')
- self.assertIsNotNone(actual)
- ident = actual.id
-
- def test_015_list(self):
- global ident, pod
-
- actual = next(self.pclient.pods.list())
- self.assertEqual('pod0', actual.name)
- self.assertEqual(ident, actual.id)
- self.assertEqual('Created', actual.status)
- self.assertEqual('0', actual.numberofcontainers)
- self.assertFalse(actual.containersinfo)
- pod = actual
-
- def test_020_get(self):
- global ident, pod
-
- actual = self.pclient.pods.get(pod.id)
- self.assertEqual('pod0', actual.name)
- self.assertEqual(ident, actual.id)
- self.assertEqual('Created', actual.status)
- self.assertEqual('0', actual.numberofcontainers)
- self.assertFalse(actual.containersinfo)
-
- def test_025_inspect(self):
- global ident, pod
-
- details = pod.inspect()
- self.assertEqual(ident, details.id)
- self.assertEqual('pod0', details.config['name'])
- self.assertIsNone(details.containers)
-
- def test_030_ident_no_ctnrs(self):
- global ident, pod
-
- actual = pod.kill()
- self.assertEqual(pod, actual)
-
- actual = pod.pause()
- self.assertEqual(pod, actual)
-
- actual = pod.unpause()
- self.assertEqual(pod, actual)
-
- actual = pod.stop()
- self.assertEqual(pod, actual)
-
- def test_045_raises_no_ctnrs(self):
- global ident, pod
-
- with self.assertRaises(podman.NoContainersInPod):
- pod.start()
-
- with self.assertRaises(podman.NoContainersInPod):
- pod.restart()
-
- with self.assertRaises(podman.NoContainerRunning):
- next(pod.stats())
-
- with self.assertRaises(varlink.error.MethodNotImplemented):
- pod.top()
-
- with self.assertRaises(varlink.error.MethodNotImplemented):
- pod.wait()
-
- def test_999_remove(self):
- global ident, pod
-
- actual = pod.remove()
- self.assertEqual(ident, actual)
-
- with self.assertRaises(StopIteration):
- next(self.pclient.pods.list())
diff --git a/contrib/python/podman/test/test_runner.sh b/contrib/python/podman/test/test_runner.sh
deleted file mode 100755
index 651b2e74f..000000000
--- a/contrib/python/podman/test/test_runner.sh
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/bash
-
-# podman needs to play some games with resources
-if [[ $(id -u) != 0 ]]; then
- echo >&2 $0 must be run as root.
- exit 2
-fi
-
-# setup path to find new binaries _NOT_ system binaries
-if [[ ! -x ../../../bin/podman ]]; then
- echo 1>&2 Cannot find podman binary from libpod root directory. Run \"make binaries\"
- exit 1
-fi
-export PATH=../../../bin:$PATH
-
-function usage {
- echo 1>&2 $0 '[-v] [-h] [test.<TestCase>|test.<TestCase>.<step>]'
-}
-
-while getopts "vh" arg; do
- case $arg in
- v ) VERBOSE='-v'; export LOG_LEVEL=debug ;;
- h ) usage ; exit 0 ;;
- \? ) usage ; exit 2 ;;
- esac
-done
-shift $((OPTIND -1))
-
-function cleanup {
- set +xeuo pipefail
- # aggressive cleanup as tests may crash leaving crap around
- umount '^(shm|nsfs)'
- umount '\/run\/netns'
- if [[ $RETURNCODE -eq 0 ]]; then
- rm -r "$1"
- fi
-}
-
-# Create temporary directory for storage
-export TMPDIR=`mktemp -d /tmp/podman.XXXXXXXXXX`
-trap "cleanup $TMPDIR" EXIT
-
-function umount {
- set +xeuo pipefail
- # xargs -r always ran once, so write any mount points to file first
- mount |awk "/$1/"' { print $3 }' >${TMPDIR}/mounts
- if [[ -s ${TMPDIR}/mounts ]]; then
- xargs <${TMPDIR}/mounts -t umount
- fi
-}
-
-function showlog {
- [[ -s $1 ]] && cat <<-EOT
-$1 =====
-$(cat "$1")
-
-EOT
-}
-
-# Need locations to store stuff
-mkdir -p ${TMPDIR}/{podman,crio,crio-run,cni/net.d,ctnr,tunnel}
-
-# Cannot be done in python unittest fixtures. EnvVar not picked up.
-export REGISTRIES_CONFIG_PATH=${TMPDIR}/registry.conf
-cat >$REGISTRIES_CONFIG_PATH <<-EOT
- [registries.search]
- registries = ['docker.io']
- [registries.insecure]
- registries = []
- [registries.block]
- registries = []
-EOT
-
-export CNI_CONFIG_PATH=${TMPDIR}/cni/net.d
-cat >$CNI_CONFIG_PATH/87-podman-bridge.conflist <<-EOT
-{
- "cniVersion": "0.3.0",
- "name": "podman",
- "plugins": [{
- "type": "bridge",
- "bridge": "cni0",
- "isGateway": true,
- "ipMasq": true,
- "ipam": {
- "type": "host-local",
- "subnet": "10.88.0.0/16",
- "routes": [{
- "dst": "0.0.0.0/0"
- }]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- }
- ]
-}
-EOT
-
-cat >$TMPDIR/ctnr/hello.sh <<-EOT
-echo 'Hello, World'
-exit 0
-EOT
-
-cat >$TMPDIR/ctnr/Dockerfile <<-EOT
-FROM alpine:latest
-COPY ./hello.sh /tmp/
-RUN chmod 755 /tmp/hello.sh
-ENTRYPOINT ["/tmp/hello.sh"]
-EOT
-
-export PODMAN_HOST="unix:${TMPDIR}/podman/io.podman"
-PODMAN_ARGS="--storage-driver=vfs \
- --root=${TMPDIR}/crio \
- --runroot=${TMPDIR}/crio-run \
- --cni-config-dir=$CNI_CONFIG_PATH \
- --cgroup-manager=cgroupfs \
- "
-if [[ -n $VERBOSE ]]; then
- PODMAN_ARGS="$PODMAN_ARGS --log-level=$LOG_LEVEL"
-fi
-PODMAN="podman $PODMAN_ARGS"
-
-cat <<-EOT |tee /tmp/test_podman.output
-$($PODMAN --version)
-$PODMAN varlink --timeout=0 ${PODMAN_HOST}
-==========================================
-EOT
-
-# Run podman in background without systemd for test purposes
-$PODMAN varlink --timeout=0 ${PODMAN_HOST} >>/tmp/test_podman.output 2>&1 &
-if [[ $? != 0 ]]; then
- echo 1>&2 Failed to start podman
- showlog /tmp/test_podman.output
-fi
-
-if [[ -z $1 ]]; then
- export PYTHONPATH=.
- python3 -m unittest discover -s . $VERBOSE
- RETURNCODE=$?
-else
- export PYTHONPATH=.:./test
- python3 -m unittest $1 $VERBOSE
- RETURNCODE=$?
-fi
-
-pkill -9 podman
-pkill -9 conmon
-
-showlog /tmp/test_podman.output
-showlog /tmp/alpine.log
-showlog /tmp/busybox.log
-
-exit $RETURNCODE
diff --git a/contrib/python/podman/test/test_system.py b/contrib/python/podman/test/test_system.py
deleted file mode 100644
index c483f3232..000000000
--- a/contrib/python/podman/test/test_system.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import os
-import unittest
-from urllib.parse import urlparse
-
-import podman
-import varlink
-
-
-class TestSystem(unittest.TestCase):
- def setUp(self):
- self.host = os.environ['PODMAN_HOST']
- self.tmpdir = os.environ['TMPDIR']
-
- def tearDown(self):
- pass
-
- def test_bad_address(self):
- with self.assertRaisesRegex(varlink.client.ConnectionError,
- "Invalid address 'bad address'"):
- podman.Client('bad address')
-
- def test_ping(self):
- with podman.Client(self.host) as pclient:
- self.assertTrue(pclient.system.ping())
-
- @unittest.skip("TODO: Need to setup ssh under Travis")
- def test_remote_ping(self):
- host = urlparse(self.host)
- remote_uri = 'ssh://root@localhost{}'.format(host.path)
-
- local_uri = 'unix:{}/tunnel/podman.sock'.format(self.tmpdir)
- with podman.Client(
- uri=local_uri,
- remote_uri=remote_uri,
- identity_file=os.path.expanduser('~/.ssh/id_rsa'),
- ) as remote_client:
- self.assertTrue(remote_client.system.ping())
-
- def test_versions(self):
- with podman.Client(self.host) as pclient:
- # Values change with each build so we cannot test too much
- self.assertListEqual(
- sorted([
- 'built', 'client_version', 'git_commit', 'go_version',
- 'os_arch', 'version'
- ]), sorted(list(pclient.system.versions._fields)))
- pclient.system.versions
- self.assertIsNot(podman.__version__, '0.0.0')
-
- def test_info(self):
- with podman.Client(self.host) as pclient:
- actual = pclient.system.info()
- # Values change too much to do exhaustive testing
- self.assertIsNotNone(actual.podman['go_version'])
- self.assertListEqual(
- sorted([
- 'host', 'insecure_registries', 'podman', 'registries',
- 'store'
- ]), sorted(list(actual._fields)))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/contrib/python/podman/test/test_tunnel.py b/contrib/python/podman/test/test_tunnel.py
deleted file mode 100644
index 9a33e76cd..000000000
--- a/contrib/python/podman/test/test_tunnel.py
+++ /dev/null
@@ -1,86 +0,0 @@
-from __future__ import absolute_import
-
-import logging
-import time
-import unittest
-from unittest.mock import MagicMock, patch
-
-from podman.libs.tunnel import Context, Portal, Tunnel
-
-
-class TestTunnel(unittest.TestCase):
- def setUp(self):
- self.tunnel_01 = MagicMock(spec=Tunnel)
- self.tunnel_02 = MagicMock(spec=Tunnel)
-
- def test_portal_ops(self):
- portal = Portal(sweap=500)
- portal['unix:/01'] = self.tunnel_01
- portal['unix:/02'] = self.tunnel_02
-
- self.assertEqual(portal.get('unix:/01'), self.tunnel_01)
- self.assertEqual(portal.get('unix:/02'), self.tunnel_02)
-
- del portal['unix:/02']
- with self.assertRaises(KeyError):
- portal['unix:/02']
- self.assertEqual(len(portal), 1)
-
- def test_portal_reaping(self):
- portal = Portal(sweap=0.5)
- portal['unix:/01'] = self.tunnel_01
- portal['unix:/02'] = self.tunnel_02
-
- self.assertEqual(len(portal), 2)
- for entry in portal:
- self.assertIn(entry, (self.tunnel_01, self.tunnel_02))
-
- time.sleep(1)
- portal.reap()
- self.assertEqual(len(portal), 0)
-
- def test_portal_no_reaping(self):
- portal = Portal(sweap=500)
- portal['unix:/01'] = self.tunnel_01
- portal['unix:/02'] = self.tunnel_02
-
- portal.reap()
- self.assertEqual(len(portal), 2)
- for entry in portal:
- self.assertIn(entry, (self.tunnel_01, self.tunnel_02))
-
- @patch('subprocess.Popen')
- @patch('os.path.exists', return_value=True)
- @patch('weakref.finalize')
- def test_tunnel(self, mock_finalize, mock_exists, mock_Popen):
- mock_Popen.return_value.returncode = 0
-
- context = Context(
- 'unix:/01',
- 'io.podman',
- '/tmp/user/socket',
- '/run/podman/socket',
- 'user',
- 'hostname',
- None,
- '~/.ssh/id_rsa',
- )
- tunnel = Tunnel(context).bore()
-
- cmd = ['ssh', '-fNT']
- if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
- cmd.append('-v')
- else:
- cmd.append('-q')
-
- cmd.extend((
- '-L',
- '{}:{}'.format(context.local_socket, context.remote_socket),
- '-i',
- context.identity_file,
- '{}@{}'.format(context.username, context.hostname),
- ))
-
- mock_finalize.assert_called_once_with(tunnel, tunnel.close)
- mock_exists.assert_called_once_with(context.local_socket)
- mock_Popen.assert_called_once_with(cmd, close_fds=True)
diff --git a/contrib/python/podman/tox.ini b/contrib/python/podman/tox.ini
deleted file mode 100644
index 797eafbe3..000000000
--- a/contrib/python/podman/tox.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[tox]
-envlist = py34,py35,py36
-skipdist = True
-
-[testenv]
-deps=-rrequirements.txt
-whitelist_externals = bash
-commands=bash test/test_runner.sh