iker-python-common 1.0.25__tar.gz → 1.0.27__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.
Files changed (72) hide show
  1. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/PKG-INFO +1 -2
  2. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/pyproject.toml +0 -1
  3. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/dockerutils.py +13 -14
  4. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/PKG-INFO +1 -2
  5. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/requires.txt +0 -1
  6. iker_python_common-1.0.27/test/iker_tests/common/utils/dockerutils_test.py +529 -0
  7. iker_python_common-1.0.25/test/iker_tests/common/utils/dockerutils_test.py +0 -629
  8. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/.editorconfig +0 -0
  9. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/.github/workflows/pr.yml +0 -0
  10. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/.github/workflows/push.yml +0 -0
  11. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/.gitignore +0 -0
  12. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/MANIFEST.in +0 -0
  13. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/README.md +0 -0
  14. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/VERSION +0 -0
  15. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/config/config.cfg +0 -0
  16. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/csv/data.csv +0 -0
  17. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/csv/data.tsv +0 -0
  18. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.baz/file.bar.baz +0 -0
  19. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.baz/file.foo.bar +0 -0
  20. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.baz/file.foo.baz +0 -0
  21. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
  22. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
  23. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
  24. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
  25. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/file.bar +0 -0
  26. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/file.baz +0 -0
  27. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/resources/unittest/shutils/dir.foo/file.foo +0 -0
  28. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/setup.cfg +0 -0
  29. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/setup.py +0 -0
  30. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/__init__.py +0 -0
  31. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/__init__.py +0 -0
  32. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/argutils.py +0 -0
  33. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/config.py +0 -0
  34. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/csv.py +0 -0
  35. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/dbutils.py +0 -0
  36. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/dtutils.py +0 -0
  37. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/funcutils.py +0 -0
  38. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/jsonutils.py +0 -0
  39. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/logger.py +0 -0
  40. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/numutils.py +0 -0
  41. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/randutils.py +0 -0
  42. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/retry.py +0 -0
  43. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/s3utils.py +0 -0
  44. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/sequtils.py +0 -0
  45. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/shutils.py +0 -0
  46. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/span.py +0 -0
  47. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/strutils.py +0 -0
  48. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker/common/utils/testutils.py +0 -0
  49. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/SOURCES.txt +0 -0
  50. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/dependency_links.txt +0 -0
  51. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/not-zip-safe +0 -0
  52. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/src/iker_python_common.egg-info/top_level.txt +0 -0
  53. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_test.py +0 -0
  54. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/__init__.py +0 -0
  55. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/argutils_test.py +0 -0
  56. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/config_test.py +0 -0
  57. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/csv_test.py +0 -0
  58. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/dbutils_test.py +0 -0
  59. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/dtutils_test.py +0 -0
  60. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/funcutils_test.py +0 -0
  61. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/jsonutils_test.py +0 -0
  62. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/logger_test.py +0 -0
  63. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/numutils_test.py +0 -0
  64. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/randutils_test.py +0 -0
  65. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/retry_test.py +0 -0
  66. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/s3utils_test.py +0 -0
  67. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/sequtils_test.py +0 -0
  68. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/shutils_test.py +0 -0
  69. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/span_test.py +0 -0
  70. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/strutils_test.py +0 -0
  71. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/common/utils/testutils_test.py +0 -0
  72. {iker_python_common-1.0.25 → iker_python_common-1.0.27}/test/iker_tests/docker_fixtures.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: iker-python-common
3
- Version: 1.0.25
3
+ Version: 1.0.27
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -16,7 +16,6 @@ Provides-Extra: test
16
16
  Requires-Dist: ddt>=1.7; extra == "test"
17
17
  Requires-Dist: moto[all,ec2,s3]>=5.0; extra == "test"
18
18
  Requires-Dist: pytest-cov>=5.0; extra == "test"
19
- Requires-Dist: pytest-mock>=3.14; extra == "test"
20
19
  Requires-Dist: pytest-mysql>=3.0; extra == "test"
21
20
  Requires-Dist: pytest-order>=1.3; extra == "test"
22
21
  Requires-Dist: pytest-postgresql>=6.1; extra == "test"
@@ -30,7 +30,6 @@ test = [
30
30
  "ddt>=1.7",
31
31
  "moto[ec2,s3,all]>=5.0",
32
32
  "pytest-cov>=5.0",
33
- "pytest-mock>=3.14",
34
33
  "pytest-mysql>=3.0",
35
34
  "pytest-order>=1.3",
36
35
  "pytest-postgresql>=6.1",
@@ -1,6 +1,6 @@
1
1
  import contextlib
2
2
  import re
3
- from collections.abc import Generator, Iterable
3
+ from collections.abc import Generator, Iterator
4
4
  from dataclasses import dataclass
5
5
  from typing import Any
6
6
 
@@ -89,7 +89,7 @@ def docker_build_image(
89
89
  path: str,
90
90
  dockerfile: str,
91
91
  build_args: dict[str, str],
92
- ) -> tuple[docker.models.images.Image, Iterable[Any]]:
92
+ ) -> tuple[docker.models.images.Image, Iterator[dict[str, str]]]:
93
93
  try:
94
94
  return client.images.build(tag=tag,
95
95
  path=path,
@@ -188,21 +188,20 @@ def docker_run_detached(
188
188
  except docker.errors.DockerException:
189
189
  raise
190
190
  finally:
191
- if container_model is None:
192
- return
193
- try:
194
- if container_model.status != "exited":
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()
195
199
  try:
196
- container_model.stop()
200
+ container_model.remove()
197
201
  except docker.errors.DockerException:
198
202
  pass
199
- container_model.wait()
200
- try:
201
- container_model.remove()
202
- except docker.errors.DockerException:
203
- pass
204
- except Exception:
205
- raise
203
+ except Exception:
204
+ raise
206
205
 
207
206
  try:
208
207
  run_args = kwargs.copy()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: iker-python-common
3
- Version: 1.0.25
3
+ Version: 1.0.27
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -16,7 +16,6 @@ Provides-Extra: test
16
16
  Requires-Dist: ddt>=1.7; extra == "test"
17
17
  Requires-Dist: moto[all,ec2,s3]>=5.0; extra == "test"
18
18
  Requires-Dist: pytest-cov>=5.0; extra == "test"
19
- Requires-Dist: pytest-mock>=3.14; extra == "test"
20
19
  Requires-Dist: pytest-mysql>=3.0; extra == "test"
21
20
  Requires-Dist: pytest-order>=1.3; extra == "test"
22
21
  Requires-Dist: pytest-postgresql>=6.1; extra == "test"
@@ -9,7 +9,6 @@ sqlalchemy>=2.0
9
9
  ddt>=1.7
10
10
  moto[all,ec2,s3]>=5.0
11
11
  pytest-cov>=5.0
12
- pytest-mock>=3.14
13
12
  pytest-mysql>=3.0
14
13
  pytest-order>=1.3
15
14
  pytest-postgresql>=6.1
@@ -0,0 +1,529 @@
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
+
18
+ @ddt.data(
19
+ (
20
+ "ubuntu",
21
+ ImageName(None, None, ["ubuntu"], None),
22
+ "",
23
+ "ubuntu",
24
+ ),
25
+ (
26
+ "ubuntu:latest",
27
+ ImageName(None, None, ["ubuntu"], "latest"),
28
+ "",
29
+ "ubuntu",
30
+ ),
31
+ (
32
+ "ubuntu:22.04",
33
+ ImageName(None, None, ["ubuntu"], "22.04"),
34
+ "",
35
+ "ubuntu",
36
+ ),
37
+ (
38
+ "canonical/ubuntu",
39
+ ImageName(None, None, ["canonical", "ubuntu"], None),
40
+ "",
41
+ "canonical/ubuntu",
42
+ ),
43
+ (
44
+ "canonical/ubuntu:latest",
45
+ ImageName(None, None, ["canonical", "ubuntu"], "latest"),
46
+ "",
47
+ "canonical/ubuntu",
48
+ ),
49
+ (
50
+ "canonical/ubuntu:22.04",
51
+ ImageName(None, None, ["canonical", "ubuntu"], "22.04"),
52
+ "",
53
+ "canonical/ubuntu",
54
+ ),
55
+ (
56
+ "hub.docker.com/canonical/ubuntu",
57
+ ImageName("hub.docker.com", None, ["canonical", "ubuntu"], None),
58
+ "hub.docker.com",
59
+ "canonical/ubuntu",
60
+ ),
61
+ (
62
+ "hub.docker.com/canonical/ubuntu:latest",
63
+ ImageName("hub.docker.com", None, ["canonical", "ubuntu"], "latest"),
64
+ "hub.docker.com",
65
+ "canonical/ubuntu",
66
+ ),
67
+ (
68
+ "hub.docker.com/canonical/ubuntu:22.04",
69
+ ImageName("hub.docker.com", None, ["canonical", "ubuntu"], "22.04"),
70
+ "hub.docker.com",
71
+ "canonical/ubuntu",
72
+ ),
73
+ (
74
+ "hub.docker.com:8080/canonical/ubuntu",
75
+ ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], None),
76
+ "hub.docker.com:8080",
77
+ "canonical/ubuntu",
78
+ ),
79
+ (
80
+ "hub.docker.com:8080/canonical/ubuntu:latest",
81
+ ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], "latest"),
82
+ "hub.docker.com:8080",
83
+ "canonical/ubuntu",
84
+ ),
85
+ (
86
+ "hub.docker.com:8080/canonical/ubuntu:22.04",
87
+ ImageName("hub.docker.com", 8080, ["canonical", "ubuntu"], "22.04"),
88
+ "hub.docker.com:8080",
89
+ "canonical/ubuntu",
90
+ ),
91
+ (
92
+ "hub.docker.com:8080/ubuntu",
93
+ ImageName("hub.docker.com", 8080, ["ubuntu"], None),
94
+ "hub.docker.com:8080",
95
+ "ubuntu",
96
+ ),
97
+ (
98
+ "hub.docker.com:8080/ubuntu:latest",
99
+ ImageName("hub.docker.com", 8080, ["ubuntu"], "latest"),
100
+ "hub.docker.com:8080",
101
+ "ubuntu",
102
+ ),
103
+ (
104
+ "hub.docker.com:8080/ubuntu:22.04",
105
+ ImageName("hub.docker.com", 8080, ["ubuntu"], "22.04"),
106
+ "hub.docker.com:8080",
107
+ "ubuntu",
108
+ ),
109
+ (
110
+ "hub.docker.com:8080/docker-hub/canonical/ubuntu",
111
+ ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], None),
112
+ "hub.docker.com:8080",
113
+ "docker-hub/canonical/ubuntu",
114
+ ),
115
+ (
116
+ "hub.docker.com:8080/docker-hub/canonical/ubuntu:latest",
117
+ ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], "latest"),
118
+ "hub.docker.com:8080",
119
+ "docker-hub/canonical/ubuntu",
120
+ ),
121
+ (
122
+ "hub.docker.com:8080/docker-hub/canonical/ubuntu:22.04",
123
+ ImageName("hub.docker.com", 8080, ["docker-hub", "canonical", "ubuntu"], "22.04"),
124
+ "hub.docker.com:8080",
125
+ "docker-hub/canonical/ubuntu",
126
+ ),
127
+ )
128
+ @ddt.unpack
129
+ def test_image_name(self, image_name_str, image_name, registry, repository):
130
+ actual = ImageName.parse(image_name_str)
131
+
132
+ self.assertEqual(image_name.registry_host, actual.registry_host)
133
+ self.assertEqual(image_name.registry_port, actual.registry_port)
134
+ self.assertEqual(image_name.components, actual.components)
135
+ self.assertEqual(image_name.tag, actual.tag)
136
+ self.assertEqual(image_name.registry, actual.registry)
137
+ self.assertEqual(image_name.repository, actual.repository)
138
+
139
+ self.assertEqual(registry, actual.registry)
140
+ self.assertEqual(repository, actual.repository)
141
+
142
+ @ddt.data(
143
+ ("Ubuntu",),
144
+ ("UBUNTU",),
145
+ ("ubuntu.",),
146
+ ("ubuntu__",),
147
+ ("ubuntu-",),
148
+ ("ubuntu..ubuntu",),
149
+ ("ubuntu___ubuntu",),
150
+ ("ubuntu._ubuntu",),
151
+ ("ubuntu//ubuntu",),
152
+ ("underscore_hostname.dummy.io:12345/ubuntu",),
153
+ ("hostname.dummy.io:bad_port/ubuntu",),
154
+ (
155
+ "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",
156
+ ),
157
+ )
158
+ @ddt.unpack
159
+ def test_image_name__bad_names(self, image_name_str):
160
+ self.assertIsNone(ImageName.parse(image_name_str))
161
+
162
+ def test_docker_create_client(self):
163
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
164
+ with docker_create_client("dummy-registry", "dummy_username", "dummy_password"):
165
+ pass
166
+
167
+ mock_docker_client.return_value.login.assert_called_with(registry="dummy-registry",
168
+ username="dummy_username",
169
+ password="dummy_password",
170
+ reauth=True)
171
+
172
+ def test_docker_create_client__with_exception(self):
173
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
174
+ mock_docker_client.return_value.login.side_effect = docker.errors.APIError("")
175
+
176
+ with self.assertRaises(docker.errors.APIError):
177
+ with docker_create_client("dummy-registry", "dummy_username", "dummy_password"):
178
+ pass
179
+
180
+ mock_docker_client.return_value.login.assert_called_with(registry="dummy-registry",
181
+ username="dummy_username",
182
+ password="dummy_password",
183
+ reauth=True)
184
+
185
+ def test_docker_build_image(self):
186
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
187
+ mock_docker_image = MockedDockerImage("dummy_image",
188
+ tags_callee=return_callee("dummy_tags"),
189
+ labels_callee=return_callee("dummy_labels"))
190
+ mock_docker_client.return_value.images.build.return_value = (
191
+ mock_docker_image,
192
+ [{"dummy-log-key": "dummy-log-value"}],
193
+ )
194
+
195
+ image_model, build_logs = docker_build_image(mock_docker_client.return_value,
196
+ "dummy_tag",
197
+ "dummy_path",
198
+ "dummy_dockerfile",
199
+ {"dummy_arg": "dummy_value"})
200
+
201
+ self.assertEqual(image_model.id, "dummy_image")
202
+ self.assertEqual(image_model.tags, "dummy_tags")
203
+ self.assertEqual(image_model.labels, "dummy_labels")
204
+ self.assertEqual(build_logs, [{"dummy-log-key": "dummy-log-value"}])
205
+
206
+ mock_docker_client.return_value.images.build.assert_called_with(tag="dummy_tag",
207
+ path="dummy_path",
208
+ dockerfile="dummy_dockerfile",
209
+ buildargs={"dummy_arg": "dummy_value"},
210
+ rm=True,
211
+ forcerm=True,
212
+ nocache=True)
213
+
214
+ @ddt.data(
215
+ (docker.errors.BuildError("dummy reason", iter([{"dummy-log-key": "dummy-log-value"}])),),
216
+ (docker.errors.APIError("dummy message"),),
217
+ (Exception(),),
218
+ )
219
+ @ddt.unpack
220
+ def test_docker_build_image__with_exception(self, exception):
221
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
222
+ mock_docker_client.return_value.images.build.side_effect = exception
223
+
224
+ with self.assertRaises(type(exception)):
225
+ docker_build_image(mock_docker_client.return_value,
226
+ "dummy_tag",
227
+ "dummy_path",
228
+ "dummy_dockerfile",
229
+ {"dummy_arg": "dummy_value"})
230
+
231
+ mock_docker_client.return_value.images.build.assert_called_with(tag="dummy_tag",
232
+ path="dummy_path",
233
+ dockerfile="dummy_dockerfile",
234
+ buildargs={"dummy_arg": "dummy_value"},
235
+ rm=True,
236
+ forcerm=True,
237
+ nocache=True)
238
+
239
+ def test_docker_get_image(self):
240
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
241
+ mock_docker_image = MockedDockerImage("dummy_image",
242
+ tags_callee=return_callee("dummy_tags"),
243
+ labels_callee=return_callee("dummy_labels"))
244
+ mock_docker_client.return_value.images.get.return_value = mock_docker_image
245
+
246
+ image_model = docker_get_image(mock_docker_client.return_value, "dummy_image")
247
+
248
+ self.assertEqual(image_model.id, "dummy_image")
249
+ self.assertEqual(image_model.tags, "dummy_tags")
250
+ self.assertEqual(image_model.labels, "dummy_labels")
251
+
252
+ mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
253
+
254
+ @ddt.data(
255
+ (docker.errors.ImageNotFound("dummy message"),),
256
+ (docker.errors.APIError("dummy message"),),
257
+ (Exception(),),
258
+ )
259
+ @ddt.unpack
260
+ def test_docker_get_image__with_exception(self, exception):
261
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
262
+ mock_docker_client.return_value.images.get.side_effect = exception
263
+
264
+ with self.assertRaises(type(exception)):
265
+ docker_get_image(mock_docker_client.return_value, "dummy_image")
266
+
267
+ mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
268
+
269
+ def test_docker_pull_image(self):
270
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
271
+ mock_get_docker_image = MockedDockerImage("dummy_get_image",
272
+ tags_callee=return_callee("dummy_get_tags"),
273
+ labels_callee=return_callee("dummy_get_labels"))
274
+ mock_docker_client.return_value.images.get.return_value = mock_get_docker_image
275
+ mock_pull_docker_image = MockedDockerImage("dummy_pull_image",
276
+ tags_callee=return_callee("dummy_pull_tags"),
277
+ labels_callee=return_callee("dummy_pull_labels"))
278
+ mock_docker_client.return_value.images.pull.return_value = mock_pull_docker_image
279
+
280
+ image_model = docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
281
+
282
+ self.assertEqual(image_model.id, "dummy_pull_image")
283
+ self.assertEqual(image_model.tags, "dummy_pull_tags")
284
+ self.assertEqual(image_model.labels, "dummy_pull_labels")
285
+
286
+ mock_docker_client.return_value.images.get.assert_not_called()
287
+ mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
288
+
289
+ def test_docker_pull_image__fallback(self):
290
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
291
+ mock_docker_image = MockedDockerImage("dummy_get_image",
292
+ tags_callee=return_callee("dummy_get_tags"),
293
+ labels_callee=return_callee("dummy_get_labels"))
294
+ mock_docker_client.return_value.images.get.return_value = mock_docker_image
295
+ mock_docker_client.return_value.images.pull.side_effect = docker.errors.APIError("dummy message")
296
+
297
+ image_model = docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
298
+
299
+ self.assertEqual(image_model.id, "dummy_get_image")
300
+ self.assertEqual(image_model.tags, "dummy_get_tags")
301
+ self.assertEqual(image_model.labels, "dummy_get_labels")
302
+
303
+ mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
304
+ mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
305
+
306
+ @ddt.data(
307
+ (docker.errors.ImageNotFound("dummy message"),),
308
+ (docker.errors.APIError("dummy message"),),
309
+ (Exception(),),
310
+ )
311
+ @ddt.unpack
312
+ def test_docker_pull_image__with_exception(self, exception):
313
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
314
+ mock_docker_client.return_value.images.get.side_effect = docker.errors.APIError("dummy message")
315
+
316
+ mock_docker_client.return_value.images.pull.side_effect = exception
317
+
318
+ with self.assertRaises(type(exception)):
319
+ docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=False)
320
+
321
+ mock_docker_client.return_value.images.get.assert_not_called()
322
+ mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
323
+
324
+ @ddt.data(
325
+ (docker.errors.ImageNotFound("dummy message"),),
326
+ (docker.errors.APIError("dummy message"),),
327
+ (Exception(),),
328
+ )
329
+ @ddt.unpack
330
+ def test_docker_pull_image__fallback_with_exception(self, exception):
331
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
332
+ mock_docker_client.return_value.images.get.side_effect = exception
333
+ mock_docker_client.return_value.images.pull.side_effect = docker.errors.APIError("dummy message")
334
+
335
+ with self.assertRaises(type(exception)):
336
+ docker_pull_image(mock_docker_client.return_value, "dummy_image", fallback_local=True)
337
+
338
+ mock_docker_client.return_value.images.get.assert_called_with("dummy_image")
339
+ mock_docker_client.return_value.images.pull.assert_called_with("dummy_image")
340
+
341
+ def test_docker_fetch_image(self):
342
+ with (
343
+ unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client,
344
+ unittest.mock.patch("iker.common.utils.dockerutils.docker_get_image") as mock_docker_get_image,
345
+ unittest.mock.patch("iker.common.utils.dockerutils.docker_pull_image") as mock_docker_pull_image,
346
+ ):
347
+ docker_fetch_image(mock_docker_client.return_value, "dummy_image")
348
+
349
+ mock_docker_get_image.assert_called_with(mock_docker_client.return_value, "dummy_image")
350
+ mock_docker_pull_image.assert_not_called()
351
+
352
+ def test_docker_fetch_image__force_pull(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", force_pull=True)
359
+
360
+ mock_docker_get_image.assert_not_called()
361
+ mock_docker_pull_image.assert_called_with(mock_docker_client.return_value,
362
+ "dummy_image",
363
+ fallback_local=True)
364
+
365
+ def test_docker_fetch_image__get_image_failed(self):
366
+ with (
367
+ unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client,
368
+ unittest.mock.patch("iker.common.utils.dockerutils.docker_get_image") as mock_docker_get_image,
369
+ unittest.mock.patch("iker.common.utils.dockerutils.docker_pull_image") as mock_docker_pull_image,
370
+ ):
371
+ mock_docker_get_image.side_effect = docker.errors.APIError("dummy message")
372
+
373
+ docker_fetch_image(mock_docker_client.return_value, "dummy_image")
374
+
375
+ mock_docker_get_image.assert_called_with(mock_docker_client.return_value, "dummy_image")
376
+ mock_docker_pull_image.assert_called_with(mock_docker_client.return_value,
377
+ "dummy_image",
378
+ fallback_local=False)
379
+
380
+ def test_docker_run_detached(self):
381
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
382
+ mock_docker_container = MockedDockerContainer("dummy_container",
383
+ status_callee=return_callee("dummy_status"),
384
+ wait_callee=return_callee({"dummy_key": "dummy_value"}),
385
+ logs_callee=return_callee("dummy log"),
386
+ stop_callee=return_callee(),
387
+ remove_callee=return_callee())
388
+ mock_docker_client.return_value.containers.run.return_value = mock_docker_container
389
+
390
+ result, log = docker_run_detached(mock_docker_client.return_value,
391
+ "dummy_image",
392
+ "dummy_container",
393
+ "dummy_command",
394
+ {"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
395
+ {"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
396
+ {"dummy.ip.address": "127.0.0.1"},
397
+ 1000,
398
+ dummy_kwarg="dummy_value")
399
+
400
+ self.assertEqual(result, {"dummy_key": "dummy_value"})
401
+ self.assertEqual(log, "dummy log")
402
+
403
+ mock_docker_client.return_value.containers.run.assert_called_with(
404
+ image="dummy_image",
405
+ name="dummy_container",
406
+ command="dummy_command",
407
+ volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
408
+ environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
409
+ extra_hosts={"dummy.ip.address": "127.0.0.1"},
410
+ detach=True,
411
+ dummy_kwarg="dummy_value",
412
+ )
413
+ mock_docker_container.status_callee.assert_called_once()
414
+ mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
415
+ mock_docker_container.wait_callee.assert_called_once_with()()
416
+ mock_docker_container.logs_callee.assert_called_once()
417
+ mock_docker_container.stop_callee.assert_called_once()
418
+ mock_docker_container.remove_callee.assert_called_once()
419
+
420
+ @ddt.data(
421
+ (requests.exceptions.ReadTimeout(),),
422
+ (docker.errors.ImageNotFound("dummy message"),),
423
+ (
424
+ docker.errors.ContainerError("dummy container",
425
+ "dummy exit status",
426
+ "dummy command",
427
+ "dummy image",
428
+ "dummy stderr"),
429
+ ),
430
+ (docker.errors.APIError("dummy message"),),
431
+ (Exception(),),
432
+ )
433
+ @ddt.unpack
434
+ def test_docker_run_detached__with_exception_on_wait(self, exception):
435
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
436
+ def mock_containers_run_wait_valuer(*args, **kwargs):
437
+ if kwargs == dict(timeout=1000):
438
+ raise exception
439
+
440
+ mock_docker_container = MockedDockerContainer("dummy_container",
441
+ status_callee=return_callee("dummy_status"),
442
+ wait_callee=return_callee(mock_containers_run_wait_valuer),
443
+ logs_callee=return_callee("dummy log"),
444
+ stop_callee=return_callee(),
445
+ remove_callee=return_callee())
446
+ mock_docker_client.return_value.containers.run.return_value = mock_docker_container
447
+
448
+ with self.assertRaises(type(exception)):
449
+ docker_run_detached(mock_docker_client.return_value,
450
+ "dummy_image",
451
+ "dummy_container",
452
+ "dummy_command",
453
+ {"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
454
+ {"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
455
+ {"dummy.ip.address": "127.0.0.1"},
456
+ 1000,
457
+ dummy_kwarg="dummy_value")
458
+
459
+ mock_docker_client.return_value.containers.run.assert_called_with(
460
+ image="dummy_image",
461
+ name="dummy_container",
462
+ command="dummy_command",
463
+ volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
464
+ environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
465
+ extra_hosts={"dummy.ip.address": "127.0.0.1"},
466
+ detach=True,
467
+ dummy_kwarg="dummy_value",
468
+ )
469
+ mock_docker_container.status_callee.assert_called_once()
470
+ mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
471
+ mock_docker_container.wait_callee.assert_called_once_with()()
472
+ mock_docker_container.logs_callee.assert_not_called()
473
+ mock_docker_container.stop_callee.assert_called_once()
474
+ mock_docker_container.remove_callee.assert_called_once()
475
+
476
+ @ddt.data(
477
+ (docker.errors.ImageNotFound("dummy message"),),
478
+ (
479
+ docker.errors.ContainerError("dummy container",
480
+ "dummy exit status",
481
+ "dummy command",
482
+ "dummy image",
483
+ "dummy stderr"),
484
+ ),
485
+ (docker.errors.APIError("dummy message"),),
486
+ )
487
+ @ddt.unpack
488
+ def test_docker_run_detached__with_exception_on_stop(self, exception):
489
+ with unittest.mock.patch("iker.common.utils.dockerutils.docker.DockerClient") as mock_docker_client:
490
+ def mock_containers_run_stop_valuer(*args, **kwargs):
491
+ raise exception
492
+
493
+ mock_docker_container = MockedDockerContainer("dummy_container",
494
+ status_callee=return_callee("dummy_status"),
495
+ wait_callee=return_callee({"dummy_key": "dummy_value"}),
496
+ logs_callee=return_callee("dummy log"),
497
+ stop_callee=return_callee(mock_containers_run_stop_valuer),
498
+ remove_callee=return_callee())
499
+ mock_docker_client.return_value.containers.run.return_value = mock_docker_container
500
+
501
+ result, log = docker_run_detached(mock_docker_client.return_value,
502
+ "dummy_image",
503
+ "dummy_container",
504
+ "dummy_command",
505
+ {"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
506
+ {"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
507
+ {"dummy.ip.address": "127.0.0.1"},
508
+ 1000,
509
+ dummy_kwarg="dummy_value")
510
+
511
+ self.assertEqual(result, {"dummy_key": "dummy_value"})
512
+ self.assertEqual(log, "dummy log")
513
+
514
+ mock_docker_client.return_value.containers.run.assert_called_with(
515
+ image="dummy_image",
516
+ name="dummy_container",
517
+ command="dummy_command",
518
+ volumes={"/dummy/src/path": {"bind": "/dummy/dst/path", "mode": "rw"}},
519
+ environment={"DUMMY_ENV_KEY": "DUMMY_ENV_VALUE"},
520
+ extra_hosts={"dummy.ip.address": "127.0.0.1"},
521
+ detach=True,
522
+ dummy_kwarg="dummy_value",
523
+ )
524
+ mock_docker_container.status_callee.assert_called_once()
525
+ mock_docker_container.wait_callee.assert_called_once_with()(timeout=1000)
526
+ mock_docker_container.wait_callee.assert_called_once_with()()
527
+ mock_docker_container.logs_callee.assert_called_once()
528
+ mock_docker_container.stop_callee.assert_called_once()
529
+ mock_docker_container.remove_callee.assert_called_once()