blob: eefb8f923c4c528af46add2c2e1387fc2c6cd82b [file] [log] [blame]
Giorgi Lekveishvili285ab622023-11-22 13:50:45 +04001# pylint: disable=W0613, W0212
2
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import argparse
18import getpass
19import os
20import sys
21
22from pathlib import Path
23
24import docker
25import pygit2 as git
26import pytest
27
28sys.path.append(os.path.join(os.path.dirname(__file__), "helpers"))
29
30# pylint: disable=C0103
31pytest_plugins = ["fixtures.credentials", "fixtures.cluster", "fixtures.helm.gerrit"]
32
33# Base images that are not published and thus only tagged with "latest"
34BASE_IMGS = ["base", "gerrit-base"]
35
36
37# pylint: disable=W0622
38class PasswordPromptAction(argparse.Action):
39 def __init__(
40 self,
41 option_strings,
42 dest=None,
43 nargs=0,
44 default=None,
45 required=False,
46 type=None,
47 metavar=None,
48 help=None,
49 ):
50 super().__init__(
51 option_strings=option_strings,
52 dest=dest,
53 nargs=nargs,
54 default=default,
55 required=required,
56 metavar=metavar,
57 type=type,
58 help=help,
59 )
60
61 def __call__(self, parser, args, values, option_string=None):
62 password = getpass.getpass()
63 setattr(args, self.dest, password)
64
65
66def pytest_addoption(parser):
67 parser.addoption(
68 "--registry",
69 action="store",
70 default="",
71 help="Container registry to push (if --push=true) and pull container images"
72 + "from for tests on Kubernetes clusters (default: '')",
73 )
74 parser.addoption(
75 "--registry-user",
76 action="store",
77 default="",
78 help="Username for container registry (default: '')",
79 )
80 parser.addoption(
81 "--registry-pwd",
82 action="store",
83 default="",
84 help="Password for container registry (default: '')",
85 )
86 parser.addoption(
87 "--org",
88 action="store",
89 default="k8sgerrit",
90 help="Docker organization (default: 'k8sgerrit')",
91 )
92 parser.addoption(
93 "--push",
94 action="store_true",
95 help="If set, the docker images will be pushed to the registry configured"
96 + "by --registry (default: false)",
97 )
98 parser.addoption(
99 "--tag",
100 action="store",
101 default=None,
102 help="Tag of cached container images to test. Missing images will be built."
103 + "(default: All container images will be built)",
104 )
105 parser.addoption(
106 "--build-cache",
107 action="store_true",
108 help="If set, the docker cache will be used when building container images.",
109 )
110 parser.addoption(
111 "--kubeconfig",
112 action="store",
113 default=None,
114 help="Kubeconfig to use for cluster connection. If none is given the currently"
115 + "configured context is used.",
116 )
117 parser.addoption(
118 "--rwm-storageclass",
119 action="store",
120 default="shared-storage",
121 help="Name of the storageclass used for ReadWriteMany access."
122 + "(default: shared-storage)",
123 )
124 parser.addoption(
125 "--ingress-url",
126 action="store",
127 default=None,
128 help="URL of the ingress domain used by the cluster.",
129 )
130 parser.addoption(
131 "--gerrit-user",
132 action="store",
133 default="admin",
134 help="Gerrit admin username to be used for smoke tests. (default: admin)",
135 )
136 parser.addoption(
137 "--gerrit-pwd",
138 action=PasswordPromptAction,
139 default="secret",
140 help="Gerrit admin password to be used for smoke tests. (default: secret)",
141 )
142 parser.addoption(
143 "--skip-slow", action="store_true", help="If set, skip slow tests."
144 )
145
146
147def pytest_collection_modifyitems(config, items):
148 if config.getoption("--skip-slow"):
149 skip_slow = pytest.mark.skip(reason="--skip-slow was set.")
150 for item in items:
151 if "slow" in item.keywords:
152 item.add_marker(skip_slow)
153
154
155def pytest_runtest_makereport(item, call):
156 if "incremental" in item.keywords:
157 if call.excinfo is not None:
158 parent = item.parent
159 parent._previousfailed = item
160
161
162def pytest_runtest_setup(item):
163 if "incremental" in item.keywords:
164 previousfailed = getattr(item.parent, "_previousfailed", None)
165 if previousfailed is not None:
166 pytest.xfail(f"previous test failed ({previousfailed.name})")
167
168
169@pytest.fixture(scope="session")
170def tag_of_cached_container(request):
171 return request.config.getoption("--tag")
172
173
174@pytest.fixture(scope="session")
175def docker_client():
176 return docker.from_env()
177
178
179@pytest.fixture(scope="session")
180def repository_root():
181 return Path(git.discover_repository(os.path.realpath(__file__))).parent.absolute()
182
183
184@pytest.fixture(scope="session")
185def container_images(repository_root):
186 image_paths = {}
187 for directory in os.listdir(os.path.join(repository_root, "container-images")):
188 image_paths[directory] = os.path.join(
189 repository_root, "container-images", directory
190 )
191 return image_paths
192
193
194@pytest.fixture(scope="session")
195def docker_registry(request):
196 registry = request.config.getoption("--registry")
197 if registry and not registry[-1] == "/":
198 registry += "/"
199 return registry
200
201
202@pytest.fixture(scope="session")
203def docker_org(request):
204 org = request.config.getoption("--org")
205 if org and not org[-1] == "/":
206 org += "/"
207 return org
208
209
210@pytest.fixture(scope="session")
211def docker_tag(tag_of_cached_container, repository_root):
212 if tag_of_cached_container:
213 return tag_of_cached_container
214 return git.Repository(repository_root).describe(dirty_suffix="-dirty")
215
216
217@pytest.fixture(scope="session")
218def docker_build(
219 request,
220 docker_client,
221 tag_of_cached_container,
222 docker_registry,
223 docker_org,
224 docker_tag,
225):
226 def docker_build(image, name):
227 if name in BASE_IMGS:
228 image_name = f"{name}:latest"
229 else:
230 image_name = f"{docker_registry}{docker_org}{name}:{docker_tag}"
231
232 if tag_of_cached_container:
233 try:
234 return docker_client.images.get(image_name)
235 except docker.errors.ImageNotFound:
236 print(f"Image {image_name} could not be loaded. Building it now.")
237
238 no_cache = not request.config.getoption("--build-cache")
239
240 build = docker_client.images.build(
241 path=image,
242 nocache=no_cache,
243 rm=True,
244 tag=image_name,
245 platform="linux/amd64",
246 )
247 return build[0]
248
249 return docker_build
250
251
252@pytest.fixture(scope="session")
253def docker_login(request, docker_client, docker_registry):
254 username = request.config.getoption("--registry-user")
255 if username:
256 docker_client.login(
257 username=username,
258 password=request.config.getoption("--registry-pwd"),
259 registry=docker_registry,
260 )
261
262
263@pytest.fixture(scope="session")
264def docker_push(
265 request, docker_client, docker_registry, docker_login, docker_org, docker_tag
266):
267 def docker_push(image):
268 docker_repository = f"{docker_registry}{docker_org}{image}"
269 docker_client.images.push(docker_repository, tag=docker_tag)
270
271 return docker_push
272
273
274@pytest.fixture(scope="session")
275def docker_network(request, docker_client):
276 network = docker_client.networks.create(
277 name="k8sgerrit-test-network", scope="local"
278 )
279
280 yield network
281
282 network.remove()
283
284
285@pytest.fixture(scope="session")
286def base_image(container_images, docker_build):
287 return docker_build(container_images["base"], "base")
288
289
290@pytest.fixture(scope="session")
291def gerrit_base_image(container_images, docker_build, base_image):
292 return docker_build(container_images["gerrit-base"], "gerrit-base")
293
294
295@pytest.fixture(scope="session")
296def gitgc_image(request, container_images, docker_build, docker_push, base_image):
297 gitgc_image = docker_build(container_images["git-gc"], "git-gc")
298 if request.config.getoption("--push"):
299 docker_push("git-gc")
300 return gitgc_image
301
302
303@pytest.fixture(scope="session")
304def apache_git_http_backend_image(
305 request, container_images, docker_build, docker_push, base_image
306):
307 apache_git_http_backend_image = docker_build(
308 container_images["apache-git-http-backend"], "apache-git-http-backend"
309 )
310 if request.config.getoption("--push"):
311 docker_push("apache-git-http-backend")
312 return apache_git_http_backend_image
313
314
315@pytest.fixture(scope="session")
316def gerrit_image(
317 request, container_images, docker_build, docker_push, base_image, gerrit_base_image
318):
319 gerrit_image = docker_build(container_images["gerrit"], "gerrit")
320 if request.config.getoption("--push"):
321 docker_push("gerrit")
322 return gerrit_image
323
324
325@pytest.fixture(scope="session")
326def gerrit_init_image(
327 request, container_images, docker_build, docker_push, base_image, gerrit_base_image
328):
329 gerrit_init_image = docker_build(container_images["gerrit-init"], "gerrit-init")
330 if request.config.getoption("--push"):
331 docker_push("gerrit-init")
332 return gerrit_init_image
333
334
335@pytest.fixture(scope="session")
336def required_plugins(request):
337 return ["healthcheck"]