mirror of
https://github.com/containers/podman-compose.git
synced 2025-01-07 06:29:42 +01:00
Merge pull request #883 from p12tic/lint-fixes
Enable ruff check and fix lint errors
This commit is contained in:
commit
a8db898ac6
2
.github/workflows/static-checks.yml
vendored
2
.github/workflows/static-checks.yml
vendored
@ -16,5 +16,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Analysing the code with ruff
|
- name: Analysing the code with ruff
|
||||||
run: |
|
run: |
|
||||||
|
set -e
|
||||||
pip install -r test-requirements.txt
|
pip install -r test-requirements.txt
|
||||||
ruff format --check
|
ruff format --check
|
||||||
|
ruff check
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
import os
|
|
||||||
import asyncio # noqa: F401
|
import asyncio # noqa: F401
|
||||||
|
import os
|
||||||
|
|
||||||
import aioredis
|
import aioredis
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
@ -7,21 +7,20 @@
|
|||||||
# https://docs.docker.com/compose/django/
|
# https://docs.docker.com/compose/django/
|
||||||
# https://docs.docker.com/compose/wordpress/
|
# https://docs.docker.com/compose/wordpress/
|
||||||
# TODO: podman pod logs --color -n -f pod_testlogs
|
# TODO: podman pod logs --color -n -f pod_testlogs
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import getpass
|
|
||||||
import argparse
|
import argparse
|
||||||
import itertools
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import hashlib
|
|
||||||
import random
|
|
||||||
import json
|
|
||||||
import glob
|
|
||||||
import asyncio.subprocess
|
import asyncio.subprocess
|
||||||
import signal
|
import getpass
|
||||||
|
import glob
|
||||||
|
import hashlib
|
||||||
|
import itertools
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
from asyncio import Task
|
from asyncio import Task
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -126,7 +125,8 @@ def str_to_seconds(txt):
|
|||||||
mins = int(mins) if mins else 0
|
mins = int(mins) if mins else 0
|
||||||
sec = float(sec) if sec else 0
|
sec = float(sec) if sec else 0
|
||||||
# "podman stop" takes only int
|
# "podman stop" takes only int
|
||||||
# Error: invalid argument "3.0" for "-t, --time" flag: strconv.ParseUint: parsing "3.0": invalid syntax
|
# Error: invalid argument "3.0" for "-t, --time" flag: strconv.ParseUint: parsing "3.0":
|
||||||
|
# invalid syntax
|
||||||
return int(mins * 60.0 + sec)
|
return int(mins * 60.0 + sec)
|
||||||
|
|
||||||
|
|
||||||
@ -389,7 +389,8 @@ async def assert_volume(compose, mount_dict):
|
|||||||
is_ext = vol.get("external", None)
|
is_ext = vol.get("external", None)
|
||||||
log(f"podman volume inspect {vol_name} || podman volume create {vol_name}")
|
log(f"podman volume inspect {vol_name} || podman volume create {vol_name}")
|
||||||
# TODO: might move to using "volume list"
|
# TODO: might move to using "volume list"
|
||||||
# podman volume list --format '{{.Name}}\t{{.MountPoint}}' -f 'label=io.podman.compose.project=HERE'
|
# podman volume list --format '{{.Name}}\t{{.MountPoint}}' \
|
||||||
|
# -f 'label=io.podman.compose.project=HERE'
|
||||||
try:
|
try:
|
||||||
_ = (await compose.podman.output([], "volume", ["inspect", vol_name])).decode("utf-8")
|
_ = (await compose.podman.output([], "volume", ["inspect", vol_name])).decode("utf-8")
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
@ -584,7 +585,10 @@ def get_secret_args(compose, cnt, secret):
|
|||||||
# having a custom name for the external secret
|
# having a custom name for the external secret
|
||||||
# has the same problem as well
|
# has the same problem as well
|
||||||
ext_name = declared_secret.get("name", None)
|
ext_name = declared_secret.get("name", None)
|
||||||
err_str = 'ERROR: Custom name/target reference "{}" for mounted external secret "{}" is not supported'
|
err_str = (
|
||||||
|
'ERROR: Custom name/target reference "{}" '
|
||||||
|
'for mounted external secret "{}" is not supported'
|
||||||
|
)
|
||||||
if ext_name and ext_name != secret_name:
|
if ext_name and ext_name != secret_name:
|
||||||
raise ValueError(err_str.format(secret_name, ext_name))
|
raise ValueError(err_str.format(secret_name, ext_name))
|
||||||
if target and target != secret_name:
|
if target and target != secret_name:
|
||||||
@ -1103,7 +1107,7 @@ def flat_deps(services, with_extends=False):
|
|||||||
for c in links_ls:
|
for c in links_ls:
|
||||||
if ":" in c:
|
if ":" in c:
|
||||||
dep_name, dep_alias = c.split(":")
|
dep_name, dep_alias = c.split(":")
|
||||||
if not "_aliases" in services[dep_name]:
|
if "_aliases" not in services[dep_name]:
|
||||||
services[dep_name]["_aliases"] = set()
|
services[dep_name]["_aliases"] = set()
|
||||||
services[dep_name]["_aliases"].add(dep_alias)
|
services[dep_name]["_aliases"].add(dep_alias)
|
||||||
for name, srv in services.items():
|
for name, srv in services.items():
|
||||||
@ -1178,9 +1182,9 @@ class Podman:
|
|||||||
|
|
||||||
async def format_out(stdout):
|
async def format_out(stdout):
|
||||||
while True:
|
while True:
|
||||||
l = await stdout.readline()
|
line = await stdout.readline()
|
||||||
if l:
|
if line:
|
||||||
print(log_formatter, l.decode('utf-8'), end='')
|
print(log_formatter, line.decode('utf-8'), end='')
|
||||||
if stdout.at_eof():
|
if stdout.at_eof():
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -1203,14 +1207,14 @@ class Podman:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
exit_code = await p.wait()
|
exit_code = await p.wait()
|
||||||
except asyncio.CancelledError as e:
|
except asyncio.CancelledError:
|
||||||
log(f"Sending termination signal")
|
log("Sending termination signal")
|
||||||
p.terminate()
|
p.terminate()
|
||||||
try:
|
try:
|
||||||
async with asyncio.timeout(10):
|
async with asyncio.timeout(10):
|
||||||
exit_code = await p.wait()
|
exit_code = await p.wait()
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
log(f"container did not shut down after 10 seconds, killing")
|
log("container did not shut down after 10 seconds, killing")
|
||||||
p.kill()
|
p.kill()
|
||||||
exit_code = await p.wait()
|
exit_code = await p.wait()
|
||||||
|
|
||||||
@ -1530,7 +1534,8 @@ class PodmanCompose:
|
|||||||
files = args.file
|
files = args.file
|
||||||
if not files:
|
if not files:
|
||||||
log(
|
log(
|
||||||
"no compose.yaml, docker-compose.yml or container-compose.yml file found, pass files with -f"
|
"no compose.yaml, docker-compose.yml or container-compose.yml file found, "
|
||||||
|
"pass files with -f"
|
||||||
)
|
)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
ex = map(os.path.exists, files)
|
ex = map(os.path.exists, files)
|
||||||
@ -1620,7 +1625,8 @@ class PodmanCompose:
|
|||||||
if not project_name:
|
if not project_name:
|
||||||
project_name = compose.get("name", None)
|
project_name = compose.get("name", None)
|
||||||
if project_name is None:
|
if project_name is None:
|
||||||
# More strict then actually needed for simplicity: podman requires [a-zA-Z0-9][a-zA-Z0-9_.-]*
|
# More strict then actually needed for simplicity:
|
||||||
|
# podman requires [a-zA-Z0-9][a-zA-Z0-9_.-]*
|
||||||
project_name = (
|
project_name = (
|
||||||
self.environ.get("COMPOSE_PROJECT_NAME", None) or dir_basename.lower()
|
self.environ.get("COMPOSE_PROJECT_NAME", None) or dir_basename.lower()
|
||||||
)
|
)
|
||||||
@ -1743,11 +1749,11 @@ class PodmanCompose:
|
|||||||
|
|
||||||
def _resolve_profiles(self, defined_services, requested_profiles=None):
|
def _resolve_profiles(self, defined_services, requested_profiles=None):
|
||||||
"""
|
"""
|
||||||
Returns a service dictionary (key = service name, value = service config) compatible with the requested_profiles
|
Returns a service dictionary (key = service name, value = service config) compatible with
|
||||||
list.
|
the requested_profiles list.
|
||||||
|
|
||||||
The returned service dictionary contains all services which do not include/reference a profile in addition to
|
The returned service dictionary contains all services which do not include/reference a
|
||||||
services that match the requested_profiles.
|
profile in addition to services that match the requested_profiles.
|
||||||
|
|
||||||
:param defined_services: The service dictionary
|
:param defined_services: The service dictionary
|
||||||
:param requested_profiles: The profiles requested using the --profile arg.
|
:param requested_profiles: The profiles requested using the --profile arg.
|
||||||
@ -2258,8 +2264,9 @@ async def compose_up(compose: PodmanCompose, args):
|
|||||||
done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
||||||
if args.abort_on_container_exit:
|
if args.abort_on_container_exit:
|
||||||
if not exiting:
|
if not exiting:
|
||||||
# If 2 containers exit at the exact same time, the cancellation of the other ones cause the status
|
# If 2 containers exit at the exact same time, the cancellation of the other ones
|
||||||
# to overwrite. Sleeping for 1 seems to fix this and make it match docker-compose
|
# cause the status to overwrite. Sleeping for 1 seems to fix this and make it match
|
||||||
|
# docker-compose
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
[_.cancel() for _ in tasks if not _.cancelling() and not _.cancelled()]
|
[_.cancel() for _ in tasks if not _.cancelling() and not _.cancelled()]
|
||||||
t: Task
|
t: Task
|
||||||
@ -2729,7 +2736,8 @@ def compose_up_parse(parser):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--no-recreate",
|
"--no-recreate",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="If containers already exist, don't recreate them. Incompatible with --force-recreate and -V.",
|
help="If containers already exist, don't recreate them. Incompatible with --force-recreate "
|
||||||
|
"and -V.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--no-build",
|
"--no-build",
|
||||||
@ -2754,8 +2762,8 @@ def compose_up_parse(parser):
|
|||||||
"--timeout",
|
"--timeout",
|
||||||
type=int,
|
type=int,
|
||||||
default=None,
|
default=None,
|
||||||
help="Use this timeout in seconds for container shutdown when attached or when containers are already running. \
|
help="Use this timeout in seconds for container shutdown when attached or when containers "
|
||||||
(default: 10)",
|
"are already running. (default: 10)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-V",
|
"-V",
|
||||||
@ -2772,14 +2780,16 @@ def compose_up_parse(parser):
|
|||||||
"--scale",
|
"--scale",
|
||||||
metavar="SERVICE=NUM",
|
metavar="SERVICE=NUM",
|
||||||
action="append",
|
action="append",
|
||||||
help="Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.",
|
help="Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if "
|
||||||
|
"present.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--exit-code-from",
|
"--exit-code-from",
|
||||||
metavar="SERVICE",
|
metavar="SERVICE",
|
||||||
type=str,
|
type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help="Return the exit code of the selected service container. Implies --abort-on-container-exit.",
|
help="Return the exit code of the selected service container. "
|
||||||
|
"Implies --abort-on-container-exit.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -3021,7 +3031,8 @@ def compose_build_up_parse(parser):
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--pull-always",
|
"--pull-always",
|
||||||
help="attempt to pull a newer version of the image, Raise an error even if the image is present locally.",
|
help="attempt to pull a newer version of the image, Raise an error even if the image is "
|
||||||
|
"present locally.",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
import copy
|
|
||||||
import os
|
|
||||||
import argparse
|
import argparse
|
||||||
import yaml
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
from podman_compose import normalize_service, PodmanCompose
|
|
||||||
|
from podman_compose import PodmanCompose
|
||||||
|
from podman_compose import normalize_service
|
||||||
|
|
||||||
|
|
||||||
class TestMergeBuild(unittest.TestCase):
|
class TestMergeBuild(unittest.TestCase):
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import argparse
|
|
||||||
import yaml
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
from podman_compose import normalize_service, PodmanCompose
|
|
||||||
|
from podman_compose import PodmanCompose
|
||||||
|
from podman_compose import normalize_service
|
||||||
|
|
||||||
test_keys = ["command", "entrypoint"]
|
test_keys = ["command", "entrypoint"]
|
||||||
|
|
||||||
|
@ -2,16 +2,15 @@
|
|||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import copy
|
|
||||||
import os
|
import os
|
||||||
import yaml
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
from podman_compose import (
|
|
||||||
normalize_final,
|
from podman_compose import PodmanCompose
|
||||||
normalize_service_final,
|
from podman_compose import normalize_final
|
||||||
PodmanCompose,
|
from podman_compose import normalize_service_final
|
||||||
)
|
|
||||||
|
|
||||||
cwd = os.path.abspath(".")
|
cwd = os.path.abspath(".")
|
||||||
|
|
||||||
|
1
setup.py
1
setup.py
@ -1,6 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from .test_utils import RunSubprocessMixin
|
from .test_utils import RunSubprocessMixin
|
||||||
|
|
||||||
|
|
||||||
@ -77,8 +78,8 @@ class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin):
|
|||||||
def test_extends_w_empty_service(self):
|
def test_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 configurations.)
|
includes an empty service. (e.g. if the file is used as placeholder for more complex
|
||||||
:return:
|
configurations.)
|
||||||
"""
|
"""
|
||||||
main_path = Path(__file__).parent.parent
|
main_path = Path(__file__).parent.parent
|
||||||
|
|
||||||
|
@ -8,11 +8,13 @@ Tests the podman-compose config command which is used to return defined compose
|
|||||||
|
|
||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
import os
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from parameterized import parameterized
|
||||||
|
|
||||||
from .test_podman_compose import podman_compose_path
|
from .test_podman_compose import podman_compose_path
|
||||||
from .test_podman_compose import test_path
|
from .test_podman_compose import test_path
|
||||||
from .test_utils import RunSubprocessMixin
|
from .test_utils import RunSubprocessMixin
|
||||||
import unittest
|
|
||||||
from parameterized import parameterized
|
|
||||||
|
|
||||||
|
|
||||||
def profile_compose_file():
|
def profile_compose_file():
|
||||||
@ -61,8 +63,8 @@ class TestComposeConfig(unittest.TestCase, RunSubprocessMixin):
|
|||||||
"""
|
"""
|
||||||
Tests podman-compose
|
Tests podman-compose
|
||||||
:param profiles: The enabled profiles for the parameterized test.
|
:param profiles: The enabled profiles for the parameterized test.
|
||||||
:param expected_services: Dictionary used to model the expected "enabled" services in the profile.
|
:param expected_services: Dictionary used to model the expected "enabled" services in the
|
||||||
Key = service name, Value = True if the service is enabled, otherwise False.
|
profile. Key = service name, Value = True if the service is enabled, otherwise False.
|
||||||
"""
|
"""
|
||||||
config_cmd = ["coverage", "run", podman_compose_path(), "-f", profile_compose_file()]
|
config_cmd = ["coverage", "run", podman_compose_path(), "-f", profile_compose_file()]
|
||||||
config_cmd.extend(profiles)
|
config_cmd.extend(profiles)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
import subprocess
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from .test_utils import RunSubprocessMixin
|
from .test_utils import RunSubprocessMixin
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ Tests the podman compose up and down commands used to create and remove services
|
|||||||
|
|
||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from .test_podman_compose import podman_compose_path
|
from .test_podman_compose import podman_compose_path
|
||||||
@ -51,8 +50,8 @@ class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin):
|
|||||||
out, _ = self.run_subprocess_assert_returncode(run_cmd)
|
out, _ = self.run_subprocess_assert_returncode(run_cmd)
|
||||||
self.assertIn(b'127.0.0.1\tlocalhost', out)
|
self.assertIn(b'127.0.0.1\tlocalhost', out)
|
||||||
|
|
||||||
# Run it again to make sure we can run it twice. I saw an issue where a second run, with the container left up,
|
# Run it again to make sure we can run it twice. I saw an issue where a second run, with
|
||||||
# would fail
|
# the container left up, would fail
|
||||||
run_cmd = [
|
run_cmd = [
|
||||||
"coverage",
|
"coverage",
|
||||||
"run",
|
"run",
|
||||||
|
@ -8,11 +8,13 @@ Tests the podman compose up and down commands used to create and remove services
|
|||||||
|
|
||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
import os
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from parameterized import parameterized
|
||||||
|
|
||||||
from .test_podman_compose import podman_compose_path
|
from .test_podman_compose import podman_compose_path
|
||||||
from .test_podman_compose import test_path
|
from .test_podman_compose import test_path
|
||||||
from .test_utils import RunSubprocessMixin
|
from .test_utils import RunSubprocessMixin
|
||||||
from parameterized import parameterized
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
def profile_compose_file():
|
def profile_compose_file():
|
||||||
@ -23,7 +25,8 @@ def profile_compose_file():
|
|||||||
class TestUpDown(unittest.TestCase, RunSubprocessMixin):
|
class TestUpDown(unittest.TestCase, RunSubprocessMixin):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""
|
"""
|
||||||
Ensures that the services within the "profile compose file" are removed between each test case.
|
Ensures that the services within the "profile compose file" are removed between each test
|
||||||
|
case.
|
||||||
"""
|
"""
|
||||||
# run the test case
|
# run the test case
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user