iker-python-common 1.0.62__tar.gz → 1.0.63__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/PKG-INFO +1 -2
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/pyproject.toml +0 -2
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/PKG-INFO +1 -2
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/SOURCES.txt +0 -3
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/requires.txt +0 -1
- iker_python_common-1.0.62/src/iker/common/utils/dockerutils.py +0 -236
- iker_python_common-1.0.62/test/iker_tests/common/utils/dockerutils_test.py +0 -544
- iker_python_common-1.0.62/test/iker_tests/docker_fixtures.py +0 -79
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/.editorconfig +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/.github/workflows/pr.yml +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/.github/workflows/push.yml +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/.gitignore +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/MANIFEST.in +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/README.md +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/VERSION +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/config/config.cfg +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/csv/data.csv +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/csv/data.tsv +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.baz/file.bar.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.baz/file.foo.bar +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.baz/file.foo.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.bar +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.baz +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.foo +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/setup.cfg +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/setup.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/__init__.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/__init__.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/argutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/config.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/csv.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/dbutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/dtutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/funcutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/jsonutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/logger.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/numutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/randutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/retry.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/sequtils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/shutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/span.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/strutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/testutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker/common/utils/typeutils.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/dependency_links.txt +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/not-zip-safe +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/top_level.txt +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/__init__.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/argutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/config_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/csv_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/dbutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/dtutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/funcutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/jsonutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/logger_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/numutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/randutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/retry_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/sequtils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/shutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/span_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/strutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/testutils_test.py +0 -0
- {iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/typeutils_test.py +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iker-python-common
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.63
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3.12
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.13
|
|
7
7
|
Classifier: Programming Language :: Python :: 3.14
|
|
8
8
|
Requires-Python: <3.15,>=3.12
|
|
9
9
|
Requires-Dist: asyncpg>=0.30
|
|
10
|
-
Requires-Dist: docker>=7.1
|
|
11
10
|
Requires-Dist: numpy>=2.3
|
|
12
11
|
Requires-Dist: psycopg>=3.2
|
|
13
12
|
Requires-Dist: pymysql>=1.1
|
|
@@ -9,7 +9,6 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
[dependency-groups]
|
|
10
10
|
dev = [
|
|
11
11
|
"asyncpg>=0.30",
|
|
12
|
-
"docker>=7.1",
|
|
13
12
|
"numpy>=2.3",
|
|
14
13
|
"psycopg>=3.2",
|
|
15
14
|
"pymysql>=1.1",
|
|
@@ -37,7 +36,6 @@ classifiers = [
|
|
|
37
36
|
]
|
|
38
37
|
dependencies = [
|
|
39
38
|
"asyncpg>=0.30",
|
|
40
|
-
"docker>=7.1",
|
|
41
39
|
"numpy>=2.3",
|
|
42
40
|
"psycopg>=3.2",
|
|
43
41
|
"pymysql>=1.1",
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/PKG-INFO
RENAMED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iker-python-common
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.63
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3.12
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.13
|
|
7
7
|
Classifier: Programming Language :: Python :: 3.14
|
|
8
8
|
Requires-Python: <3.15,>=3.12
|
|
9
9
|
Requires-Dist: asyncpg>=0.30
|
|
10
|
-
Requires-Dist: docker>=7.1
|
|
11
10
|
Requires-Dist: numpy>=2.3
|
|
12
11
|
Requires-Dist: psycopg>=3.2
|
|
13
12
|
Requires-Dist: pymysql>=1.1
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/SOURCES.txt
RENAMED
|
@@ -26,7 +26,6 @@ src/iker/common/utils/argutils.py
|
|
|
26
26
|
src/iker/common/utils/config.py
|
|
27
27
|
src/iker/common/utils/csv.py
|
|
28
28
|
src/iker/common/utils/dbutils.py
|
|
29
|
-
src/iker/common/utils/dockerutils.py
|
|
30
29
|
src/iker/common/utils/dtutils.py
|
|
31
30
|
src/iker/common/utils/funcutils.py
|
|
32
31
|
src/iker/common/utils/jsonutils.py
|
|
@@ -48,12 +47,10 @@ src/iker_python_common.egg-info/requires.txt
|
|
|
48
47
|
src/iker_python_common.egg-info/top_level.txt
|
|
49
48
|
test/iker_test.py
|
|
50
49
|
test/iker_tests/__init__.py
|
|
51
|
-
test/iker_tests/docker_fixtures.py
|
|
52
50
|
test/iker_tests/common/utils/argutils_test.py
|
|
53
51
|
test/iker_tests/common/utils/config_test.py
|
|
54
52
|
test/iker_tests/common/utils/csv_test.py
|
|
55
53
|
test/iker_tests/common/utils/dbutils_test.py
|
|
56
|
-
test/iker_tests/common/utils/dockerutils_test.py
|
|
57
54
|
test/iker_tests/common/utils/dtutils_test.py
|
|
58
55
|
test/iker_tests/common/utils/funcutils_test.py
|
|
59
56
|
test/iker_tests/common/utils/jsonutils_test.py
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import contextlib
|
|
2
|
-
import dataclasses
|
|
3
|
-
import re
|
|
4
|
-
from collections.abc import Generator, Iterator
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
import docker
|
|
8
|
-
import docker.errors
|
|
9
|
-
import docker.models.containers
|
|
10
|
-
import docker.models.images
|
|
11
|
-
import requests.exceptions
|
|
12
|
-
|
|
13
|
-
from iker.common.utils import logger
|
|
14
|
-
from iker.common.utils.strutils import parse_int_or, trim_to_empty
|
|
15
|
-
|
|
16
|
-
__all__ = [
|
|
17
|
-
"ImageName",
|
|
18
|
-
"docker_create_client",
|
|
19
|
-
"docker_build_image",
|
|
20
|
-
"docker_get_image",
|
|
21
|
-
"docker_pull_image",
|
|
22
|
-
"docker_fetch_image",
|
|
23
|
-
"docker_run_detached",
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@dataclasses.dataclass
|
|
28
|
-
class ImageName(object):
|
|
29
|
-
registry_host: str | None
|
|
30
|
-
registry_port: int | None
|
|
31
|
-
components: list[str]
|
|
32
|
-
tag: str | None
|
|
33
|
-
|
|
34
|
-
@property
|
|
35
|
-
def registry(self) -> str:
|
|
36
|
-
if self.registry_host is None and self.registry_port is None:
|
|
37
|
-
return ""
|
|
38
|
-
if self.registry_port is None:
|
|
39
|
-
return self.registry_host
|
|
40
|
-
return f"{self.registry_host}:{self.registry_port}"
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def repository(self) -> str:
|
|
44
|
-
return "/".join(self.components)
|
|
45
|
-
|
|
46
|
-
@staticmethod
|
|
47
|
-
def parse(s: str):
|
|
48
|
-
|
|
49
|
-
# Registry absent version
|
|
50
|
-
matcher = re.compile(
|
|
51
|
-
r"^(?P<components>[a-z0-9]+((__?|-+)[a-z0-9]+)*(/[a-z0-9]+((__?|-+)[a-z0-9]+)*)*)(:(?P<tag>\w[\w.-]{0,127}))?$")
|
|
52
|
-
match = matcher.match(s)
|
|
53
|
-
if match:
|
|
54
|
-
return ImageName(registry_host=None,
|
|
55
|
-
registry_port=None,
|
|
56
|
-
components=trim_to_empty(match.group("components")).split("/"),
|
|
57
|
-
tag=match.group("tag"))
|
|
58
|
-
|
|
59
|
-
# Registry present version
|
|
60
|
-
matcher = re.compile(
|
|
61
|
-
r"^((?P<host>[a-zA-Z0-9.-]+)(:(?P<port>\d+))?/)?(?P<components>[a-z0-9]+((__?|-+)[a-z0-9]+)*(/[a-z0-9]+((__?|-+)[a-z0-9]+)*)*)(:(?P<tag>\w[\w.-]{0,127}))?$")
|
|
62
|
-
match = matcher.match(s)
|
|
63
|
-
if match:
|
|
64
|
-
return ImageName(registry_host=match.group("host"),
|
|
65
|
-
registry_port=parse_int_or(match.group("port"), None),
|
|
66
|
-
components=trim_to_empty(match.group("components")).split("/"),
|
|
67
|
-
tag=match.group("tag"))
|
|
68
|
-
|
|
69
|
-
return None
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def docker_create_client(
|
|
73
|
-
registry: str,
|
|
74
|
-
username: str,
|
|
75
|
-
password: str,
|
|
76
|
-
) -> contextlib.AbstractContextManager[docker.DockerClient]:
|
|
77
|
-
try:
|
|
78
|
-
client = docker.DockerClient()
|
|
79
|
-
client.login(registry=registry, username=username, password=password, reauth=True)
|
|
80
|
-
return contextlib.closing(client)
|
|
81
|
-
except docker.errors.APIError:
|
|
82
|
-
logger.exception("Failed to login Docker server <%s>", registry)
|
|
83
|
-
raise
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def docker_build_image(
|
|
87
|
-
client: docker.DockerClient,
|
|
88
|
-
tag: str,
|
|
89
|
-
path: str,
|
|
90
|
-
dockerfile: str,
|
|
91
|
-
build_args: dict[str, str],
|
|
92
|
-
) -> tuple[docker.models.images.Image, Iterator[dict[str, str]]]:
|
|
93
|
-
try:
|
|
94
|
-
return client.images.build(tag=tag,
|
|
95
|
-
path=path,
|
|
96
|
-
dockerfile=dockerfile,
|
|
97
|
-
buildargs=build_args,
|
|
98
|
-
rm=True,
|
|
99
|
-
forcerm=True,
|
|
100
|
-
nocache=True)
|
|
101
|
-
|
|
102
|
-
except docker.errors.BuildError:
|
|
103
|
-
logger.exception("Failed to build image <%s>", tag)
|
|
104
|
-
raise
|
|
105
|
-
except docker.errors.APIError:
|
|
106
|
-
logger.exception("Docker server returns an error while building image <%s>", tag)
|
|
107
|
-
raise
|
|
108
|
-
except Exception:
|
|
109
|
-
logger.exception("Unexpected error occurred while building image <%s>", tag)
|
|
110
|
-
raise
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def docker_get_image(
|
|
114
|
-
client: docker.DockerClient,
|
|
115
|
-
image: str,
|
|
116
|
-
) -> docker.models.images.Image:
|
|
117
|
-
try:
|
|
118
|
-
return client.images.get(image)
|
|
119
|
-
except docker.errors.ImageNotFound:
|
|
120
|
-
logger.exception("Image <%s> is not found from local repository", image)
|
|
121
|
-
raise
|
|
122
|
-
except docker.errors.APIError:
|
|
123
|
-
logger.exception("Docker server returns an error while getting image <%s>", image)
|
|
124
|
-
raise
|
|
125
|
-
except Exception:
|
|
126
|
-
logger.exception("Unexpected error occurred while getting image <%s>", image)
|
|
127
|
-
raise
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def docker_pull_image(
|
|
131
|
-
client: docker.DockerClient,
|
|
132
|
-
image: str,
|
|
133
|
-
fallback_local: bool = False,
|
|
134
|
-
) -> docker.models.images.Image:
|
|
135
|
-
try:
|
|
136
|
-
return client.images.pull(image)
|
|
137
|
-
except docker.errors.ImageNotFound:
|
|
138
|
-
if not fallback_local:
|
|
139
|
-
logger.exception("Image <%s> is not found from remote repository", image)
|
|
140
|
-
raise
|
|
141
|
-
logger.warning("Image <%s> is not found from remote repository, try local repository instead", image)
|
|
142
|
-
except docker.errors.APIError:
|
|
143
|
-
if not fallback_local:
|
|
144
|
-
logger.exception("Docker server returns an error while pulling image <%s>", image)
|
|
145
|
-
raise
|
|
146
|
-
logger.warning("Docker server returns an error while pulling image <%s>, try local repository instead", image)
|
|
147
|
-
except Exception:
|
|
148
|
-
logger.exception("Unexpected error occurred while pulling image <%s>", image)
|
|
149
|
-
raise
|
|
150
|
-
|
|
151
|
-
return docker_get_image(client, image)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def docker_fetch_image(
|
|
155
|
-
client: docker.DockerClient,
|
|
156
|
-
image: str,
|
|
157
|
-
force_pull: bool = False,
|
|
158
|
-
) -> docker.models.images.Image:
|
|
159
|
-
if force_pull:
|
|
160
|
-
return docker_pull_image(client, image, fallback_local=True)
|
|
161
|
-
else:
|
|
162
|
-
try:
|
|
163
|
-
return docker_get_image(client, image)
|
|
164
|
-
except Exception:
|
|
165
|
-
return docker_pull_image(client, image, fallback_local=False)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def docker_run_detached(
|
|
169
|
-
client: docker.DockerClient,
|
|
170
|
-
image: str,
|
|
171
|
-
name: str,
|
|
172
|
-
command: str | list[str],
|
|
173
|
-
volumes: dict[str, dict[str, str]],
|
|
174
|
-
environment: dict[str, str],
|
|
175
|
-
extra_hosts: dict[str, str],
|
|
176
|
-
timeout: int,
|
|
177
|
-
**kwargs,
|
|
178
|
-
) -> tuple[dict[str, Any], Any]:
|
|
179
|
-
@contextlib.contextmanager
|
|
180
|
-
def managed_docker_run(
|
|
181
|
-
client: docker.DockerClient,
|
|
182
|
-
**kwargs,
|
|
183
|
-
) -> Generator[docker.models.containers.Container, None, None]:
|
|
184
|
-
container_model = None
|
|
185
|
-
try:
|
|
186
|
-
container_model = client.containers.run(**kwargs)
|
|
187
|
-
yield container_model
|
|
188
|
-
except docker.errors.DockerException:
|
|
189
|
-
raise
|
|
190
|
-
finally:
|
|
191
|
-
if container_model is not None:
|
|
192
|
-
try:
|
|
193
|
-
if container_model.status != "exited":
|
|
194
|
-
try:
|
|
195
|
-
container_model.stop()
|
|
196
|
-
except docker.errors.DockerException:
|
|
197
|
-
pass
|
|
198
|
-
container_model.wait()
|
|
199
|
-
try:
|
|
200
|
-
container_model.remove()
|
|
201
|
-
except docker.errors.DockerException:
|
|
202
|
-
pass
|
|
203
|
-
except Exception:
|
|
204
|
-
raise
|
|
205
|
-
|
|
206
|
-
try:
|
|
207
|
-
run_args = kwargs.copy()
|
|
208
|
-
run_args.update(dict(image=image,
|
|
209
|
-
name=name,
|
|
210
|
-
command=command,
|
|
211
|
-
volumes=volumes,
|
|
212
|
-
environment=environment,
|
|
213
|
-
extra_hosts=extra_hosts,
|
|
214
|
-
detach=True))
|
|
215
|
-
|
|
216
|
-
with managed_docker_run(client, **run_args) as container_model:
|
|
217
|
-
result = container_model.wait(timeout=timeout)
|
|
218
|
-
logs = container_model.logs()
|
|
219
|
-
|
|
220
|
-
return result, logs
|
|
221
|
-
|
|
222
|
-
except requests.exceptions.ReadTimeout:
|
|
223
|
-
logger.exception("Running container <%s> of image <%s> exceed the timeout", name, image)
|
|
224
|
-
raise
|
|
225
|
-
except docker.errors.ImageNotFound:
|
|
226
|
-
logger.exception("Image <%s> is not found", image)
|
|
227
|
-
raise
|
|
228
|
-
except docker.errors.ContainerError:
|
|
229
|
-
logger.exception("Failed to run container <%s> of image <%s>", name, image)
|
|
230
|
-
raise
|
|
231
|
-
except docker.errors.APIError:
|
|
232
|
-
logger.exception("Docker server returns an error while running container <%s> of image <%s>", name, image)
|
|
233
|
-
raise
|
|
234
|
-
except Exception:
|
|
235
|
-
logger.exception("Unexpected error occurred while running container <%s> of image <%s>", image)
|
|
236
|
-
raise
|
|
@@ -1,544 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
import unittest.mock
|
|
3
|
-
|
|
4
|
-
import ddt
|
|
5
|
-
import docker.errors
|
|
6
|
-
import docker.models.containers
|
|
7
|
-
import docker.models.images
|
|
8
|
-
import requests.exceptions
|
|
9
|
-
|
|
10
|
-
from iker.common.utils.dockerutils import *
|
|
11
|
-
from iker.common.utils.testutils import return_callee
|
|
12
|
-
from iker_tests.docker_fixtures import MockedDockerContainer, MockedDockerImage
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@ddt.ddt
|
|
16
|
-
class DockerUtilsTest(unittest.TestCase):
|
|
17
|
-
data_image_name = [
|
|
18
|
-
(
|
|
19
|
-
"ubuntu",
|
|
20
|
-
ImageName(None, None, ["ubuntu"], None),
|
|
21
|
-
"",
|
|
22
|
-
"ubuntu",
|
|
23
|
-
),
|
|
24
|
-
(
|
|
25
|
-
"ubuntu:latest",
|
|
26
|
-
ImageName(None, None, ["ubuntu"], "latest"),
|
|
27
|
-
"",
|
|
28
|
-
"ubuntu",
|
|
29
|
-
),
|
|
30
|
-
(
|
|
31
|
-
"ubuntu:22.04",
|
|
32
|
-
ImageName(None, None, ["ubuntu"], "22.04"),
|
|
33
|
-
"",
|
|
34
|
-
"ubuntu",
|
|
35
|
-
),
|
|
36
|
-
(
|
|
37
|
-
"canonical/ubuntu",
|
|
38
|
-
ImageName(None, None, ["canonical", "ubuntu"], None),
|
|
39
|
-
"",
|
|
40
|
-
"canonical/ubuntu",
|
|
41
|
-
),
|
|
42
|
-
(
|
|
43
|
-
"canonical/ubuntu:latest",
|
|
44
|
-
ImageName(None, None, ["canonical", "ubuntu"], "latest"),
|
|
45
|
-
"",
|
|
46
|
-
"canonical/ubuntu",
|
|
47
|
-
),
|
|
48
|
-
(
|
|
49
|
-
"canonical/ubuntu:22.04",
|
|
50
|
-
ImageName(None, None, ["canonical", "ubuntu"], "22.04"),
|
|
51
|
-
"",
|
|
52
|
-
"canonical/ubuntu",
|
|
53
|
-
),
|
|
54
|
-
(
|
|
55
|
-
"hub.docker.com/canonical/ubuntu",
|
|
56
|
-
ImageName("hub.docker.com", None, ["canonical", "ubuntu"], None),
|
|
57
|
-
"hub.docker.com",
|
|
58
|
-
"canonical/ubuntu",
|
|
59
|
-
),
|
|
60
|
-
(
|
|
61
|
-
"hub.docker.com/canonical/ubuntu:latest",
|
|
62
|
-
ImageName("hub.docker.com", None, ["canonical", "ubuntu"], "latest"),
|
|
63
|
-
"hub.docker.com",
|
|
64
|
-
"canonical/ubuntu",
|
|
65
|
-
),
|
|
66
|
-
(
|
|
67
|
-
"hub.docker.com/canonical/ubuntu:22.04",
|
|
68
|
-
ImageName("hub.docker.com", None, ["canonical", "ubuntu"], "22.04"),
|
|
69
|
-
"hub.docker.com",
|
|
70
|
-
"canonical/ubuntu",
|
|
71
|
-
),
|
|
72
|
-
(
|
|
73
|
-
"hub.docker.com:8080/canonical/ubuntu",
|
|
74
|
-
ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], None),
|
|
75
|
-
"hub.docker.com:8080",
|
|
76
|
-
"canonical/ubuntu",
|
|
77
|
-
),
|
|
78
|
-
(
|
|
79
|
-
"hub.docker.com:8080/canonical/ubuntu:latest",
|
|
80
|
-
ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], "latest"),
|
|
81
|
-
"hub.docker.com:8080",
|
|
82
|
-
"canonical/ubuntu",
|
|
83
|
-
),
|
|
84
|
-
(
|
|
85
|
-
"hub.docker.com:8080/canonical/ubuntu:22.04",
|
|
86
|
-
ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], "22.04"),
|
|
87
|
-
"hub.docker.com:8080",
|
|
88
|
-
"canonical/ubuntu",
|
|
89
|
-
),
|
|
90
|
-
(
|
|
91
|
-
"hub.docker.com:8080/ubuntu",
|
|
92
|
-
ImageName("hub.docker.com", 8080, ["ubuntu"], None),
|
|
93
|
-
"hub.docker.com:8080",
|
|
94
|
-
"ubuntu",
|
|
95
|
-
),
|
|
96
|
-
(
|
|
97
|
-
"hub.docker.com:8080/ubuntu:latest",
|
|
98
|
-
ImageName("hub.docker.com", 8080, ["ubuntu"], "latest"),
|
|
99
|
-
"hub.docker.com:8080",
|
|
100
|
-
"ubuntu",
|
|
101
|
-
),
|
|
102
|
-
(
|
|
103
|
-
"hub.docker.com:8080/ubuntu:22.04",
|
|
104
|
-
ImageName("hub.docker.com", 8080, ["ubuntu"], "22.04"),
|
|
105
|
-
"hub.docker.com:8080",
|
|
106
|
-
"ubuntu",
|
|
107
|
-
),
|
|
108
|
-
(
|
|
109
|
-
"hub.docker.com:8080/docker-hub/canonical/ubuntu",
|
|
110
|
-
ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], None),
|
|
111
|
-
"hub.docker.com:8080",
|
|
112
|
-
"docker-hub/canonical/ubuntu",
|
|
113
|
-
),
|
|
114
|
-
(
|
|
115
|
-
"hub.docker.com:8080/docker-hub/canonical/ubuntu:latest",
|
|
116
|
-
ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], "latest"),
|
|
117
|
-
"hub.docker.com:8080",
|
|
118
|
-
"docker-hub/canonical/ubuntu",
|
|
119
|
-
),
|
|
120
|
-
(
|
|
121
|
-
"hub.docker.com:8080/docker-hub/canonical/ubuntu:22.04",
|
|
122
|
-
ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], "22.04"),
|
|
123
|
-
"hub.docker.com:8080",
|
|
124
|
-
"docker-hub/canonical/ubuntu",
|
|
125
|
-
),
|
|
126
|
-
]
|
|
127
|
-
|
|
128
|
-
@ddt.idata(data_image_name)
|
|
129
|
-
@ddt.unpack
|
|
130
|
-
def test_image_name(self, image_name_str, image_name, registry, repository):
|
|
131
|
-
actual = ImageName.parse(image_name_str)
|
|
132
|
-
|
|
133
|
-
self.assertEqual(image_name.registry_host, actual.registry_host)
|
|
134
|
-
self.assertEqual(image_name.registry_port, actual.registry_port)
|
|
135
|
-
self.assertEqual(image_name.components, actual.components)
|
|
136
|
-
self.assertEqual(image_name.tag, actual.tag)
|
|
137
|
-
self.assertEqual(image_name.registry, actual.registry)
|
|
138
|
-
self.assertEqual(image_name.repository, actual.repository)
|
|
139
|
-
|
|
140
|
-
self.assertEqual(registry, actual.registry)
|
|
141
|
-
self.assertEqual(repository, actual.repository)
|
|
142
|
-
|
|
143
|
-
data_image_name__bad_names = [
|
|
144
|
-
("Ubuntu",),
|
|
145
|
-
("UBUNTU",),
|
|
146
|
-
("ubuntu.",),
|
|
147
|
-
("ubuntu__",),
|
|
148
|
-
("ubuntu-",),
|
|
149
|
-
("ubuntu..ubuntu",),
|
|
150
|
-
("ubuntu___ubuntu",),
|
|
151
|
-
("ubuntu._ubuntu",),
|
|
152
|
-
("ubuntu//ubuntu",),
|
|
153
|
-
("underscore_hostname.dummy.io:12345/ubuntu",),
|
|
154
|
-
("hostname.dummy.io:bad_port/ubuntu",),
|
|
155
|
-
(
|
|
156
|
-
"ubuntu:tag_is_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_too_long",
|
|
157
|
-
),
|
|
158
|
-
]
|
|
159
|
-
|
|
160
|
-
@ddt.idata(data_image_name__bad_names)
|
|
161
|
-
@ddt.unpack
|
|
162
|
-
def test_image_name__bad_names(self, image_name_str):
|
|
163
|
-
self.assertIsNone(ImageName.parse(image_name_str))
|
|
164
|
-
|
|
165
|
-
def test_docker_create_client(self):
|
|
166
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
167
|
-
with docker_create_client("dummy-registry", "dummy_username", "dummy_password"):
|
|
168
|
-
pass
|
|
169
|
-
|
|
170
|
-
mock_docker_client.return_value.login.assert_called_with(registry="dummy-registry",
|
|
171
|
-
username="dummy_username",
|
|
172
|
-
password="dummy_password",
|
|
173
|
-
reauth=True)
|
|
174
|
-
|
|
175
|
-
def test_docker_create_client__with_exception(self):
|
|
176
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
177
|
-
mock_docker_client.return_value.login.side_effect = docker.errors.APIError("")
|
|
178
|
-
|
|
179
|
-
with self.assertRaises(docker.errors.APIError):
|
|
180
|
-
with docker_create_client("dummy-registry", "dummy_username", "dummy_password"):
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
|
-
mock_docker_client.return_value.login.assert_called_with(registry="dummy-registry",
|
|
184
|
-
username="dummy_username",
|
|
185
|
-
password="dummy_password",
|
|
186
|
-
reauth=True)
|
|
187
|
-
|
|
188
|
-
def test_docker_build_image(self):
|
|
189
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
190
|
-
mock_docker_image = MockedDockerImage("dummy_image",
|
|
191
|
-
tags_callee=return_callee("dummy_tags"),
|
|
192
|
-
labels_callee=return_callee("dummy_labels"))
|
|
193
|
-
mock_docker_client.return_value.images.build.return_value = (
|
|
194
|
-
mock_docker_image,
|
|
195
|
-
[{"dummy-log-key": "dummy-log-value"}],
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
image_model, build_logs = docker_build_image(mock_docker_client.return_value,
|
|
199
|
-
"dummy_tag",
|
|
200
|
-
"dummy_path",
|
|
201
|
-
"dummy_dockerfile",
|
|
202
|
-
{"dummy_arg": "dummy_value"})
|
|
203
|
-
|
|
204
|
-
self.assertEqual(image_model.id, "dummy_image")
|
|
205
|
-
self.assertEqual(image_model.tags, "dummy_tags")
|
|
206
|
-
self.assertEqual(image_model.labels, "dummy_labels")
|
|
207
|
-
self.assertEqual(build_logs, [{"dummy-log-key": "dummy-log-value"}])
|
|
208
|
-
|
|
209
|
-
mock_docker_client.return_value.images.build.assert_called_with(tag="dummy_tag",
|
|
210
|
-
path="dummy_path",
|
|
211
|
-
dockerfile="dummy_dockerfile",
|
|
212
|
-
buildargs={"dummy_arg": "dummy_value"},
|
|
213
|
-
rm=True,
|
|
214
|
-
forcerm=True,
|
|
215
|
-
nocache=True)
|
|
216
|
-
|
|
217
|
-
data_docker_build_image__with_exception = [
|
|
218
|
-
(docker.errors.BuildError("dummy reason", iter([{"dummy-log-key": "dummy-log-value"}])),),
|
|
219
|
-
(docker.errors.APIError("dummy message"),),
|
|
220
|
-
(Exception(),),
|
|
221
|
-
]
|
|
222
|
-
|
|
223
|
-
@ddt.idata(data_docker_build_image__with_exception)
|
|
224
|
-
@ddt.unpack
|
|
225
|
-
def test_docker_build_image__with_exception(self, exception):
|
|
226
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
227
|
-
mock_docker_client.return_value.images.build.side_effect = exception
|
|
228
|
-
|
|
229
|
-
with self.assertRaises(type(exception)):
|
|
230
|
-
docker_build_image(mock_docker_client.return_value,
|
|
231
|
-
"dummy_tag",
|
|
232
|
-
"dummy_path",
|
|
233
|
-
"dummy_dockerfile",
|
|
234
|
-
{"dummy_arg": "dummy_value"})
|
|
235
|
-
|
|
236
|
-
mock_docker_client.return_value.images.build.assert_called_with(tag="dummy_tag",
|
|
237
|
-
path="dummy_path",
|
|
238
|
-
dockerfile="dummy_dockerfile",
|
|
239
|
-
buildargs={"dummy_arg": "dummy_value"},
|
|
240
|
-
rm=True,
|
|
241
|
-
forcerm=True,
|
|
242
|
-
nocache=True)
|
|
243
|
-
|
|
244
|
-
def test_docker_get_image(self):
|
|
245
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
246
|
-
mock_docker_image = MockedDockerImage("dummy_image",
|
|
247
|
-
tags_callee=return_callee("dummy_tags"),
|
|
248
|
-
labels_callee=return_callee("dummy_labels"))
|
|
249
|
-
mock_docker_client.return_value.images.get.return_value = mock_docker_image
|
|
250
|
-
|
|
251
|
-
image_model = docker_get_image(mock_docker_client.return_value, "dummy_image")
|
|
252
|
-
|
|
253
|
-
self.assertEqual(image_model.id, "dummy_image")
|
|
254
|
-
self.assertEqual(image_model.tags, "dummy_tags")
|
|
255
|
-
self.assertEqual(image_model.labels, "dummy_labels")
|
|
256
|
-
|
|
257
|
-
mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
|
|
258
|
-
|
|
259
|
-
data_docker_get_image__with_exception = [
|
|
260
|
-
(docker.errors.ImageNotFound("dummy message"),),
|
|
261
|
-
(docker.errors.APIError("dummy message"),),
|
|
262
|
-
(Exception(),),
|
|
263
|
-
]
|
|
264
|
-
|
|
265
|
-
@ddt.idata(data_docker_get_image__with_exception)
|
|
266
|
-
@ddt.unpack
|
|
267
|
-
def test_docker_get_image__with_exception(self, exception):
|
|
268
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
269
|
-
mock_docker_client.return_value.images.get.side_effect = exception
|
|
270
|
-
|
|
271
|
-
with self.assertRaises(type(exception)):
|
|
272
|
-
docker_get_image(mock_docker_client.return_value, "dummy_image")
|
|
273
|
-
|
|
274
|
-
mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
|
|
275
|
-
|
|
276
|
-
def test_docker_pull_image(self):
|
|
277
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
278
|
-
mock_get_docker_image = MockedDockerImage("dummy_get_image",
|
|
279
|
-
tags_callee=return_callee("dummy_get_tags"),
|
|
280
|
-
labels_callee=return_callee("dummy_get_labels"))
|
|
281
|
-
mock_docker_client.return_value.images.get.return_value = mock_get_docker_image
|
|
282
|
-
mock_pull_docker_image = MockedDockerImage("dummy_pull_image",
|
|
283
|
-
tags_callee=return_callee("dummy_pull_tags"),
|
|
284
|
-
labels_callee=return_callee("dummy_pull_labels"))
|
|
285
|
-
mock_docker_client.return_value.images.pull.return_value = mock_pull_docker_image
|
|
286
|
-
|
|
287
|
-
image_model = docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
|
|
288
|
-
|
|
289
|
-
self.assertEqual(image_model.id, "dummy_pull_image")
|
|
290
|
-
self.assertEqual(image_model.tags, "dummy_pull_tags")
|
|
291
|
-
self.assertEqual(image_model.labels, "dummy_pull_labels")
|
|
292
|
-
|
|
293
|
-
mock_docker_client.return_value.images.get.assert_not_called()
|
|
294
|
-
mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
|
|
295
|
-
|
|
296
|
-
def test_docker_pull_image__fallback(self):
|
|
297
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
298
|
-
mock_docker_image = MockedDockerImage("dummy_get_image",
|
|
299
|
-
tags_callee=return_callee("dummy_get_tags"),
|
|
300
|
-
labels_callee=return_callee("dummy_get_labels"))
|
|
301
|
-
mock_docker_client.return_value.images.get.return_value = mock_docker_image
|
|
302
|
-
mock_docker_client.return_value.images.pull.side_effect = docker.errors.APIError("dummy message")
|
|
303
|
-
|
|
304
|
-
image_model = docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
|
|
305
|
-
|
|
306
|
-
self.assertEqual(image_model.id, "dummy_get_image")
|
|
307
|
-
self.assertEqual(image_model.tags, "dummy_get_tags")
|
|
308
|
-
self.assertEqual(image_model.labels, "dummy_get_labels")
|
|
309
|
-
|
|
310
|
-
mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
|
|
311
|
-
mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
|
|
312
|
-
|
|
313
|
-
data_docker_pull_image__with_exception = [
|
|
314
|
-
(docker.errors.ImageNotFound("dummy message"),),
|
|
315
|
-
(docker.errors.APIError("dummy message"),),
|
|
316
|
-
(Exception(),),
|
|
317
|
-
]
|
|
318
|
-
|
|
319
|
-
@ddt.idata(data_docker_pull_image__with_exception)
|
|
320
|
-
@ddt.unpack
|
|
321
|
-
def test_docker_pull_image__with_exception(self, exception):
|
|
322
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
323
|
-
mock_docker_client.return_value.images.get.side_effect = docker.errors.APIError("dummy message")
|
|
324
|
-
|
|
325
|
-
mock_docker_client.return_value.images.pull.side_effect = exception
|
|
326
|
-
|
|
327
|
-
with self.assertRaises(type(exception)):
|
|
328
|
-
docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=False)
|
|
329
|
-
|
|
330
|
-
mock_docker_client.return_value.images.get.assert_not_called()
|
|
331
|
-
mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
|
|
332
|
-
|
|
333
|
-
data_docker_pull_image__fallback_with_exception = [
|
|
334
|
-
(docker.errors.ImageNotFound("dummy message"),),
|
|
335
|
-
(docker.errors.APIError("dummy message"),),
|
|
336
|
-
(Exception(),),
|
|
337
|
-
]
|
|
338
|
-
|
|
339
|
-
@ddt.idata(data_docker_pull_image__fallback_with_exception)
|
|
340
|
-
@ddt.unpack
|
|
341
|
-
def test_docker_pull_image__fallback_with_exception(self, exception):
|
|
342
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
343
|
-
mock_docker_client.return_value.images.get.side_effect = exception
|
|
344
|
-
mock_docker_client.return_value.images.pull.side_effect = docker.errors.APIError("dummy message")
|
|
345
|
-
|
|
346
|
-
with self.assertRaises(type(exception)):
|
|
347
|
-
docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
|
|
348
|
-
|
|
349
|
-
mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
|
|
350
|
-
mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
|
|
351
|
-
|
|
352
|
-
def test_docker_fetch_image(self):
|
|
353
|
-
with (
|
|
354
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client,
|
|
355
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_get_image") as mock_docker_get_image,
|
|
356
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_pull_image") as mock_docker_pull_image,
|
|
357
|
-
):
|
|
358
|
-
docker_fetch_image(mock_docker_client.return_value, "dummy_image")
|
|
359
|
-
|
|
360
|
-
mock_docker_get_image.assert_called_with(mock_docker_client.return_value, "dummy_image")
|
|
361
|
-
mock_docker_pull_image.assert_not_called()
|
|
362
|
-
|
|
363
|
-
def test_docker_fetch_image__force_pull(self):
|
|
364
|
-
with (
|
|
365
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client,
|
|
366
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_get_image") as mock_docker_get_image,
|
|
367
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_pull_image") as mock_docker_pull_image,
|
|
368
|
-
):
|
|
369
|
-
docker_fetch_image(mock_docker_client.return_value, "dummy_image", force_pull=True)
|
|
370
|
-
|
|
371
|
-
mock_docker_get_image.assert_not_called()
|
|
372
|
-
mock_docker_pull_image.assert_called_with(mock_docker_client.return_value,
|
|
373
|
-
"dummy_image",
|
|
374
|
-
fallback_local=True)
|
|
375
|
-
|
|
376
|
-
def test_docker_fetch_image__get_image_failed(self):
|
|
377
|
-
with (
|
|
378
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client,
|
|
379
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_get_image") as mock_docker_get_image,
|
|
380
|
-
unittest.mock.patch("iker.common.utils.dockerutils.docker_pull_image") as mock_docker_pull_image,
|
|
381
|
-
):
|
|
382
|
-
mock_docker_get_image.side_effect = docker.errors.APIError("dummy message")
|
|
383
|
-
|
|
384
|
-
docker_fetch_image(mock_docker_client.return_value, "dummy_image")
|
|
385
|
-
|
|
386
|
-
mock_docker_get_image.assert_called_with(mock_docker_client.return_value, "dummy_image")
|
|
387
|
-
mock_docker_pull_image.assert_called_with(mock_docker_client.return_value,
|
|
388
|
-
"dummy_image",
|
|
389
|
-
fallback_local=False)
|
|
390
|
-
|
|
391
|
-
def test_docker_run_detached(self):
|
|
392
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
393
|
-
mock_docker_container = MockedDockerContainer("dummy_container",
|
|
394
|
-
status_callee=return_callee("dummy_status"),
|
|
395
|
-
wait_callee=return_callee({"dummy_key": "dummy_value"}),
|
|
396
|
-
logs_callee=return_callee("dummy log"),
|
|
397
|
-
stop_callee=return_callee(),
|
|
398
|
-
remove_callee=return_callee())
|
|
399
|
-
mock_docker_client.return_value.containers.run.return_value = mock_docker_container
|
|
400
|
-
|
|
401
|
-
result, log = docker_run_detached(mock_docker_client.return_value,
|
|
402
|
-
"dummy_image",
|
|
403
|
-
"dummy_container",
|
|
404
|
-
"dummy_command",
|
|
405
|
-
{"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
406
|
-
{"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
407
|
-
{"dummy.ip.address": "127.0.0.1"},
|
|
408
|
-
1000,
|
|
409
|
-
dummy_kwarg="dummy_value")
|
|
410
|
-
|
|
411
|
-
self.assertEqual(result, {"dummy_key": "dummy_value"})
|
|
412
|
-
self.assertEqual(log, "dummy log")
|
|
413
|
-
|
|
414
|
-
mock_docker_client.return_value.containers.run.assert_called_with(
|
|
415
|
-
image="dummy_image",
|
|
416
|
-
name="dummy_container",
|
|
417
|
-
command="dummy_command",
|
|
418
|
-
volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
419
|
-
environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
420
|
-
extra_hosts={"dummy.ip.address": "127.0.0.1"},
|
|
421
|
-
detach=True,
|
|
422
|
-
dummy_kwarg="dummy_value",
|
|
423
|
-
)
|
|
424
|
-
mock_docker_container.status_callee.assert_called_once()
|
|
425
|
-
mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
|
|
426
|
-
mock_docker_container.wait_callee.assert_called_once_with()()
|
|
427
|
-
mock_docker_container.logs_callee.assert_called_once()
|
|
428
|
-
mock_docker_container.stop_callee.assert_called_once()
|
|
429
|
-
mock_docker_container.remove_callee.assert_called_once()
|
|
430
|
-
|
|
431
|
-
data_docker_run_detached__with_exception_on_wait = [
|
|
432
|
-
(requests.exceptions.ReadTimeout(),),
|
|
433
|
-
(docker.errors.ImageNotFound("dummy message"),),
|
|
434
|
-
(
|
|
435
|
-
docker.errors.ContainerError("dummy container",
|
|
436
|
-
"dummy exit status",
|
|
437
|
-
"dummy command",
|
|
438
|
-
"dummy image",
|
|
439
|
-
"dummy stderr"),
|
|
440
|
-
),
|
|
441
|
-
(docker.errors.APIError("dummy message"),),
|
|
442
|
-
(Exception(),),
|
|
443
|
-
]
|
|
444
|
-
|
|
445
|
-
@ddt.idata(data_docker_run_detached__with_exception_on_wait)
|
|
446
|
-
@ddt.unpack
|
|
447
|
-
def test_docker_run_detached__with_exception_on_wait(self, exception):
|
|
448
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
449
|
-
def mock_containers_run_wait_valuer(*args, **kwargs):
|
|
450
|
-
if kwargs == dict(timeout=1000):
|
|
451
|
-
raise exception
|
|
452
|
-
|
|
453
|
-
mock_docker_container = MockedDockerContainer("dummy_container",
|
|
454
|
-
status_callee=return_callee("dummy_status"),
|
|
455
|
-
wait_callee=return_callee(mock_containers_run_wait_valuer),
|
|
456
|
-
logs_callee=return_callee("dummy log"),
|
|
457
|
-
stop_callee=return_callee(),
|
|
458
|
-
remove_callee=return_callee())
|
|
459
|
-
mock_docker_client.return_value.containers.run.return_value = mock_docker_container
|
|
460
|
-
|
|
461
|
-
with self.assertRaises(type(exception)):
|
|
462
|
-
docker_run_detached(mock_docker_client.return_value,
|
|
463
|
-
"dummy_image",
|
|
464
|
-
"dummy_container",
|
|
465
|
-
"dummy_command",
|
|
466
|
-
{"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
467
|
-
{"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
468
|
-
{"dummy.ip.address": "127.0.0.1"},
|
|
469
|
-
1000,
|
|
470
|
-
dummy_kwarg="dummy_value")
|
|
471
|
-
|
|
472
|
-
mock_docker_client.return_value.containers.run.assert_called_with(
|
|
473
|
-
image="dummy_image",
|
|
474
|
-
name="dummy_container",
|
|
475
|
-
command="dummy_command",
|
|
476
|
-
volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
477
|
-
environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
478
|
-
extra_hosts={"dummy.ip.address": "127.0.0.1"},
|
|
479
|
-
detach=True,
|
|
480
|
-
dummy_kwarg="dummy_value",
|
|
481
|
-
)
|
|
482
|
-
mock_docker_container.status_callee.assert_called_once()
|
|
483
|
-
mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
|
|
484
|
-
mock_docker_container.wait_callee.assert_called_once_with()()
|
|
485
|
-
mock_docker_container.logs_callee.assert_not_called()
|
|
486
|
-
mock_docker_container.stop_callee.assert_called_once()
|
|
487
|
-
mock_docker_container.remove_callee.assert_called_once()
|
|
488
|
-
|
|
489
|
-
data_docker_run_detached__with_exception_on_stop = [
|
|
490
|
-
(docker.errors.ImageNotFound("dummy message"),),
|
|
491
|
-
(
|
|
492
|
-
docker.errors.ContainerError("dummy container",
|
|
493
|
-
"dummy exit status",
|
|
494
|
-
"dummy command",
|
|
495
|
-
"dummy image",
|
|
496
|
-
"dummy stderr"),
|
|
497
|
-
),
|
|
498
|
-
(docker.errors.APIError("dummy message"),),
|
|
499
|
-
]
|
|
500
|
-
|
|
501
|
-
@ddt.idata(data_docker_run_detached__with_exception_on_stop)
|
|
502
|
-
@ddt.unpack
|
|
503
|
-
def test_docker_run_detached__with_exception_on_stop(self, exception):
|
|
504
|
-
with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
|
|
505
|
-
def mock_containers_run_stop_valuer(*args, **kwargs):
|
|
506
|
-
raise exception
|
|
507
|
-
|
|
508
|
-
mock_docker_container = MockedDockerContainer("dummy_container",
|
|
509
|
-
status_callee=return_callee("dummy_status"),
|
|
510
|
-
wait_callee=return_callee({"dummy_key": "dummy_value"}),
|
|
511
|
-
logs_callee=return_callee("dummy log"),
|
|
512
|
-
stop_callee=return_callee(mock_containers_run_stop_valuer),
|
|
513
|
-
remove_callee=return_callee())
|
|
514
|
-
mock_docker_client.return_value.containers.run.return_value = mock_docker_container
|
|
515
|
-
|
|
516
|
-
result, log = docker_run_detached(mock_docker_client.return_value,
|
|
517
|
-
"dummy_image",
|
|
518
|
-
"dummy_container",
|
|
519
|
-
"dummy_command",
|
|
520
|
-
{"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
521
|
-
{"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
522
|
-
{"dummy.ip.address": "127.0.0.1"},
|
|
523
|
-
1000,
|
|
524
|
-
dummy_kwarg="dummy_value")
|
|
525
|
-
|
|
526
|
-
self.assertEqual(result, {"dummy_key": "dummy_value"})
|
|
527
|
-
self.assertEqual(log, "dummy log")
|
|
528
|
-
|
|
529
|
-
mock_docker_client.return_value.containers.run.assert_called_with(
|
|
530
|
-
image="dummy_image",
|
|
531
|
-
name="dummy_container",
|
|
532
|
-
command="dummy_command",
|
|
533
|
-
volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
|
|
534
|
-
environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
|
|
535
|
-
extra_hosts={"dummy.ip.address": "127.0.0.1"},
|
|
536
|
-
detach=True,
|
|
537
|
-
dummy_kwarg="dummy_value",
|
|
538
|
-
)
|
|
539
|
-
mock_docker_container.status_callee.assert_called_once()
|
|
540
|
-
mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
|
|
541
|
-
mock_docker_container.wait_callee.assert_called_once_with()()
|
|
542
|
-
mock_docker_container.logs_callee.assert_called_once()
|
|
543
|
-
mock_docker_container.stop_callee.assert_called_once()
|
|
544
|
-
mock_docker_container.remove_callee.assert_called_once()
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import docker
|
|
2
|
-
import docker.errors
|
|
3
|
-
import docker.models.containers
|
|
4
|
-
import docker.models.images
|
|
5
|
-
import docker.models.resource
|
|
6
|
-
|
|
7
|
-
from iker.common.utils.testutils import CalleeMock
|
|
8
|
-
from iker.common.utils.testutils import return_callee
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
"MockedDockerClient",
|
|
12
|
-
"MockedDockerImage",
|
|
13
|
-
"MockedDockerContainer",
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class MockedDockerClient(docker.DockerClient):
|
|
18
|
-
def __init__(self):
|
|
19
|
-
# Do not call superclass init to avoid underlying API client being initialized
|
|
20
|
-
pass
|
|
21
|
-
|
|
22
|
-
def close(self):
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class MockedDockerImage(docker.models.resource.Model):
|
|
27
|
-
def __init__(
|
|
28
|
-
self,
|
|
29
|
-
model_id: str,
|
|
30
|
-
*,
|
|
31
|
-
tags_callee: CalleeMock = return_callee(),
|
|
32
|
-
labels_callee: CalleeMock = return_callee(),
|
|
33
|
-
):
|
|
34
|
-
super(MockedDockerImage, self).__init__({docker.models.resource.Model.id_attribute: model_id})
|
|
35
|
-
self.tags_callee = tags_callee
|
|
36
|
-
self.labels_callee = labels_callee
|
|
37
|
-
|
|
38
|
-
@property
|
|
39
|
-
def tags(self):
|
|
40
|
-
return self.tags_callee()
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def labels(self):
|
|
44
|
-
return self.labels_callee()
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class MockedDockerContainer(docker.models.resource.Model):
|
|
48
|
-
def __init__(
|
|
49
|
-
self,
|
|
50
|
-
model_id: str,
|
|
51
|
-
*,
|
|
52
|
-
status_callee: CalleeMock = return_callee(),
|
|
53
|
-
wait_callee: CalleeMock = return_callee(),
|
|
54
|
-
logs_callee: CalleeMock = return_callee(),
|
|
55
|
-
stop_callee: CalleeMock = return_callee(),
|
|
56
|
-
remove_callee: CalleeMock = return_callee(),
|
|
57
|
-
):
|
|
58
|
-
super(MockedDockerContainer, self).__init__({docker.models.resource.Model.id_attribute: model_id})
|
|
59
|
-
self.status_callee = status_callee
|
|
60
|
-
self.wait_callee = wait_callee
|
|
61
|
-
self.logs_callee = logs_callee
|
|
62
|
-
self.stop_callee = stop_callee
|
|
63
|
-
self.remove_callee = remove_callee
|
|
64
|
-
|
|
65
|
-
@property
|
|
66
|
-
def status(self):
|
|
67
|
-
return self.status_callee()
|
|
68
|
-
|
|
69
|
-
def wait(self, **kwargs):
|
|
70
|
-
return self.wait_callee(**kwargs)
|
|
71
|
-
|
|
72
|
-
def logs(self, **kwargs):
|
|
73
|
-
return self.logs_callee(**kwargs)
|
|
74
|
-
|
|
75
|
-
def stop(self, **kwargs):
|
|
76
|
-
return self.stop_callee(**kwargs)
|
|
77
|
-
|
|
78
|
-
def remove(self, **kwargs):
|
|
79
|
-
return self.remove_callee(**kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/config/config.cfg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.bar
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.baz
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/resources/unittest/shutils/dir.foo/file.foo
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/src/iker_python_common.egg-info/not-zip-safe
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/config_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/csv_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/dbutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/dtutils_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/logger_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/retry_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/shutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.62 → iker_python_common-1.0.63}/test/iker_tests/common/utils/span_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|