Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline error message #380

Merged
merged 5 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/changes/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changes

* [2.0.1](changes_2.0.1.md)
* [2.0.0](changes_2.0.0.md)
* [1.7.1](changes_1.7.1.md)
* [1.7.0](changes_1.7.0.md)
Expand Down Expand Up @@ -29,6 +30,7 @@
---
hidden:
---
changes_2.0.1
changes_2.0.0
changes_1.7.1
changes_1.7.0
Expand Down
13 changes: 13 additions & 0 deletions doc/changes/changes_2.0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Unreleased

## Summary

### Supported Exasol Versions

* **7.1**: up to 7.1.17
* **8**: 8.18.1

## Internal

* #184: Streamlined error messages
* Added exasol-error-reporting library
47 changes: 27 additions & 20 deletions exasol_integration_test_docker_environment/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,54 @@
package and also provide help to find potential fixes.
"""
import sys
from typing import Iterable
from exasol import error
from enum import Enum
from typing import Iterator

import docker
from docker.errors import DockerException

SUPPORTED_PLATFORMS = ["linux", "darwin"]


class ErrorCodes(Enum):
"""The equivalent of ICD-10 codes this doctor is using"""
class Error(Enum):
Unknown = error.ExaError(
"E-ITDE-0",
"Unknown issue.",
["An unknown error occurred, please contact the maintainer."],
{}
)

Unknown = "Unknown issue"
UnixSocketNotAvailable = "Could not find unix socket to connect to"
TargetPlatformNotSupported = "The platform you are running on is not supported."
UnixSocketNotAvailable = error.ExaError(
"E-ITDE-1",
"Could not find unix socket to connect to.",
["Make sure environment variable DOCKER_HOST is configured correctly."],
{}
)

TargetPlatformNotSupported = error.ExaError(
"E-ITDE-2",
"The platform ITDE is running on is not supported.",
["Make sure you are using one of the following platforms: [linux, darwin]."],
{}
)

def recommend_mitigation(error_code) -> str:
"""Get treatment advice based on the error_code"""
return {
ErrorCodes.Unknown: "You are sick but this symptoms are unknown, please contact the maintainer.",
ErrorCodes.UnixSocketNotAvailable: "Make sure your DOCKER_HOST environment variable is configured correctly.",
ErrorCodes.TargetPlatformNotSupported: f"Make sure you are using one of the following platforms: {SUPPORTED_PLATFORMS}.",
}[error_code]


def diagnose_docker_daemon_not_available() -> Iterator[ErrorCodes]:
def diagnose_docker_daemon_not_available() -> Iterable[error.ExaError]:
"""Diagnose reasons why docker deamon is not available"""

def _is_unix_socket_issue(message: str) -> bool:
return "FileNotFoundError(2, 'No such file or directory')" in message

errors = set()
errors = list()
try:
_docker = docker.from_env()
except DockerException as ex:
msg = f"{ex}"
if _is_unix_socket_issue(msg):
errors.add(ErrorCodes.UnixSocketNotAvailable)
errors.append(Error.UnixSocketNotAvailable)
if len(errors) == 0:
errors.add(ErrorCodes.Unknown)
errors.append(Error.Unknown)
return errors


Expand All @@ -65,15 +72,15 @@ def is_supported_platform() -> bool:
return sys.platform in SUPPORTED_PLATFORMS


def health_checkup() -> Iterator[ErrorCodes]:
def health_checkup() -> Iterable[error.ExaError]:
"""
Runs all known examinations

return an iterator of error codes specifying which problems have been identified.
"""
examinations = [
(is_docker_daemon_available, diagnose_docker_daemon_not_available),
(is_supported_platform, lambda: ErrorCodes.TargetPlatformNotSupported),
(is_supported_platform, lambda: Error.TargetPlatformNotSupported),
]
for is_fine, diagnosis in examinations:
if not is_fine():
Expand Down
23 changes: 5 additions & 18 deletions exasol_integration_test_docker_environment/lib/api/health.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from inspect import cleandoc

from exasol_integration_test_docker_environment.doctor import health_checkup, recommend_mitigation
from exasol_integration_test_docker_environment.doctor import health_checkup
from exasol_integration_test_docker_environment.lib.api.api_errors import HealthProblem
from exasol_integration_test_docker_environment.lib.api.common import cli_function

Expand All @@ -17,31 +17,18 @@ def health():
:raises HealthProblem
"""

problems = set(health_checkup())
if not problems:
errors = set(health_checkup())
if not errors:
return

suggestion_template = cleandoc(
"""
* {problem}
Fix: {suggestion}
"""
)
message = cleandoc(
"""
{count} problem(s) have been identified.

{problems}
"""
).format(
count=len(problems),
problems="\n".join(
(
suggestion_template.format(
problem=icd.value, suggestion=recommend_mitigation(icd)
)
for icd in problems
)
),
count=len(errors),
problems="\n".join(f"{error.value}" for error in errors),
Nicoretti marked this conversation as resolved.
Show resolved Hide resolved
)
raise HealthProblem(message)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from exasol_integration_test_docker_environment.doctor import (
SUPPORTED_PLATFORMS,
ErrorCodes,
Error,
diagnose_docker_daemon_not_available,
is_docker_daemon_available,
is_supported_platform,
Expand Down Expand Up @@ -56,13 +56,13 @@ class DiagnoseDockerDaemonNotAvailable(unittest.TestCase):
"""

def test_non_existing_unix_socket(self):
expected = {ErrorCodes.UnixSocketNotAvailable}
expected = [Error.UnixSocketNotAvailable]
env = {"DOCKER_HOST": "unix:///var/non/existent/path"}
with temporary_env(env):
self.assertEqual(expected, diagnose_docker_daemon_not_available())

def test_unknown_error(self):
expected = {ErrorCodes.Unknown}
expected = [Error.Unknown]
env = {"DOCKER_HOST": "https://foobar"}
with temporary_env(env):
self.assertEqual(expected, diagnose_docker_daemon_not_available())
Expand Down
Loading
Loading