Skip to content

Commit 8f2349b

Browse files
Merge pull request #886 from jstourac/checkWorkbenchStartupLogs
RHOAIENG-18979: chore(test/containers): check workbench startup logs
2 parents c0c64e0 + 466b468 commit 8f2349b

File tree

1 file changed

+44
-9
lines changed

1 file changed

+44
-9
lines changed

tests/containers/workbenches/workbench_image_test.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
import os
77
import platform
8+
import time
89
import urllib.error
910
import urllib.request
1011

@@ -18,6 +19,7 @@
1819
import testcontainers.core.waiting_utils
1920

2021
import pytest
22+
import pytest_subtests
2123

2224
from tests.containers import docker_utils, podman_machine_utils
2325

@@ -31,7 +33,7 @@ class TestWorkbenchImage:
3133
# disable ipv6 https://danwalsh.livejournal.com/47118.html
3234
{"net.ipv6.conf.all.disable_ipv6": "1"}
3335
])
34-
def test_image_entrypoint_starts(self, image: str, sysctls) -> None:
36+
def test_image_entrypoint_starts(self, subtests: pytest_subtests.SubTests, image: str, sysctls) -> None:
3537
skip_if_not_workbench_image(image)
3638

3739
container = WorkbenchContainer(image=image, user=1000, group_add=[0],
@@ -40,17 +42,16 @@ def test_image_entrypoint_starts(self, image: str, sysctls) -> None:
4042
try:
4143
container.start()
4244
# check explicitly that we can connect to the ide running in the workbench
43-
container._connect()
45+
with subtests.test("Attempting to connect to the workbench..."):
46+
container._connect()
4447
finally:
4548
# try to grab logs regardless of whether container started or not
46-
stdout, stderr = container.get_logs()
47-
for line in stdout.splitlines() + stderr.splitlines():
48-
logging.debug(line)
49+
grab_and_check_logs(subtests, container)
4950
finally:
5051
docker_utils.NotebookContainer(container).stop(timeout=0)
5152

5253
@pytest.mark.skip(reason="RHOAIENG-17305: currently our Workbench images don't tolerate IPv6")
53-
def test_ipv6_only(self, image: str, test_frame):
54+
def test_ipv6_only(self, subtests: pytest_subtests.SubTests, image: str, test_frame):
5455
"""Test that workbench image is accessible via IPv6.
5556
Workarounds for macOS will be needed, so that's why it's a separate test."""
5657
skip_if_not_workbench_image(image)
@@ -103,9 +104,7 @@ def test_ipv6_only(self, image: str, test_frame):
103104
container._connect(container_host=host, container_port=port)
104105
finally:
105106
# try to grab logs regardless of whether container started or not
106-
stdout, stderr = container.get_logs()
107-
for line in stdout.splitlines() + stderr.splitlines():
108-
logging.debug(line)
107+
grab_and_check_logs(subtests, container)
109108
finally:
110109
docker_utils.NotebookContainer(container).stop(timeout=0)
111110

@@ -192,3 +191,39 @@ def skip_if_not_workbench_image(image: str) -> docker.models.images.Image:
192191
f"Image {image} does not have any of '{ide_server_label_fragments=} in {image_metadata.labels['name']=}'")
193192

194193
return image_metadata
194+
195+
def grab_and_check_logs(subtests: pytest_subtests.SubTests, container: WorkbenchContainer) -> None:
196+
# Here is a list of blocked keywords we don't want to see in the log messages during the container/workbench
197+
# startup (e.g. log messages from Jupyter IDE, code-server IDE or RStudio IDE).
198+
blocked_keywords = ["Error", "error", "Warning", "warning", "Failed", "failed", "[W ", "[E ", "Traceback"]
199+
# Here is a list of allowed messages that match some block keyword from the list above, but we allow them
200+
# for some reason.
201+
allowed_messages = [
202+
# We don't touch this - it should be fixed in the future by the package upgrade.
203+
"JupyterEventsVersionWarning: The `version` property of an event schema must be a string. It has been type coerced, but in a future version of this library, it will fail to validate.",
204+
# This is a message from our reverse proxy nginx caused by the fact that we attempt to connect to the code-server before it's actually running (container.start(wait_for_readiness=True)).
205+
"connect() failed (111: Connection refused) while connecting to upstream, client",
206+
]
207+
208+
# Let's wait couple of seconds to give a chance to log eventual extra startup messages just to be sure we don't
209+
# miss anytihng important in this test.
210+
time.sleep(3)
211+
212+
stdout, stderr = container.get_logs()
213+
full_logs = ""
214+
for line in stdout.splitlines() + stderr.splitlines():
215+
full_logs = "\n".join([full_logs, line.decode()])
216+
logging.debug(line.decode())
217+
218+
# let's check that logs don't contain any error or unexpected warning message
219+
with subtests.test("Checking the log in the workbench..."):
220+
failed_lines: list[str] = []
221+
for line in full_logs.splitlines():
222+
if any(keyword in line for keyword in blocked_keywords):
223+
if any(allowed in line for allowed in allowed_messages):
224+
logging.debug(f"Waived message: '{line}'")
225+
else:
226+
logging.error(f"Unexpected keyword in the following message: '{line}'")
227+
failed_lines.append(line)
228+
if len(failed_lines) > 0:
229+
pytest.fail(f"Log message(s) ({len(failed_lines)}) that violate our checks occurred during the workbench startup:\n{"\n".join(failed_lines)}")

0 commit comments

Comments
 (0)