mirror of
https://github.com/containers/podman-compose.git
synced 2025-07-05 07:00:11 +02:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
ed1e8650db | |||
8e2cd2bab8 | |||
b37076bc5e | |||
3db72df49d | |||
189c086d5b | |||
32b3d26ab1 | |||
35a66f5a8b |
9
.github/workflows/static-checks.yml
vendored
9
.github/workflows/static-checks.yml
vendored
@ -14,19 +14,12 @@ jobs:
|
|||||||
options: --privileged --cgroupns=host
|
options: --privileged --cgroupns=host
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install dependencies
|
- name: Analysing the code with ruff
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
pip install -r test-requirements.txt
|
pip install -r test-requirements.txt
|
||||||
- name: Analysing the code using ruff
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
ruff format --check
|
ruff format --check
|
||||||
ruff check
|
ruff check
|
||||||
- name: Analysing the code using mypy
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
mypy .
|
|
||||||
- name: Analysing the code with pylint
|
- name: Analysing the code with pylint
|
||||||
run: |
|
run: |
|
||||||
pylint podman_compose.py
|
pylint podman_compose.py
|
||||||
|
@ -19,12 +19,11 @@ Note: Some steps are OPTIONAL but all are RECOMMENDED.
|
|||||||
$ cd podman-compose
|
$ cd podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
2. (OPTIONAL) Create a Python virtual environment. Example using python builtin
|
2. (OPTIONAL) Create a Python virtual environment. Example using
|
||||||
`venv` module:
|
[virtualenv wrapper](https://virtualenvwrapper.readthedocs.io/en/latest/):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ python3 -m venv .venv
|
$ mkvirtualenv podman-compose
|
||||||
$ . .venv/bin/activate
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Install the project runtime and development requirements:
|
3. Install the project runtime and development requirements:
|
||||||
@ -61,25 +60,9 @@ Note: Some steps are OPTIONAL but all are RECOMMENDED.
|
|||||||
- Make sure you include a `Signed-off-by` message in your commits.
|
- Make sure you include a `Signed-off-by` message in your commits.
|
||||||
Read [this guide](https://github.com/containers/common/blob/main/CONTRIBUTING.md#sign-your-prs)
|
Read [this guide](https://github.com/containers/common/blob/main/CONTRIBUTING.md#sign-your-prs)
|
||||||
to learn how to sign your commits.
|
to learn how to sign your commits.
|
||||||
- In the commit message body, reference the Issue ID that your code fixes and a brief description of the changes.
|
- In the commit message, reference the Issue ID that your code fixes and a brief description of
|
||||||
Example:
|
the changes.
|
||||||
```
|
Example: `Fixes #516: Allow empty network`
|
||||||
Allow empty network
|
|
||||||
|
|
||||||
<description, such as links to the compose spec and so on>
|
|
||||||
|
|
||||||
Fixes https://github.com/containers/podman-compose/issues/516
|
|
||||||
```
|
|
||||||
- If your commit requires a refactoring, first do the refactoring and
|
|
||||||
commit it separately before starting feature work. This makes the
|
|
||||||
pull request easier to review. Additionally, pull request will be
|
|
||||||
less risky, because if it breaks something, it's way easier to
|
|
||||||
isolate the offending code, understand what's broken and fix it.
|
|
||||||
Due to the latter reason it's best to commit in as many independent
|
|
||||||
commits as reasonable.
|
|
||||||
|
|
||||||
This will result in pull requests being merged much faster.
|
|
||||||
|
|
||||||
9. Open a pull request to `containers/podman-compose` and wait for a maintainer to review your work.
|
9. Open a pull request to `containers/podman-compose` and wait for a maintainer to review your work.
|
||||||
|
|
||||||
## Adding new commands
|
## Adding new commands
|
||||||
|
63
README.md
63
README.md
@ -68,23 +68,7 @@ Or latest development version from GitHub:
|
|||||||
pip3 install https://github.com/containers/podman-compose/archive/main.tar.gz
|
pip3 install https://github.com/containers/podman-compose/archive/main.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
### Package repositories
|
### Homebrew
|
||||||
|
|
||||||
podman-compose is available from the following package repositories:
|
|
||||||
|
|
||||||
Debian:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install podman-compose
|
|
||||||
```
|
|
||||||
|
|
||||||
Fedora (starting from f31) repositories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo dnf install podman-compose
|
|
||||||
```
|
|
||||||
|
|
||||||
Homebrew:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install podman-compose
|
brew install podman-compose
|
||||||
@ -110,22 +94,51 @@ curl -o ~/.local/bin/podman-compose https://raw.githubusercontent.com/containers
|
|||||||
chmod +x ~/.local/bin/podman-compose
|
chmod +x ~/.local/bin/podman-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or install from Fedora (starting from f31) repositories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf install podman-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
We have included fully functional sample stacks inside `examples/` directory.
|
||||||
|
You can get more examples from [awesome-compose](https://github.com/docker/awesome-compose).
|
||||||
|
|
||||||
|
A quick example would be
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd examples/busybox
|
||||||
|
podman-compose --help
|
||||||
|
podman-compose up --help
|
||||||
|
podman-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
A more rich example can be found in [examples/awx3](examples/awx3)
|
||||||
|
which have
|
||||||
|
|
||||||
|
- A Postgres Database
|
||||||
|
- RabbitMQ server
|
||||||
|
- MemCached server
|
||||||
|
- a django web server
|
||||||
|
- a django tasks
|
||||||
|
|
||||||
|
|
||||||
|
When testing the `AWX3` example, if you got errors, just wait for db migrations to end.
|
||||||
|
There is also AWX 17.1.0
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
podman-compose is tested via unit and integration tests.
|
Inside `tests/` directory we have many useless docker-compose stacks
|
||||||
|
that are meant to test as many cases as we can to make sure we are compatible
|
||||||
|
|
||||||
Unit tests can be run via the following:
|
### Unit tests with unittest
|
||||||
|
run a unittest with following command
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
python3 -m unittest discover tests/unit
|
python3 -m unittest discover tests/unit
|
||||||
```
|
```
|
||||||
|
|
||||||
Integration tests can be run via the following:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python3 -m unittest discover tests/integration
|
|
||||||
```
|
|
||||||
|
|
||||||
# Contributing guide
|
# Contributing guide
|
||||||
|
|
||||||
If you are a user or a developer and want to contribute please check the [CONTRIBUTING](CONTRIBUTING.md) section
|
If you are a user or a developer and want to contribute please check the [CONTRIBUTING](CONTRIBUTING.md) section
|
||||||
|
@ -27,22 +27,6 @@ services:
|
|||||||
|
|
||||||
For explanations of these extensions, please refer to the [Podman Documentation](https://docs.podman.io/).
|
For explanations of these extensions, please refer to the [Podman Documentation](https://docs.podman.io/).
|
||||||
|
|
||||||
## Secrets
|
|
||||||
The following extension keys are available under `secret` configuration:
|
|
||||||
|
|
||||||
x-podman.relabel - Configure SELinux relabeling
|
|
||||||
|
|
||||||
For example, the following configures custom-secret to use mount with private and unshared content.
|
|
||||||
Only the current container can use a private volume.
|
|
||||||
|
|
||||||
```yml
|
|
||||||
secrets:
|
|
||||||
custom-secret:
|
|
||||||
x-podman.relabel: Z
|
|
||||||
```
|
|
||||||
|
|
||||||
For explanations of these extensions, please refer to the [podman-run --volume documentation](https://docs.podman.io/en/latest/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options)).
|
|
||||||
|
|
||||||
## Network management
|
## Network management
|
||||||
|
|
||||||
The following extension keys are available under network configuration:
|
The following extension keys are available under network configuration:
|
||||||
@ -139,44 +123,6 @@ The options to the network modes are passed to the `--network` option of the `po
|
|||||||
as-is.
|
as-is.
|
||||||
|
|
||||||
|
|
||||||
## Docker Compose Compatibility
|
|
||||||
|
|
||||||
podman-compose aims to be compatible with docker-compose, but there are some differences in
|
|
||||||
behavior and features. The following sections describe how to enable compatibility with docker-compose
|
|
||||||
and how to handle some of the differences.
|
|
||||||
|
|
||||||
Compatibility settings can either be set explicitly as described below, or by setting the `docker_compose_compat` meta
|
|
||||||
settings to `true` under the global `x-podman` key:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
x-podman:
|
|
||||||
docker_compose_compat: true
|
|
||||||
```
|
|
||||||
|
|
||||||
This will enable all compatibility settings described below, and is equivalent to setting each of them to `true`.
|
|
||||||
|
|
||||||
This setting can also be changed by setting the `PODMAN_COMPOSE_DOCKER_COMPOSE_COMPAT` environment variable.
|
|
||||||
|
|
||||||
## Compatibility of name separators between docker-compose and podman-compose
|
|
||||||
|
|
||||||
Currently, podman-compose is using underscores (`_` character) as a separator in names of
|
|
||||||
containers, images, etc., while docker-compose has switched to hyphens (`-` character). This setting
|
|
||||||
allows to switch podman-compose to use hyphens as well.
|
|
||||||
|
|
||||||
To enable compatibility between docker-compose and podman-compose, specify
|
|
||||||
`name_separator_compat: true` under global `x-podman` key:
|
|
||||||
|
|
||||||
```
|
|
||||||
x-podman:
|
|
||||||
name_separator_compat: true
|
|
||||||
```
|
|
||||||
|
|
||||||
By default `name_separator_compat` is `false`. This will change to `true` at some point and the
|
|
||||||
setting will be removed.
|
|
||||||
|
|
||||||
This setting can also be changed by setting `PODMAN_COMPOSE_NAME_SEPARATOR_COMPAT` environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
## Compatibility of default network names between docker-compose and podman-compose
|
## Compatibility of default network names between docker-compose and podman-compose
|
||||||
|
|
||||||
Current versions of podman-compose may produce different default external network names than
|
Current versions of podman-compose may produce different default external network names than
|
||||||
@ -194,9 +140,6 @@ x-podman:
|
|||||||
By default `default_net_name_compat` is `false`. This will change to `true` at some point and the
|
By default `default_net_name_compat` is `false`. This will change to `true` at some point and the
|
||||||
setting will be removed.
|
setting will be removed.
|
||||||
|
|
||||||
This setting can also be changed by setting `PODMAN_COMPOSE_DEFAULT_NET_NAME_COMPAT` environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
## Compatibility of default network behavior between docker-compose and podman-compose
|
## Compatibility of default network behavior between docker-compose and podman-compose
|
||||||
|
|
||||||
When there is no network defined (neither network-mode nor networks) in service,
|
When there is no network defined (neither network-mode nor networks) in service,
|
||||||
@ -217,9 +160,6 @@ x-podman:
|
|||||||
default_net_behavior_compat: true
|
default_net_behavior_compat: true
|
||||||
```
|
```
|
||||||
|
|
||||||
This setting can also be changed by setting `PODMAN_COMPOSE_DEFAULT_NET_BEHAVIOR_COMPAT` environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
## Custom pods management
|
## Custom pods management
|
||||||
|
|
||||||
Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.
|
Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.
|
||||||
@ -239,9 +179,6 @@ x-podman:
|
|||||||
in_pod: false
|
in_pod: false
|
||||||
```
|
```
|
||||||
|
|
||||||
This setting can also be changed by setting `PODMAN_COMPOSE_IN_POD` environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
It is also possible to override the default arguments for pod creation that are
|
It is also possible to override the default arguments for pod creation that are
|
||||||
used when --pod-args is not passed on the command line:
|
used when --pod-args is not passed on the command line:
|
||||||
```yml
|
```yml
|
||||||
@ -255,6 +192,3 @@ x-podman:
|
|||||||
```
|
```
|
||||||
When not set in docker-compose.yml or on the command line, the pod args default
|
When not set in docker-compose.yml or on the command line, the pod args default
|
||||||
to `["--infra=false", "--share="]`.
|
to `["--infra=false", "--share="]`.
|
||||||
|
|
||||||
This setting can also be changed by setting `PODMAN_COMPOSE_POD_ARGS` environment
|
|
||||||
variable.
|
|
@ -3,8 +3,8 @@
|
|||||||
import asyncio # noqa: F401
|
import asyncio # noqa: F401
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import aioredis # type: ignore[import-not-found]
|
import aioredis
|
||||||
from aiohttp import web # type: ignore[import-not-found]
|
from aiohttp import web
|
||||||
|
|
||||||
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
|
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
|
||||||
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
|
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
|
||||||
@ -16,13 +16,13 @@ routes = web.RouteTableDef()
|
|||||||
|
|
||||||
|
|
||||||
@routes.get("/")
|
@routes.get("/")
|
||||||
async def hello(request: web.Request) -> web.Response: # pylint: disable=unused-argument
|
async def hello(request): # pylint: disable=unused-argument
|
||||||
counter = await redis.incr("mycounter")
|
counter = await redis.incr("mycounter")
|
||||||
return web.Response(text=f"counter={counter}")
|
return web.Response(text=f"counter={counter}")
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/hello.json")
|
@routes.get("/hello.json")
|
||||||
async def hello_json(request: web.Request) -> web.Response: # pylint: disable=unused-argument
|
async def hello_json(request): # pylint: disable=unused-argument
|
||||||
counter = await redis.incr("mycounter")
|
counter = await redis.incr("mycounter")
|
||||||
data = {"counter": counter}
|
data = {"counter": counter}
|
||||||
return web.json_response(data)
|
return web.json_response(data)
|
||||||
@ -31,7 +31,7 @@ async def hello_json(request: web.Request) -> web.Response: # pylint: disable=u
|
|||||||
app.add_routes(routes)
|
app.add_routes(routes)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main():
|
||||||
web.run_app(app, port=8080)
|
web.run_app(app, port=8080)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
- Add unregister command to remove systemd service registration (`podman-compose systemd -a unregister`)
|
|
@ -1 +0,0 @@
|
|||||||
- Change behaviour of `--in-pod` to handle custom pod names instead of only disabling pod feature
|
|
@ -1 +0,0 @@
|
|||||||
- Add new docker_compose_compat x-podman meta setting to enable all Docker Compose compatibility settings
|
|
@ -1 +0,0 @@
|
|||||||
Add support for environment variable interpolation for YAML keys.
|
|
@ -1 +0,0 @@
|
|||||||
Fixed build ssh path to a local SSH key, to be relative to the directory of compose file.
|
|
@ -1 +0,0 @@
|
|||||||
Fixed support for CMD healthchecks to run using the given command directly and not using `/bin/sh -c`.
|
|
@ -1 +0,0 @@
|
|||||||
Implemented forwarding failure exit code from `push` command.
|
|
@ -1 +0,0 @@
|
|||||||
Implemented short syntax for environment variables set in `.env` for compose.yml "environment:" section.
|
|
@ -1 +0,0 @@
|
|||||||
Fixed regression of log output including "text" in detached mode.
|
|
@ -1 +0,0 @@
|
|||||||
Hide the stack trace on a YAML parse error.
|
|
@ -1 +0,0 @@
|
|||||||
Added `io.podman.compose.service` label to created containers. It contains the same value as com.docker.compose.service.
|
|
@ -1 +0,0 @@
|
|||||||
- Add new name_separator_compat x-podman setting to change name separator to hyphen, same as Docker Compose
|
|
@ -1 +0,0 @@
|
|||||||
- Add relabel option to secret to make possible to read the secret file by the contained process.
|
|
@ -1 +0,0 @@
|
|||||||
- Add support for setting x-podman values using PODMAN_COMPOSE_* environment variables.
|
|
File diff suppressed because it is too large
Load Diff
@ -1,59 +1,3 @@
|
|||||||
[build-system]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
requires = ["setuptools"]
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "podman-compose"
|
|
||||||
authors = [
|
|
||||||
{ email = "alsadi@gmail.com", name = "Muayyad Alsadi" },
|
|
||||||
]
|
|
||||||
description = "A script to run docker-compose.yml using podman"
|
|
||||||
dependencies = [
|
|
||||||
"python-dotenv",
|
|
||||||
"pyyaml",
|
|
||||||
]
|
|
||||||
requires-python = ">=3.9"
|
|
||||||
classifiers = [
|
|
||||||
"Development Status :: 3 - Alpha",
|
|
||||||
"Intended Audience :: Developers",
|
|
||||||
"Operating System :: OS Independent",
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"Programming Language :: Python :: 3",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Programming Language :: Python :: 3.11",
|
|
||||||
"Programming Language :: Python :: 3.12",
|
|
||||||
"Programming Language :: Python :: 3.13",
|
|
||||||
"Topic :: Software Development :: Build Tools",
|
|
||||||
]
|
|
||||||
keywords = [
|
|
||||||
"podman",
|
|
||||||
"podman-compose",
|
|
||||||
]
|
|
||||||
license = "GPL-2.0-only"
|
|
||||||
dynamic = ["version", "readme"]
|
|
||||||
|
|
||||||
[project.urls]
|
|
||||||
homepage = "https://github.com/containers/podman-compose"
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
|
||||||
devel = [
|
|
||||||
"coverage",
|
|
||||||
"parameterized",
|
|
||||||
"pre-commit",
|
|
||||||
"ruff",
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.scripts]
|
|
||||||
podman-compose = "podman_compose:main"
|
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
py-modules = ["podman_compose"]
|
|
||||||
|
|
||||||
[tool.setuptools.dynamic]
|
|
||||||
readme = {file = ["README.md"], content-type = "text/markdown"}
|
|
||||||
version = {attr = "podman_compose.__version__"}
|
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 100
|
line-length = 100
|
||||||
target-version = "py38"
|
target-version = "py38"
|
||||||
@ -109,21 +53,3 @@ quote-style = "preserve"
|
|||||||
directory = "misc"
|
directory = "misc"
|
||||||
name = "Misc"
|
name = "Misc"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[tool.mypy]
|
|
||||||
python_version = "3.9"
|
|
||||||
namespace_packages = true
|
|
||||||
explicit_package_bases = true
|
|
||||||
pretty = true
|
|
||||||
warn_redundant_casts = true
|
|
||||||
disallow_untyped_calls = false
|
|
||||||
disallow_untyped_defs = true
|
|
||||||
no_implicit_optional = true
|
|
||||||
mypy_path = "$MYPY_CONFIG_FILE_DIR"
|
|
||||||
exclude = "build"
|
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
|
||||||
module = [
|
|
||||||
"parameterized.*",
|
|
||||||
]
|
|
||||||
ignore_missing_imports = true
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
./scripts/uninstall.sh
|
./scripts/uninstall.sh
|
||||||
./scripts/clean_up.sh
|
./scripts/clean_up.sh
|
||||||
pyproject-build
|
python3 setup.py register
|
||||||
|
python3 setup.py sdist bdist_wheel
|
||||||
twine upload dist/*
|
twine upload dist/*
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
[bdist_wheel]
|
||||||
|
universal = 1
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
version = attr: podman_compose.__version__
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
# The GitHub editor is 127 chars wide
|
# The GitHub editor is 127 chars wide
|
||||||
max-line-length=127
|
max-line-length=127
|
||||||
|
49
setup.py
Normal file
49
setup.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
try:
|
||||||
|
README = open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8").read()
|
||||||
|
except: # noqa: E722 # pylint: disable=bare-except
|
||||||
|
README = ""
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="podman-compose",
|
||||||
|
description="A script to run docker-compose.yml using podman",
|
||||||
|
long_description=README,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Topic :: Software Development :: Build Tools",
|
||||||
|
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
|
||||||
|
],
|
||||||
|
keywords="podman, podman-compose",
|
||||||
|
author="Muayyad Alsadi",
|
||||||
|
author_email="alsadi@gmail.com",
|
||||||
|
url="https://github.com/containers/podman-compose",
|
||||||
|
py_modules=["podman_compose"],
|
||||||
|
entry_points={"console_scripts": ["podman-compose = podman_compose:main"]},
|
||||||
|
include_package_data=True,
|
||||||
|
license="GPL-2.0-only",
|
||||||
|
install_requires=[
|
||||||
|
"pyyaml",
|
||||||
|
"python-dotenv",
|
||||||
|
],
|
||||||
|
extras_require={"devel": ["ruff", "pre-commit", "coverage", "parameterized"]},
|
||||||
|
# test_suite='tests',
|
||||||
|
# tests_require=[
|
||||||
|
# 'coverage',
|
||||||
|
# 'tox',
|
||||||
|
# ]
|
||||||
|
)
|
@ -1,15 +1,10 @@
|
|||||||
-e .
|
-e .
|
||||||
coverage==7.4.3
|
coverage==7.4.3
|
||||||
cryptography==44.0.3
|
|
||||||
parameterized==0.9.0
|
parameterized==0.9.0
|
||||||
pytest==8.0.2
|
pytest==8.0.2
|
||||||
tox==4.13.0
|
tox==4.13.0
|
||||||
mypy==1.15.0
|
ruff==0.3.1
|
||||||
ruff==0.11.11
|
|
||||||
pylint==3.1.0
|
pylint==3.1.0
|
||||||
types-PyYAML==6.0.12.20250402
|
|
||||||
types-requests==2.32.0.20250328
|
|
||||||
types-setuptools==80.7.0.20250516
|
|
||||||
|
|
||||||
# The packages below are transitive dependencies of the packages above and are included here
|
# The packages below are transitive dependencies of the packages above and are included here
|
||||||
# to make testing reproducible.
|
# to make testing reproducible.
|
||||||
@ -28,7 +23,6 @@ filelock==3.13.1
|
|||||||
iniconfig==2.0.0
|
iniconfig==2.0.0
|
||||||
isort==5.13.2
|
isort==5.13.2
|
||||||
mccabe==0.7.0
|
mccabe==0.7.0
|
||||||
mypy_extensions==1.1.0
|
|
||||||
packaging==23.2
|
packaging==23.2
|
||||||
platformdirs==4.2.0
|
platformdirs==4.2.0
|
||||||
pluggy==1.4.0
|
pluggy==1.4.0
|
||||||
@ -37,5 +31,4 @@ python-dotenv==1.0.1
|
|||||||
PyYAML==6.0.1
|
PyYAML==6.0.1
|
||||||
requests
|
requests
|
||||||
tomlkit==0.12.4
|
tomlkit==0.12.4
|
||||||
typing_extensions==4.13.2
|
|
||||||
virtualenv==20.26.6
|
virtualenv==20.26.6
|
||||||
|
@ -2,7 +2,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def create_base_test_image() -> None:
|
def create_base_test_image():
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
['podman', 'build', '-t', 'nopush/podman-compose-test', '.'],
|
['podman', 'build', '-t', 'nopush/podman-compose-test', '.'],
|
||||||
cwd=os.path.join(os.path.dirname(__file__), "base_image"),
|
cwd=os.path.join(os.path.dirname(__file__), "base_image"),
|
||||||
|
@ -10,7 +10,7 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path(failure_order: str) -> str:
|
def compose_yaml_path(failure_order):
|
||||||
return os.path.join(test_path(), "abort", f"docker-compose-fail-{failure_order}.yaml")
|
return os.path.join(test_path(), "abort", f"docker-compose-fail-{failure_order}.yaml")
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ class TestComposeAbort(unittest.TestCase, RunSubprocessMixin):
|
|||||||
("exit", "none", 0),
|
("exit", "none", 0),
|
||||||
("failure", "none", 0),
|
("failure", "none", 0),
|
||||||
])
|
])
|
||||||
def test_abort(self, abort_type: str, failure_order: str, expected_exit_code: int) -> None:
|
def test_abort(self, abort_type, failure_order, expected_exit_code):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -11,13 +11,13 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
""" "Returns the path to the compose file used for this test module"""
|
""" "Returns the path to the compose file used for this test module"""
|
||||||
return os.path.join(test_path(), "additional_contexts", "project")
|
return os.path.join(test_path(), "additional_contexts", "project")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeBuildAdditionalContexts(unittest.TestCase):
|
class TestComposeBuildAdditionalContexts(unittest.TestCase):
|
||||||
def test_build_additional_context(self) -> None:
|
def test_build_additional_context(self):
|
||||||
"""podman build should receive additional contexts as --build-context
|
"""podman build should receive additional contexts as --build-context
|
||||||
|
|
||||||
See additional_context/project/docker-compose.yaml for context paths
|
See additional_context/project/docker-compose.yaml for context paths
|
||||||
|
@ -1 +0,0 @@
|
|||||||
test
|
|
@ -3,12 +3,3 @@ services:
|
|||||||
test:
|
test:
|
||||||
build: ./context
|
build: ./context
|
||||||
image: build-fail-img
|
image: build-fail-img
|
||||||
test_no_dockerfile:
|
|
||||||
build:
|
|
||||||
context: ./context_no_file
|
|
||||||
image: busybox
|
|
||||||
test_no_custom_dockerfile:
|
|
||||||
build:
|
|
||||||
context: ./context_no_file
|
|
||||||
dockerfile: Dockerfile-alt
|
|
||||||
image: busybox
|
|
||||||
|
@ -22,48 +22,9 @@ class TestComposeBuildFail(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"-f",
|
"-f",
|
||||||
compose_yaml_path(),
|
compose_yaml_path(),
|
||||||
"build",
|
"build",
|
||||||
"test",
|
|
||||||
],
|
],
|
||||||
expected_returncode=127,
|
expected_returncode=127,
|
||||||
)
|
)
|
||||||
self.assertIn("RUN this_command_does_not_exist", str(output))
|
self.assertIn("RUN this_command_does_not_exist", str(output))
|
||||||
self.assertIn("this_command_does_not_exist: not found", str(error))
|
self.assertIn("this_command_does_not_exist: not found", str(error))
|
||||||
self.assertIn("while running runtime: exit status 127", str(error))
|
self.assertIn("while running runtime: exit status 127", str(error))
|
||||||
|
|
||||||
def test_dockerfile_does_not_exist(self):
|
|
||||||
out, error = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"build",
|
|
||||||
"test_no_dockerfile",
|
|
||||||
],
|
|
||||||
expected_returncode=1,
|
|
||||||
)
|
|
||||||
error = error.decode('utf-8')
|
|
||||||
result = '\n'.join(error.splitlines()[-1:])
|
|
||||||
|
|
||||||
expected_path = os.path.join(os.path.dirname(__file__), "context_no_file")
|
|
||||||
expected = f'OSError: Dockerfile not found in {expected_path}'
|
|
||||||
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
|
||||||
def test_custom_dockerfile_does_not_exist(self):
|
|
||||||
out, error = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"build",
|
|
||||||
"test_no_custom_dockerfile",
|
|
||||||
],
|
|
||||||
expected_returncode=1,
|
|
||||||
)
|
|
||||||
error = error.decode('utf-8')
|
|
||||||
result = '\n'.join(error.splitlines()[-1:])
|
|
||||||
|
|
||||||
expected_path = os.path.join(os.path.dirname(__file__), "context_no_file/Dockerfile-alt")
|
|
||||||
expected = f'OSError: Dockerfile not found in {expected_path}'
|
|
||||||
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.integration.test_utils import RunSubprocessMixin
|
||||||
|
from tests.integration.test_utils import podman_compose_path
|
||||||
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
|
def compose_yaml_path():
|
||||||
|
""" "Returns the path to the compose file used for this test module"""
|
||||||
|
base_path = os.path.join(test_path(), "build_fail_multi")
|
||||||
|
return os.path.join(base_path, "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
|
class TestComposeBuildFailMulti(unittest.TestCase, RunSubprocessMixin):
|
||||||
|
def test_build_fail_multi(self):
|
||||||
|
output, error = self.run_subprocess_assert_returncode(
|
||||||
|
[
|
||||||
|
podman_compose_path(),
|
||||||
|
"-f",
|
||||||
|
compose_yaml_path(),
|
||||||
|
"build",
|
||||||
|
# prevent the successful build from being cached to ensure it runs long enough
|
||||||
|
"--no-cache",
|
||||||
|
],
|
||||||
|
expected_returncode=1,
|
||||||
|
)
|
||||||
|
self.assertIn("RUN false", str(output))
|
||||||
|
self.assertIn("while running runtime: exit status 1", str(error))
|
@ -1,76 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from tests.integration.test_utils import RunSubprocessMixin
|
|
||||||
from tests.integration.test_utils import podman_compose_path
|
|
||||||
from tests.integration.test_utils import test_path
|
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
|
||||||
""" "Returns the path to the compose file used for this test module"""
|
|
||||||
base_path = os.path.join(test_path(), "commands_fail_exit_code")
|
|
||||||
return os.path.join(base_path, "docker-compose.yml")
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeCommandsFailExitCodes(unittest.TestCase, RunSubprocessMixin):
|
|
||||||
def test_build_command_fail(self) -> None:
|
|
||||||
output, error = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"build",
|
|
||||||
# prevent the successful build from being cached to ensure it runs long enough
|
|
||||||
"--no-cache",
|
|
||||||
],
|
|
||||||
expected_returncode=1,
|
|
||||||
)
|
|
||||||
self.assertIn("RUN false", str(output))
|
|
||||||
self.assertIn("while running runtime: exit status 1", str(error))
|
|
||||||
|
|
||||||
def test_push_command_fail(self) -> None:
|
|
||||||
# test that push command is able to return other than "0" return code
|
|
||||||
# "push" command fails due to several steps missing before running it (logging, tagging)
|
|
||||||
try:
|
|
||||||
output, error = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"push",
|
|
||||||
"good",
|
|
||||||
],
|
|
||||||
expected_returncode=125,
|
|
||||||
)
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"down",
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_run_command_fail(self) -> None:
|
|
||||||
# test that run command is able to return other than "0" return code
|
|
||||||
try:
|
|
||||||
output, error = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"run",
|
|
||||||
"bad",
|
|
||||||
],
|
|
||||||
expected_returncode=125,
|
|
||||||
)
|
|
||||||
self.assertIn("RUN false", str(output))
|
|
||||||
self.assertIn("while running runtime: exit status 1", str(error))
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path(),
|
|
||||||
"down",
|
|
||||||
])
|
|
@ -10,7 +10,7 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path(scenario: str) -> str:
|
def compose_yaml_path(scenario):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
os.path.join(test_path(), "default_net_behavior"), f"docker-compose_{scenario}.yaml"
|
os.path.join(test_path(), "default_net_behavior"), f"docker-compose_{scenario}.yaml"
|
||||||
)
|
)
|
||||||
@ -27,13 +27,13 @@ class TestComposeDefaultNetBehavior(unittest.TestCase, RunSubprocessMixin):
|
|||||||
('two_nets_compat', 'default_net_behavior_default'),
|
('two_nets_compat', 'default_net_behavior_default'),
|
||||||
('with_default_compat', 'default_net_behavior_default'),
|
('with_default_compat', 'default_net_behavior_default'),
|
||||||
])
|
])
|
||||||
def test_nethost(self, scenario: str, default_net: str) -> None:
|
def test_nethost(self, scenario, default_net):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[podman_compose_path(), "-f", compose_yaml_path(scenario), "up", "-d"],
|
[podman_compose_path(), "-f", compose_yaml_path(scenario), "up", "-d"],
|
||||||
)
|
)
|
||||||
|
|
||||||
container_id_out, _ = self.run_subprocess_assert_returncode(
|
container_id, _ = self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
@ -43,7 +43,7 @@ class TestComposeDefaultNetBehavior(unittest.TestCase, RunSubprocessMixin):
|
|||||||
'{{.ID}}',
|
'{{.ID}}',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
container_id = container_id_out.decode('utf-8').split('\n')[0]
|
container_id = container_id.decode('utf-8').split('\n')[0]
|
||||||
output, _ = self.run_subprocess_assert_returncode(
|
output, _ = self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
"podman",
|
"podman",
|
||||||
|
@ -9,12 +9,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path(suffix: str = "") -> str:
|
def compose_yaml_path(suffix=""):
|
||||||
return os.path.join(os.path.join(test_path(), "deps"), f"docker-compose{suffix}.yaml")
|
return os.path.join(os.path.join(test_path(), "deps"), f"docker-compose{suffix}.yaml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_deps(self) -> None:
|
def test_deps(self):
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -37,7 +37,7 @@ class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_run_nodeps(self) -> None:
|
def test_run_nodeps(self):
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -62,7 +62,7 @@ class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_up_nodeps(self) -> None:
|
def test_up_nodeps(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -89,7 +89,7 @@ class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_podman_compose_run(self) -> None:
|
def test_podman_compose_run(self):
|
||||||
"""
|
"""
|
||||||
This will test depends_on as well
|
This will test depends_on as well
|
||||||
"""
|
"""
|
||||||
@ -143,7 +143,7 @@ class TestComposeBaseDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
|
|
||||||
|
|
||||||
class TestComposeConditionalDeps(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeConditionalDeps(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_deps_succeeds(self) -> None:
|
def test_deps_succeeds(self):
|
||||||
suffix = "-conditional-succeeds"
|
suffix = "-conditional-succeeds"
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
@ -167,7 +167,7 @@ class TestComposeConditionalDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_deps_fails(self) -> None:
|
def test_deps_fails(self):
|
||||||
suffix = "-conditional-fails"
|
suffix = "-conditional-fails"
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
@ -188,10 +188,10 @@ class TestComposeConditionalDeps(unittest.TestCase, RunSubprocessMixin):
|
|||||||
|
|
||||||
|
|
||||||
class TestComposeConditionalDepsHealthy(unittest.TestCase, PodmanAwareRunSubprocessMixin):
|
class TestComposeConditionalDepsHealthy(unittest.TestCase, PodmanAwareRunSubprocessMixin):
|
||||||
def setUp(self) -> None:
|
def setUp(self):
|
||||||
self.podman_version = self.retrieve_podman_version()
|
self.podman_version = self.retrieve_podman_version()
|
||||||
|
|
||||||
def test_up_deps_healthy(self) -> None:
|
def test_up_deps_healthy(self):
|
||||||
suffix = "-conditional-healthy"
|
suffix = "-conditional-healthy"
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
@ -261,6 +261,6 @@ class TestComposeConditionalDepsHealthy(unittest.TestCase, PodmanAwareRunSubproc
|
|||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
compose_yaml_path(suffix),
|
compose_yaml_path(),
|
||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
2
tests/integration/env-file-tests/.env
Normal file
2
tests/integration/env-file-tests/.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ZZVAR1='This value is overwritten by env-file-tests/.env'
|
||||||
|
ZZVAR3='This value is loaded from env-file-tests/.env'
|
@ -1,3 +1,2 @@
|
|||||||
ZZVAR1='This value is loaded but should be overwritten'
|
ZZVAR1='This value is loaded but should be overwritten'
|
||||||
ZZVAR2='This value is loaded from .env in project/ directory'
|
ZZVAR2='This value is loaded from .env in project/ directory'
|
||||||
ZZVAR3=TEST
|
|
@ -8,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_base_path() -> str:
|
def compose_base_path():
|
||||||
return os.path.join(test_path(), "env_file_tests")
|
return os.path.join(test_path(), "env-file-tests")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_path_env_file_inline(self) -> None:
|
def test_path_env_file_inline(self):
|
||||||
# Test taking env variable value directly from env-file when its path is inline path
|
# Test taking env variable value directly from env-file when its path is inline path
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
path_compose_file = os.path.join(base_path, "project/container-compose.yaml")
|
path_compose_file = os.path.join(base_path, "project/container-compose.yaml")
|
||||||
@ -42,7 +42,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_path_env_file_flat_in_compose_file(self) -> None:
|
def test_path_env_file_flat_in_compose_file(self):
|
||||||
# Test taking env variable value from env-file/project-1.env which was declared in
|
# Test taking env variable value from env-file/project-1.env which was declared in
|
||||||
# compose file's env_file
|
# compose file's env_file
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
@ -74,7 +74,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_path_env_file_obj_in_compose_file(self) -> None:
|
def test_path_env_file_obj_in_compose_file(self):
|
||||||
# take variable value from env-file project-1.env which was declared in compose
|
# take variable value from env-file project-1.env which was declared in compose
|
||||||
# file's env_file by -path: ...
|
# file's env_file by -path: ...
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
@ -106,7 +106,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_exists_optional_env_file_path_in_compose_file(self) -> None:
|
def test_exists_optional_env_file_path_in_compose_file(self):
|
||||||
# test taking env variable values from several env-files when one of them is optional
|
# test taking env variable values from several env-files when one of them is optional
|
||||||
# and exists
|
# and exists
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
@ -139,7 +139,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_missing_optional_env_file_path_in_compose_file(self) -> None:
|
def test_missing_optional_env_file_path_in_compose_file(self):
|
||||||
# test taking env variable values from several env-files when one of them is optional and
|
# test taking env variable values from several env-files when one of them is optional and
|
||||||
# is missing (silently skip it)
|
# is missing (silently skip it)
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
@ -173,7 +173,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_var_value_inline_overrides_env_file_path_inline(self) -> None:
|
def test_var_value_inline_overrides_env_file_path_inline(self):
|
||||||
# Test overriding env value when value is declared in inline command
|
# Test overriding env value when value is declared in inline command
|
||||||
base_path = compose_base_path()
|
base_path = compose_base_path()
|
||||||
path_compose_file = os.path.join(base_path, "project/container-compose.yaml")
|
path_compose_file = os.path.join(base_path, "project/container-compose.yaml")
|
||||||
@ -204,7 +204,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_taking_env_variables_from_env_files_from_different_directories(self) -> None:
|
def test_taking_env_variables_from_env_files_from_different_directories(self):
|
||||||
# FIXME: It is not clear what this test actually tests, but from README.md it looks like:
|
# FIXME: It is not clear what this test actually tests, but from README.md it looks like:
|
||||||
# Test overriding env values by directory env-files-tests/.env file values
|
# Test overriding env values by directory env-files-tests/.env file values
|
||||||
# and only take value from project/.env, when it does not exist in env-files-tests/.env
|
# and only take value from project/.env, when it does not exist in env-files-tests/.env
|
||||||
@ -233,7 +233,7 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
[
|
[
|
||||||
'ZZVAR1=This value is loaded but should be overwritten\r',
|
'ZZVAR1=This value is loaded but should be overwritten\r',
|
||||||
'ZZVAR2=This value is loaded from .env in project/ directory\r',
|
'ZZVAR2=This value is loaded from .env in project/ directory\r',
|
||||||
'ZZVAR3=TEST\r',
|
'ZZVAR3=\r',
|
||||||
'',
|
'',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -244,36 +244,3 @@ class TestComposeEnvFile(unittest.TestCase, RunSubprocessMixin):
|
|||||||
path_compose_file,
|
path_compose_file,
|
||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_env_var_value_accessed_in_compose_file_short_syntax(self) -> None:
|
|
||||||
# Test that compose file can access the environment variable set in .env file using
|
|
||||||
# short syntax, that is: only the name of environment variable is used in "environment:" in
|
|
||||||
# compose.yml file and its value is picked up directly from .env file
|
|
||||||
# long syntax of environment variables interpolation is tested in
|
|
||||||
# tests/integration/interpolation
|
|
||||||
|
|
||||||
base_path = compose_base_path()
|
|
||||||
compose_file_path = os.path.join(base_path, "project/container-compose.short_syntax.yaml")
|
|
||||||
try:
|
|
||||||
self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_file_path,
|
|
||||||
"up",
|
|
||||||
"-d",
|
|
||||||
])
|
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_file_path,
|
|
||||||
"logs",
|
|
||||||
])
|
|
||||||
# ZZVAR3 was set in .env file
|
|
||||||
self.assertEqual(output, b"ZZVAR3=TEST\n")
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_file_path,
|
|
||||||
"down",
|
|
||||||
])
|
|
@ -8,14 +8,14 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "env_tests"), "container-compose.yml")
|
return os.path.join(os.path.join(test_path(), "env-tests"), "container-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeEnv(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeEnv(unittest.TestCase, RunSubprocessMixin):
|
||||||
"""Test that inline environment variable overrides environment variable from compose file."""
|
"""Test that inline environment variable overrides environment variable from compose file."""
|
||||||
|
|
||||||
def test_env(self) -> None:
|
def test_env(self):
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -50,7 +50,7 @@ class TestComposeEnv(unittest.TestCase, RunSubprocessMixin):
|
|||||||
- https://github.com/compose-spec/compose-spec/blob/main/04-version-and-name.md
|
- https://github.com/compose-spec/compose-spec/blob/main/04-version-and-name.md
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def test_project_name(self) -> None:
|
def test_project_name(self):
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -68,7 +68,7 @@ class TestComposeEnv(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_project_name_override(self) -> None:
|
def test_project_name_override(self):
|
||||||
try:
|
try:
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
output, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
@ -1,2 +0,0 @@
|
|||||||
ZZVAR1='This value is overwritten by env_file_tests/.env'
|
|
||||||
ZZVAR3='This value is loaded from env_file_tests/.env'
|
|
@ -1,10 +0,0 @@
|
|||||||
services:
|
|
||||||
app:
|
|
||||||
image: nopush/podman-compose-test
|
|
||||||
command: ["/bin/busybox", "sh", "-c", "env | grep ZZVAR3"]
|
|
||||||
# 'env_file:' section is not used, so .env file is searched in the same directory as compose.yml
|
|
||||||
# file
|
|
||||||
environment:
|
|
||||||
# this is short syntax: podman-compose takes only this variable value from '.env' file and
|
|
||||||
# sends it to container environment
|
|
||||||
- ZZVAR3
|
|
@ -8,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "exit_from"), "docker-compose.yaml")
|
return os.path.join(os.path.join(test_path(), "exit-from"), "docker-compose.yaml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeExitFrom(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeExitFrom(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_exit_code_sh1(self) -> None:
|
def test_exit_code_sh1(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
@ -33,7 +33,7 @@ class TestComposeExitFrom(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_exit_code_sh2(self) -> None:
|
def test_exit_code_sh2(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
@ -53,13 +53,13 @@ class TestComposeExitFrom(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_podman_compose_exit_from(self) -> None:
|
def test_podman_compose_exit_from(self):
|
||||||
up_cmd = [
|
up_cmd = [
|
||||||
"coverage",
|
"coverage",
|
||||||
"run",
|
"run",
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
compose_yaml_path(),
|
os.path.join(test_path(), "exit-from", "docker-compose.yaml"),
|
||||||
"up",
|
"up",
|
||||||
]
|
]
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -8,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "extends"), "docker-compose.yaml")
|
return os.path.join(os.path.join(test_path(), "extends"), "docker-compose.yaml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeExteds(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeExteds(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_extends_service_launch_echo(self) -> None:
|
def test_extends_service_launch_echo(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -38,7 +38,7 @@ class TestComposeExteds(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_extends_service_launch_echo1(self) -> None:
|
def test_extends_service_launch_echo1(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
@ -63,7 +63,7 @@ class TestComposeExteds(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_extends_service_launch_env1(self) -> None:
|
def test_extends_service_launch_env1(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
|
@ -9,12 +9,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "extends_w_empty_service"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "extends_w_empty_service"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeExtendsWithEmptyService(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeExtendsWithEmptyService(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_extends_w_empty_service(self) -> None:
|
def test_extends_w_empty_service(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
@ -39,7 +39,7 @@ class TestComposeExtendsWithEmptyService(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_podman_compose_extends_w_empty_service(self) -> None:
|
def test_podman_compose_extends_w_empty_service(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose can execute podman-compose -f <file> up with extended File which
|
Test that podman-compose can execute podman-compose -f <file> up with extended File which
|
||||||
includes an empty service. (e.g. if the file is used as placeholder for more complex
|
includes an empty service. (e.g. if the file is used as placeholder for more complex
|
||||||
|
@ -8,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "extends_w_file"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "extends_w_file"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeExtendsWithFile(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeExtendsWithFile(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_extends_w_file(self) -> None: # when file is Dockerfile for building the image
|
def test_extends_w_file(self): # when file is Dockerfile for building the image
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -9,12 +9,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "extends_w_file_subdir"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "extends_w_file_subdir"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeExtendsWithFileSubdir(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeExtendsWithFileSubdir(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_extends_w_file_subdir(self) -> None: # when file is Dockerfile for building the image
|
def test_extends_w_file_subdir(self): # when file is Dockerfile for building the image
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
@ -39,7 +39,7 @@ class TestComposeExtendsWithFileSubdir(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"down",
|
"down",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_podman_compose_extends_w_file_subdir(self) -> None:
|
def test_podman_compose_extends_w_file_subdir(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose can execute podman-compose -f <file> up with extended File which
|
Test that podman-compose can execute podman-compose -f <file> up with extended File which
|
||||||
includes a build context
|
includes a build context
|
||||||
|
@ -10,7 +10,7 @@ from tests.integration.test_utils import test_path
|
|||||||
|
|
||||||
|
|
||||||
class TestFilesystem(unittest.TestCase, RunSubprocessMixin):
|
class TestFilesystem(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_compose_symlink(self) -> None:
|
def test_compose_symlink(self):
|
||||||
"""The context of podman-compose.yml should come from the same directory as the file even
|
"""The context of podman-compose.yml should come from the same directory as the file even
|
||||||
if it is a symlink
|
if it is a symlink
|
||||||
"""
|
"""
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
services:
|
|
||||||
cont:
|
|
||||||
image: nopush/podman-compose-test
|
|
||||||
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
|
||||||
|
|
||||||
x-podman:
|
|
||||||
in_pod: custom_test_pod_name
|
|
@ -6,26 +6,26 @@ import unittest
|
|||||||
from tests.integration.test_utils import RunSubprocessMixin
|
from tests.integration.test_utils import RunSubprocessMixin
|
||||||
|
|
||||||
|
|
||||||
def base_path() -> str:
|
def base_path():
|
||||||
"""Returns the base path for the project"""
|
"""Returns the base path for the project"""
|
||||||
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||||
|
|
||||||
|
|
||||||
def test_path() -> str:
|
def test_path():
|
||||||
"""Returns the path to the tests directory"""
|
"""Returns the path to the tests directory"""
|
||||||
return os.path.join(base_path(), "tests/integration")
|
return os.path.join(base_path(), "tests/integration")
|
||||||
|
|
||||||
|
|
||||||
def podman_compose_path() -> str:
|
def podman_compose_path():
|
||||||
"""Returns the path to the podman compose script"""
|
"""Returns the path to the podman compose script"""
|
||||||
return os.path.join(base_path(), "podman_compose.py")
|
return os.path.join(base_path(), "podman_compose.py")
|
||||||
|
|
||||||
|
|
||||||
def is_root() -> bool:
|
def is_root():
|
||||||
return os.geteuid() == 0
|
return os.geteuid() == 0
|
||||||
|
|
||||||
|
|
||||||
def failure_exitcode_when_rootful() -> int:
|
def failure_exitcode_when_rootful():
|
||||||
if is_root():
|
if is_root():
|
||||||
return 125
|
return 125
|
||||||
return 0
|
return 0
|
||||||
@ -37,7 +37,7 @@ def failure_exitcode_when_rootful() -> int:
|
|||||||
# Test all combinations of command line argument in_pod and compose file argument in_pod.
|
# Test all combinations of command line argument in_pod and compose file argument in_pod.
|
||||||
class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
||||||
# compose file provides x-podman in_pod=false
|
# compose file provides x-podman in_pod=false
|
||||||
def test_x_podman_in_pod_false_command_line_in_pod_not_exists(self) -> None:
|
def test_x_podman_in_pod_false_command_line_in_pod_not_exists(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
||||||
does not provide this option
|
does not provide this option
|
||||||
@ -82,7 +82,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# throws an error, can not actually find this pod because it was not created
|
# throws an error, can not actually find this pod because it was not created
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, expected_returncode=1)
|
self.run_subprocess_assert_returncode(command_rm_pod, expected_returncode=1)
|
||||||
|
|
||||||
def test_x_podman_in_pod_false_command_line_in_pod_true(self) -> None:
|
def test_x_podman_in_pod_false_command_line_in_pod_true(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating even with command line in_pod=True
|
Test that podman-compose does not allow pod creating even with command line in_pod=True
|
||||||
when --userns and --pod are set together: throws an error
|
when --userns and --pod are set together: throws an error
|
||||||
@ -115,7 +115,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# been created) and have expected_returncode=1 (see FIXME above)
|
# been created) and have expected_returncode=1 (see FIXME above)
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
def test_x_podman_in_pod_false_command_line_in_pod_false(self) -> None:
|
def test_x_podman_in_pod_false_command_line_in_pod_false(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||||
"""
|
"""
|
||||||
@ -160,7 +160,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# can not actually find this pod because it was not created
|
# can not actually find this pod because it was not created
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||||
|
|
||||||
def test_x_podman_in_pod_false_command_line_in_pod_empty_string(self) -> None:
|
def test_x_podman_in_pod_false_command_line_in_pod_empty_string(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
||||||
command line in_pod=""
|
command line in_pod=""
|
||||||
@ -207,7 +207,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||||
|
|
||||||
# compose file provides x-podman in_pod=true
|
# compose file provides x-podman in_pod=true
|
||||||
def test_x_podman_in_pod_true_command_line_in_pod_not_exists(self) -> None:
|
def test_x_podman_in_pod_true_command_line_in_pod_not_exists(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together even when x-podman in_pod=true: throws an error
|
together even when x-podman in_pod=true: throws an error
|
||||||
@ -240,7 +240,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# created) and have expected_returncode=1 (see FIXME above)
|
# created) and have expected_returncode=1 (see FIXME above)
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
def test_x_podman_in_pod_true_command_line_in_pod_true(self) -> None:
|
def test_x_podman_in_pod_true_command_line_in_pod_true(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together even when x-podman in_pod=true and and command line in_pod=True: throws an error
|
together even when x-podman in_pod=true and and command line in_pod=True: throws an error
|
||||||
@ -274,7 +274,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# been created) and have expected_returncode=1 (see FIXME above)
|
# been created) and have expected_returncode=1 (see FIXME above)
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
def test_x_podman_in_pod_true_command_line_in_pod_false(self) -> None:
|
def test_x_podman_in_pod_true_command_line_in_pod_false(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||||
"""
|
"""
|
||||||
@ -319,7 +319,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# can not actually find this pod because it was not created
|
# can not actually find this pod because it was not created
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||||
|
|
||||||
def test_x_podman_in_pod_true_command_line_in_pod_empty_string(self) -> None:
|
def test_x_podman_in_pod_true_command_line_in_pod_empty_string(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together even when x-podman in_pod=true and command line in_pod="": throws an error
|
together even when x-podman in_pod=true and command line in_pod="": throws an error
|
||||||
@ -354,7 +354,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
# compose file does not provide x-podman in_pod
|
# compose file does not provide x-podman in_pod
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_not_exists(self) -> None:
|
def test_x_podman_in_pod_not_exists_command_line_in_pod_not_exists(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together: throws an error
|
together: throws an error
|
||||||
@ -387,7 +387,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# created) and have expected_returncode=1 (see FIXME above)
|
# created) and have expected_returncode=1 (see FIXME above)
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_true(self) -> None:
|
def test_x_podman_in_pod_not_exists_command_line_in_pod_true(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together even when x-podman in_pod=true: throws an error
|
together even when x-podman in_pod=true: throws an error
|
||||||
@ -421,7 +421,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# been created) and have expected_returncode=1 (see FIXME above)
|
# been created) and have expected_returncode=1 (see FIXME above)
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||||
|
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_false(self) -> None:
|
def test_x_podman_in_pod_not_exists_command_line_in_pod_false(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||||
"""
|
"""
|
||||||
@ -467,136 +467,7 @@ class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
|||||||
# can not actually find this pod because it was not created
|
# can not actually find this pod because it was not created
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||||
|
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_not_exists_docker_compat(self) -> None:
|
def test_x_podman_in_pod_not_exists_command_line_in_pod_empty_string(self):
|
||||||
"""
|
|
||||||
Test that podman-compose will not create a pod when docker compat is requested.
|
|
||||||
"""
|
|
||||||
command_up = [
|
|
||||||
"python3",
|
|
||||||
os.path.join(base_path(), "podman_compose.py"),
|
|
||||||
"-f",
|
|
||||||
os.path.join(
|
|
||||||
base_path(),
|
|
||||||
"tests",
|
|
||||||
"integration",
|
|
||||||
"in_pod",
|
|
||||||
"custom_x-podman_not_exists",
|
|
||||||
"docker-compose.yml",
|
|
||||||
),
|
|
||||||
"up",
|
|
||||||
"-d",
|
|
||||||
]
|
|
||||||
|
|
||||||
down_cmd = [
|
|
||||||
"python3",
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
os.path.join(
|
|
||||||
base_path(),
|
|
||||||
"tests",
|
|
||||||
"integration",
|
|
||||||
"in_pod",
|
|
||||||
"custom_x-podman_not_exists",
|
|
||||||
"docker-compose.yml",
|
|
||||||
),
|
|
||||||
"down",
|
|
||||||
]
|
|
||||||
|
|
||||||
env = {
|
|
||||||
"PODMAN_COMPOSE_DOCKER_COMPOSE_COMPAT": "1",
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.run_subprocess_assert_returncode(
|
|
||||||
command_up, failure_exitcode_when_rootful(), env=env
|
|
||||||
)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode(down_cmd, env=env)
|
|
||||||
|
|
||||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
|
||||||
# can not actually find this pod because it was not created
|
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
|
||||||
|
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_not_exists_env_var(self) -> None:
|
|
||||||
"""
|
|
||||||
Test that podman-compose will not create a pod when env var is set.
|
|
||||||
"""
|
|
||||||
command_up = [
|
|
||||||
"python3",
|
|
||||||
os.path.join(base_path(), "podman_compose.py"),
|
|
||||||
"-f",
|
|
||||||
os.path.join(
|
|
||||||
base_path(),
|
|
||||||
"tests",
|
|
||||||
"integration",
|
|
||||||
"in_pod",
|
|
||||||
"custom_x-podman_not_exists",
|
|
||||||
"docker-compose.yml",
|
|
||||||
),
|
|
||||||
"up",
|
|
||||||
"-d",
|
|
||||||
]
|
|
||||||
|
|
||||||
down_cmd = [
|
|
||||||
"python3",
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
os.path.join(
|
|
||||||
base_path(),
|
|
||||||
"tests",
|
|
||||||
"integration",
|
|
||||||
"in_pod",
|
|
||||||
"custom_x-podman_not_exists",
|
|
||||||
"docker-compose.yml",
|
|
||||||
),
|
|
||||||
"down",
|
|
||||||
]
|
|
||||||
|
|
||||||
env = {
|
|
||||||
"PODMAN_COMPOSE_IN_POD": "0",
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.run_subprocess_assert_returncode(
|
|
||||||
command_up, failure_exitcode_when_rootful(), env=env
|
|
||||||
)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode(down_cmd, env=env)
|
|
||||||
|
|
||||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
|
||||||
# can not actually find this pod because it was not created
|
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
|
||||||
|
|
||||||
def test_x_podman_in_pod_custom_name(self) -> None:
|
|
||||||
"""
|
|
||||||
Test that podman-compose will create a pod with a custom name
|
|
||||||
"""
|
|
||||||
command_up = [
|
|
||||||
"python3",
|
|
||||||
os.path.join(base_path(), "podman_compose.py"),
|
|
||||||
"-f",
|
|
||||||
os.path.join(
|
|
||||||
base_path(),
|
|
||||||
"tests",
|
|
||||||
"integration",
|
|
||||||
"in_pod",
|
|
||||||
"custom_x-podman_custom_name",
|
|
||||||
"docker-compose.yml",
|
|
||||||
),
|
|
||||||
"up",
|
|
||||||
"--no-start",
|
|
||||||
]
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.run_subprocess_assert_returncode(command_up)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
command_rm_pod = ["podman", "pod", "rm", "custom_test_pod_name"]
|
|
||||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
|
||||||
|
|
||||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_empty_string(self) -> None:
|
|
||||||
"""
|
"""
|
||||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||||
together: throws an error
|
together: throws an error
|
||||||
|
@ -7,7 +7,7 @@ from tests.integration.test_utils import RunSubprocessMixin
|
|||||||
|
|
||||||
|
|
||||||
class TestPodmanComposeInclude(unittest.TestCase, RunSubprocessMixin):
|
class TestPodmanComposeInclude(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_podman_compose_include(self) -> None:
|
def test_podman_compose_include(self):
|
||||||
"""
|
"""
|
||||||
Test that podman-compose can execute podman-compose -f <file> up with include
|
Test that podman-compose can execute podman-compose -f <file> up with include
|
||||||
:return:
|
:return:
|
||||||
|
@ -1,2 +1 @@
|
|||||||
DOT_ENV_VARIABLE=This value is from the .env file
|
DOT_ENV_VARIABLE=This value is from the .env file
|
||||||
TEST_LABELS=TEST
|
|
||||||
|
@ -11,10 +11,4 @@ services:
|
|||||||
EXAMPLE_DOT_ENV: $DOT_ENV_VARIABLE
|
EXAMPLE_DOT_ENV: $DOT_ENV_VARIABLE
|
||||||
EXAMPLE_LITERAL: This is a $$literal
|
EXAMPLE_LITERAL: This is a $$literal
|
||||||
EXAMPLE_EMPTY: $NOT_A_VARIABLE
|
EXAMPLE_EMPTY: $NOT_A_VARIABLE
|
||||||
labels_test:
|
|
||||||
image: busybox
|
|
||||||
labels:
|
|
||||||
- "$TEST_LABELS=test_labels"
|
|
||||||
- test.${TEST_LABELS}=${TEST_LABELS}
|
|
||||||
- "${TEST_LABELS}.test2=test2(`${TEST_LABELS}`)"
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@ -9,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "interpolation"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "interpolation"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeInterpolation(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeInterpolation(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_interpolation(self) -> None:
|
def test_interpolation(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
"env",
|
"env",
|
||||||
@ -37,18 +36,6 @@ class TestComposeInterpolation(unittest.TestCase, RunSubprocessMixin):
|
|||||||
self.assertIn("EXAMPLE_DOT_ENV='This value is from the .env file'", str(output))
|
self.assertIn("EXAMPLE_DOT_ENV='This value is from the .env file'", str(output))
|
||||||
self.assertIn("EXAMPLE_EMPTY=''", str(output))
|
self.assertIn("EXAMPLE_EMPTY=''", str(output))
|
||||||
self.assertIn("EXAMPLE_LITERAL='This is a $literal'", str(output))
|
self.assertIn("EXAMPLE_LITERAL='This is a $literal'", str(output))
|
||||||
|
|
||||||
output, _ = self.run_subprocess_assert_returncode([
|
|
||||||
"podman",
|
|
||||||
"inspect",
|
|
||||||
"interpolation_labels_test_1",
|
|
||||||
])
|
|
||||||
inspect_output = json.loads(output)
|
|
||||||
labels_dict = inspect_output[0].get("Config", {}).get("Labels", {})
|
|
||||||
self.assertIn(('TEST', 'test_labels'), labels_dict.items())
|
|
||||||
self.assertIn(('TEST.test2', 'test2(`TEST`)'), labels_dict.items())
|
|
||||||
self.assertIn(('test.TEST', 'TEST'), labels_dict.items())
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
|
@ -9,12 +9,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "ipam_default"), "docker-compose.yaml")
|
return os.path.join(os.path.join(test_path(), "ipam_default"), "docker-compose.yaml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeIpamDefault(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeIpamDefault(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_ipam_default(self) -> None:
|
def test_ipam_default(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[podman_compose_path(), "-f", compose_yaml_path(), "up", "-d"],
|
[podman_compose_path(), "-f", compose_yaml_path(), "up", "-d"],
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
@ -13,7 +12,7 @@ from tests.integration.test_utils import test_path
|
|||||||
|
|
||||||
|
|
||||||
class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_up_single_container(self) -> None:
|
def test_up_single_container(self):
|
||||||
"""Podman compose up should be able to start containers one after another"""
|
"""Podman compose up should be able to start containers one after another"""
|
||||||
|
|
||||||
compose_path = os.path.join(test_path(), "lifetime/up_single_container/docker-compose.yml")
|
compose_path = os.path.join(test_path(), "lifetime/up_single_container/docker-compose.yml")
|
||||||
@ -69,7 +68,7 @@ class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
|||||||
("no_ports", "up_single_container_many_times"),
|
("no_ports", "up_single_container_many_times"),
|
||||||
("with_ports", "up_single_container_many_times_with_ports"),
|
("with_ports", "up_single_container_many_times_with_ports"),
|
||||||
])
|
])
|
||||||
def test_up_single_container_many_times(self, name: str, subdir: str) -> None:
|
def test_up_single_container_many_times(self, name, subdir):
|
||||||
"""Podman compose up should be able to start a container many times after it finishes
|
"""Podman compose up should be able to start a container many times after it finishes
|
||||||
running.
|
running.
|
||||||
"""
|
"""
|
||||||
@ -86,6 +85,7 @@ class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"container1",
|
"container1",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
for _ in range(0, 3):
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
@ -105,7 +105,6 @@ class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
|||||||
|
|
||||||
self.assertEqual(out, b"test1\n")
|
self.assertEqual(out, b"test1\n")
|
||||||
|
|
||||||
# "restart: always" keeps restarting container until its removal
|
|
||||||
out, _ = self.run_subprocess_assert_returncode([
|
out, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
@ -114,22 +113,13 @@ class TestLifetime(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"container2",
|
"container2",
|
||||||
])
|
])
|
||||||
|
|
||||||
if not out.startswith(b"test2\ntest2"):
|
# BUG: container should be started 3 times, not 4.
|
||||||
time.sleep(1)
|
self.assertEqual(out, b"test2\n" * 4)
|
||||||
out, _ = self.run_subprocess_assert_returncode([
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_path,
|
|
||||||
"logs",
|
|
||||||
"container2",
|
|
||||||
])
|
|
||||||
self.assertTrue(out.startswith(b"test2\ntest2"))
|
|
||||||
finally:
|
finally:
|
||||||
out, _ = self.run_subprocess_assert_returncode([
|
out, _ = self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
compose_path,
|
compose_path,
|
||||||
"down",
|
"down",
|
||||||
"-t",
|
|
||||||
"0",
|
|
||||||
])
|
])
|
||||||
|
@ -5,5 +5,5 @@ services:
|
|||||||
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
|
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
|
||||||
container2:
|
container2:
|
||||||
image: nopush/podman-compose-test
|
image: nopush/podman-compose-test
|
||||||
restart: always
|
restart: never
|
||||||
command: ["/bin/bash", "-c", "echo test2"]
|
command: ["/bin/bash", "-c", "echo test2"]
|
||||||
|
@ -6,6 +6,6 @@ services:
|
|||||||
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
|
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
|
||||||
container2:
|
container2:
|
||||||
image: nopush/podman-compose-test
|
image: nopush/podman-compose-test
|
||||||
restart: always
|
restart: never
|
||||||
ports: "9002:9002"
|
ports: "9002:9002"
|
||||||
command: ["/bin/bash", "-c", "echo test2"]
|
command: ["/bin/bash", "-c", "echo test2"]
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -9,19 +9,16 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(
|
return os.path.join(os.path.join(test_path(), "override_tag_attribute"), "docker-compose.yaml")
|
||||||
test_path(),
|
|
||||||
"merge/reset_and_override_tags/override_tag_attribute/docker-compose.yaml",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeOverrideTagAttribute(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeOverrideTagAttribute(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if a service attribute from docker-compose.yaml file is overridden
|
# test if a service attribute from docker-compose.yaml file is overridden
|
||||||
def test_override_tag_attribute(self) -> None:
|
def test_override_tag_attribute(self):
|
||||||
override_file = os.path.join(
|
override_file = os.path.join(
|
||||||
test_path(),
|
os.path.join(test_path(), "override_tag_attribute"),
|
||||||
"merge/reset_and_override_tags/override_tag_attribute/docker-compose.override_attribute.yaml",
|
"docker-compose.override_attribute.yaml",
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
|
@ -9,19 +9,16 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(
|
return os.path.join(os.path.join(test_path(), "override_tag_service"), "docker-compose.yaml")
|
||||||
test_path(),
|
|
||||||
"merge/reset_and_override_tags/override_tag_service/docker-compose.yaml",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeOverrideTagService(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeOverrideTagService(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if whole service from docker-compose.yaml file is overridden in another file
|
# test if whole service from docker-compose.yaml file is overridden in another file
|
||||||
def test_override_tag_service(self) -> None:
|
def test_override_tag_service(self):
|
||||||
override_file = os.path.join(
|
override_file = os.path.join(
|
||||||
test_path(),
|
os.path.join(test_path(), "override_tag_service"),
|
||||||
"merge/reset_and_override_tags/override_tag_service/docker-compose.override_service.yaml",
|
"docker-compose.override_service.yaml",
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
|
@ -3,4 +3,3 @@ services:
|
|||||||
app:
|
app:
|
||||||
image: busybox
|
image: busybox
|
||||||
command: !reset {}
|
command: !reset {}
|
||||||
depends_on: !reset null
|
|
||||||
|
@ -3,5 +3,3 @@ services:
|
|||||||
app:
|
app:
|
||||||
image: busybox
|
image: busybox
|
||||||
command: ["/bin/busybox", "echo", "Zero"]
|
command: ["/bin/busybox", "echo", "Zero"]
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
|
@ -8,19 +8,15 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(
|
return os.path.join(os.path.join(test_path(), "reset_tag_attribute"), "docker-compose.yaml")
|
||||||
test_path(),
|
|
||||||
"merge/reset_and_override_tags/reset_tag_attribute/docker-compose.yaml",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeResetTagAttribute(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeResetTagAttribute(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if the attribute of the service is correctly reset
|
# test if the attribute of the service is correctly reset
|
||||||
def test_reset_tag_attribute(self) -> None:
|
def test_reset_tag_attribute(self):
|
||||||
reset_file = os.path.join(
|
reset_file = os.path.join(
|
||||||
test_path(),
|
os.path.join(test_path(), "reset_tag_attribute"), "docker-compose.reset_attribute.yaml"
|
||||||
"merge/reset_and_override_tags/reset_tag_attribute/docker-compose.reset_attribute.yaml",
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
@ -53,8 +49,6 @@ class TestComposeResetTagAttribute(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"logs",
|
"logs",
|
||||||
])
|
])
|
||||||
self.assertEqual(output, b"")
|
self.assertEqual(output, b"")
|
||||||
# depends_on: !reset null testing: if this test works, depends_on is correctly reset.
|
|
||||||
# Otherwise the test would break, since "db" dependency service is not provided
|
|
||||||
finally:
|
finally:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
|
@ -8,18 +8,15 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(
|
return os.path.join(os.path.join(test_path(), "reset_tag_service"), "docker-compose.yaml")
|
||||||
test_path(), "merge/reset_and_override_tags/reset_tag_service/docker-compose.yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeResetTagService(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeResetTagService(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if whole service from docker-compose.yaml file is reset
|
# test if whole service from docker-compose.yaml file is reset
|
||||||
def test_reset_tag_service(self) -> None:
|
def test_reset_tag_service(self):
|
||||||
reset_file = os.path.join(
|
reset_file = os.path.join(
|
||||||
test_path(),
|
os.path.join(test_path(), "reset_tag_service"), "docker-compose.reset_service.yaml"
|
||||||
"merge/reset_and_override_tags/reset_tag_service/docker-compose.reset_service.yaml",
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
|
@ -9,14 +9,14 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path(compose_name: str) -> str:
|
def compose_yaml_path(compose_name):
|
||||||
""" "Returns the path to the compose file used for this test module"""
|
""" "Returns the path to the compose file used for this test module"""
|
||||||
base_path = os.path.join(test_path(), "merge/volumes_merge/")
|
base_path = os.path.join(test_path(), "volumes_merge/")
|
||||||
return os.path.join(base_path, compose_name)
|
return os.path.join(base_path, compose_name)
|
||||||
|
|
||||||
|
|
||||||
class TestComposeVolumesMerge(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeVolumesMerge(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_volumes_merge(self) -> None:
|
def test_volumes_merge(self):
|
||||||
# test if additional compose file overrides host path and access mode of a volume
|
# test if additional compose file overrides host path and access mode of a volume
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
@ -55,7 +55,7 @@ class TestComposeVolumesMerge(unittest.TestCase, RunSubprocessMixin):
|
|||||||
binds_info = volumes_info["HostConfig"]["Binds"]
|
binds_info = volumes_info["HostConfig"]["Binds"]
|
||||||
binds_info.sort()
|
binds_info.sort()
|
||||||
|
|
||||||
file_path = os.path.join(test_path(), "merge/volumes_merge/override.txt")
|
file_path = os.path.join(test_path(), "volumes_merge/override.txt")
|
||||||
expected = [
|
expected = [
|
||||||
f'{file_path}:/var/www/html/index.html:ro,rprivate,rbind',
|
f'{file_path}:/var/www/html/index.html:ro,rprivate,rbind',
|
||||||
f'{file_path}:/var/www/html/index2.html:rw,rprivate,rbind',
|
f'{file_path}:/var/www/html/index2.html:rw,rprivate,rbind',
|
||||||
|
@ -8,12 +8,12 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "multicompose"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "multicompose"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeMulticompose(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeMulticompose(unittest.TestCase, RunSubprocessMixin):
|
||||||
def test_multicompose(self) -> None:
|
def test_multicompose(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
services:
|
|
||||||
web:
|
|
||||||
image: busybox
|
|
||||||
command: httpd -f -p 8123 -h /tmp/
|
|
||||||
|
|
||||||
x-podman:
|
|
||||||
name_separator_compat: true
|
|
@ -1,4 +0,0 @@
|
|||||||
services:
|
|
||||||
web:
|
|
||||||
image: busybox
|
|
||||||
command: httpd -f -p 8123 -h /tmp/
|
|
@ -1,60 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from parameterized import parameterized
|
|
||||||
|
|
||||||
from tests.integration.test_utils import RunSubprocessMixin
|
|
||||||
from tests.integration.test_utils import podman_compose_path
|
|
||||||
from tests.integration.test_utils import test_path
|
|
||||||
|
|
||||||
|
|
||||||
class TestComposeNameSeparatorCompat(unittest.TestCase, RunSubprocessMixin):
|
|
||||||
@parameterized.expand([
|
|
||||||
('default', {}, '_'),
|
|
||||||
('default', {'PODMAN_COMPOSE_NAME_SEPARATOR_COMPAT': '1'}, '-'),
|
|
||||||
('default', {'PODMAN_COMPOSE_DOCKER_COMPOSE_COMPAT': '1'}, '-'),
|
|
||||||
('compat', {}, '-'),
|
|
||||||
('compat', {'PODMAN_COMPOSE_NAME_SEPARATOR_COMPAT': '1'}, '-'),
|
|
||||||
('compat', {'PODMAN_COMPOSE_NAME_SEPARATOR_COMPAT': '0'}, '_'),
|
|
||||||
])
|
|
||||||
def test_container_name(self, file: str, env: dict[str, str], expected_sep: str) -> None:
|
|
||||||
compose_yaml_path = os.path.join(
|
|
||||||
test_path(), "name_separator_compat", f"docker-compose_{file}.yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.run_subprocess_assert_returncode(
|
|
||||||
[podman_compose_path(), "-f", compose_yaml_path, "up", "-d"],
|
|
||||||
env=env,
|
|
||||||
)
|
|
||||||
|
|
||||||
container_name_out, _ = self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path,
|
|
||||||
"ps",
|
|
||||||
"--format",
|
|
||||||
'{{.Names}}',
|
|
||||||
],
|
|
||||||
env=env,
|
|
||||||
)
|
|
||||||
container_name = container_name_out.decode('utf-8').strip()
|
|
||||||
|
|
||||||
expected_container_name = f'name_separator_compat{expected_sep}web{expected_sep}1'
|
|
||||||
|
|
||||||
self.assertEqual(container_name, expected_container_name)
|
|
||||||
finally:
|
|
||||||
self.run_subprocess_assert_returncode(
|
|
||||||
[
|
|
||||||
podman_compose_path(),
|
|
||||||
"-f",
|
|
||||||
compose_yaml_path,
|
|
||||||
"down",
|
|
||||||
"-t",
|
|
||||||
"0",
|
|
||||||
],
|
|
||||||
env=env,
|
|
||||||
)
|
|
@ -10,20 +10,20 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "nethost"), "docker-compose.yaml")
|
return os.path.join(os.path.join(test_path(), "nethost"), "docker-compose.yaml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeNethost(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeNethost(unittest.TestCase, RunSubprocessMixin):
|
||||||
# check if container listens for http requests and sends response back
|
# check if container listens for http requests and sends response back
|
||||||
# as network_mode: host allows to connect to container easily
|
# as network_mode: host allows to connect to container easily
|
||||||
def test_nethost(self) -> None:
|
def test_nethost(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[podman_compose_path(), "-f", compose_yaml_path(), "up", "-d"],
|
[podman_compose_path(), "-f", compose_yaml_path(), "up", "-d"],
|
||||||
)
|
)
|
||||||
|
|
||||||
container_id_out, _ = self.run_subprocess_assert_returncode(
|
container_id, _ = self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
podman_compose_path(),
|
podman_compose_path(),
|
||||||
"-f",
|
"-f",
|
||||||
@ -33,7 +33,7 @@ class TestComposeNethost(unittest.TestCase, RunSubprocessMixin):
|
|||||||
'{{.ID}}',
|
'{{.ID}}',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
container_id = container_id_out.decode('utf-8').split('\n')[0]
|
container_id = container_id.decode('utf-8').split('\n')[0]
|
||||||
output, _ = self.run_subprocess_assert_returncode(
|
output, _ = self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
"podman",
|
"podman",
|
||||||
|
@ -11,13 +11,13 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "nets_test1"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "nets_test1"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeNetsTest1(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeNetsTest1(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if port mapping works as expected
|
# test if port mapping works as expected
|
||||||
def test_nets_test1(self) -> None:
|
def test_nets_test1(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -11,13 +11,13 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "nets_test2"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "nets_test2"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeNetsTest2(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeNetsTest2(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if port mapping works as expected with networks top-level element
|
# test if port mapping works as expected with networks top-level element
|
||||||
def test_nets_test2(self) -> None:
|
def test_nets_test2(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -10,7 +10,7 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "nets_test3"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "nets_test3"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
@ -28,12 +28,8 @@ class TestComposeNetsTest3(unittest.TestCase, RunSubprocessMixin):
|
|||||||
("nets_test3_web1_1", "alias21", b"", 1),
|
("nets_test3_web1_1", "alias21", b"", 1),
|
||||||
])
|
])
|
||||||
def test_nets_test3(
|
def test_nets_test3(
|
||||||
self,
|
self, container_name, nework_alias_name, expected_text, expected_returncode
|
||||||
container_name: str,
|
):
|
||||||
nework_alias_name: str,
|
|
||||||
expected_text: bytes,
|
|
||||||
expected_returncode: int,
|
|
||||||
) -> None:
|
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -8,14 +8,14 @@ from tests.integration.test_utils import podman_compose_path
|
|||||||
from tests.integration.test_utils import test_path
|
from tests.integration.test_utils import test_path
|
||||||
|
|
||||||
|
|
||||||
def compose_yaml_path() -> str:
|
def compose_yaml_path():
|
||||||
return os.path.join(os.path.join(test_path(), "nets_test_ip"), "docker-compose.yml")
|
return os.path.join(os.path.join(test_path(), "nets_test_ip"), "docker-compose.yml")
|
||||||
|
|
||||||
|
|
||||||
class TestComposeNetsTestIp(unittest.TestCase, RunSubprocessMixin):
|
class TestComposeNetsTestIp(unittest.TestCase, RunSubprocessMixin):
|
||||||
# test if services retain custom ipv4_address and mac_address matching the subnet provided
|
# test if services retain custom ipv4_address and mac_address matching the subnet provided
|
||||||
# in networks top-level element
|
# in networks top-level element
|
||||||
def test_nets_test_ip(self) -> None:
|
def test_nets_test_ip(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode(
|
self.run_subprocess_assert_returncode(
|
||||||
[
|
[
|
||||||
|
@ -9,7 +9,6 @@ Tests the podman networking parameters
|
|||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from typing import Generator
|
|
||||||
|
|
||||||
from tests.integration.test_utils import RunSubprocessMixin
|
from tests.integration.test_utils import RunSubprocessMixin
|
||||||
from tests.integration.test_utils import podman_compose_path
|
from tests.integration.test_utils import podman_compose_path
|
||||||
@ -18,11 +17,11 @@ from tests.integration.test_utils import test_path
|
|||||||
|
|
||||||
class TestPodmanComposeNetwork(RunSubprocessMixin, unittest.TestCase):
|
class TestPodmanComposeNetwork(RunSubprocessMixin, unittest.TestCase):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def compose_file() -> str:
|
def compose_file():
|
||||||
"""Returns the path to the compose file used for this test module"""
|
"""Returns the path to the compose file used for this test module"""
|
||||||
return os.path.join(test_path(), "nets_test_ip", "docker-compose.yml")
|
return os.path.join(test_path(), "nets_test_ip", "docker-compose.yml")
|
||||||
|
|
||||||
def teardown(self) -> Generator[None, None, None]:
|
def teardown(self):
|
||||||
"""
|
"""
|
||||||
Ensures that the services within the "profile compose file" are removed between
|
Ensures that the services within the "profile compose file" are removed between
|
||||||
each test case.
|
each test case.
|
||||||
@ -41,7 +40,7 @@ class TestPodmanComposeNetwork(RunSubprocessMixin, unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.run_subprocess(down_cmd)
|
self.run_subprocess(down_cmd)
|
||||||
|
|
||||||
def test_networks(self) -> None:
|
def test_networks(self):
|
||||||
up_cmd = [
|
up_cmd = [
|
||||||
"coverage",
|
"coverage",
|
||||||
"run",
|
"run",
|
||||||
@ -116,7 +115,7 @@ class TestPodmanComposeNetwork(RunSubprocessMixin, unittest.TestCase):
|
|||||||
self.assertIn(f"ether {mac}", out.decode('utf-8'))
|
self.assertIn(f"ether {mac}", out.decode('utf-8'))
|
||||||
self.assertIn(f"inet {ip}/", out.decode('utf-8'))
|
self.assertIn(f"inet {ip}/", out.decode('utf-8'))
|
||||||
|
|
||||||
def test_down_with_network(self) -> None:
|
def test_down_with_network(self):
|
||||||
try:
|
try:
|
||||||
self.run_subprocess_assert_returncode([
|
self.run_subprocess_assert_returncode([
|
||||||
"coverage",
|
"coverage",
|
||||||
|
@ -10,10 +10,10 @@ from tests.integration.test_utils import test_path
|
|||||||
|
|
||||||
|
|
||||||
class TestPodmanComposeNetworkInterfaceName(RunSubprocessMixin, unittest.TestCase):
|
class TestPodmanComposeNetworkInterfaceName(RunSubprocessMixin, unittest.TestCase):
|
||||||
def compose_file(self) -> str:
|
def compose_file(self):
|
||||||
return os.path.join(test_path(), "network_interface_name", "docker-compose.yml")
|
return os.path.join(test_path(), "network_interface_name", "docker-compose.yml")
|
||||||
|
|
||||||
def up(self) -> None:
|
def up(self):
|
||||||
up_cmd = [
|
up_cmd = [
|
||||||
"coverage",
|
"coverage",
|
||||||
"run",
|
"run",
|
||||||
@ -26,7 +26,7 @@ class TestPodmanComposeNetworkInterfaceName(RunSubprocessMixin, unittest.TestCas
|
|||||||
]
|
]
|
||||||
self.run_subprocess_assert_returncode(up_cmd)
|
self.run_subprocess_assert_returncode(up_cmd)
|
||||||
|
|
||||||
def down(self) -> None:
|
def down(self):
|
||||||
down_cmd = [
|
down_cmd = [
|
||||||
"coverage",
|
"coverage",
|
||||||
"run",
|
"run",
|
||||||
@ -38,7 +38,7 @@ class TestPodmanComposeNetworkInterfaceName(RunSubprocessMixin, unittest.TestCas
|
|||||||
]
|
]
|
||||||
self.run_subprocess(down_cmd)
|
self.run_subprocess(down_cmd)
|
||||||
|
|
||||||
def test_interface_name(self) -> None:
|
def test_interface_name(self):
|
||||||
try:
|
try:
|
||||||
self.up()
|
self.up()
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user