-
Notifications
You must be signed in to change notification settings - Fork 137
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Airflow operator - raise structured exceptions and retrieve job termi…
…nation reason Co-authored-by: Martynas Asipauskas <[email protected]>
- Loading branch information
1 parent
39ea0d3
commit 7313fb8
Showing
6 changed files
with
122 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from airflow.exceptions import AirflowException | ||
|
||
from armada_client.typings import JobState | ||
|
||
|
||
class ArmadaOperatorJobFailedError(AirflowException): | ||
""" | ||
Raised when an ArmadaOperator job has terminated unsuccessfully on Armada. | ||
:param job_id: The unique identifier of the job. | ||
:type job_id: str | ||
:param queue: The queue the job was submitted to. | ||
:type queue: str | ||
:param state: The termination state of the job. | ||
:type state: TerminationState | ||
:param reason: The termination reason, if provided. | ||
:type reason: str | ||
""" | ||
|
||
def __init__(self, queue: str, job_id: str, state: JobState, reason: str = ""): | ||
self.job_id = job_id | ||
self.queue = queue | ||
self.state = state | ||
self.reason = reason | ||
self.message = self._generate_message() | ||
super().__init__(self.message) | ||
|
||
def _generate_message(self) -> str: | ||
""" | ||
Generate a user-friendly error message. | ||
:return: Formatted error message with job details. | ||
:rtype: str | ||
""" | ||
message = ( | ||
f"ArmadaOperator job '{self.job_id}' in queue '{self.queue}'" | ||
f" terminated with state '{self.state.name.capitalize()}'." | ||
) | ||
if self.reason: | ||
message += f" Termination reason: {self.reason}" | ||
return message | ||
|
||
def __str__(self) -> str: | ||
""" | ||
Return the error message when the exception is converted to a string. | ||
:return: The error message. | ||
:rtype: str | ||
""" | ||
return self.message |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ readme='README.md' | |
authors = [{name = "Armada-GROSS", email = "[email protected]"}] | ||
license = { text = "Apache Software License" } | ||
dependencies=[ | ||
'armada-client>=0.4.6', | ||
'armada-client>=0.4.7', | ||
'apache-airflow>=2.6.3', | ||
'types-protobuf==4.24.0.1', | ||
'kubernetes>=23.6.0', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import pytest | ||
from armada_client.typings import JobState | ||
from armada.operators.errors import ArmadaOperatorJobFailedError | ||
|
||
|
||
def test_constructor(): | ||
job_id = "test-job" | ||
queue = "default-queue" | ||
state = JobState.FAILED | ||
reason = "Out of memory" | ||
|
||
error = ArmadaOperatorJobFailedError(queue, job_id, state, reason) | ||
|
||
assert error.job_id == job_id | ||
assert error.queue == queue | ||
assert error.state == state | ||
assert error.reason == reason | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"reason,expected_message", | ||
[ | ||
( | ||
"", | ||
"ArmadaOperator job 'test-job' in queue 'default-queue' terminated " | ||
"with state 'Failed'.", | ||
), | ||
( | ||
"Out of memory", | ||
"ArmadaOperator job 'test-job' in queue 'default-queue' terminated " | ||
"with state 'Failed'. Termination reason: Out of memory", | ||
), | ||
], | ||
) | ||
def test_message(reason: str, expected_message: str): | ||
error = ArmadaOperatorJobFailedError( | ||
"default-queue", "test-job", JobState.FAILED, reason | ||
) | ||
assert str(error) == expected_message |