Skip to content

Commit 74768c4

Browse files
authoredFeb 18, 2025··
cherry-pick: Pull commits from release 5.5 (#726)
2 parents a4839cb + 514229f commit 74768c4

File tree

4 files changed

+68
-3
lines changed

4 files changed

+68
-3
lines changed
 

‎changes/agent/.gitignore

Whitespace-only changes.

‎changes/agent/722.fixed.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Updated the schema for slurm job data to handle slurm updates

‎jobbergate-agent/jobbergate_agent/jobbergate/schemas.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import List, Optional, TypedDict, TypeAlias
33

44
import pydantic
5-
from pydantic import ConfigDict
5+
from pydantic import ConfigDict, field_validator
66

77
from jobbergate_agent.jobbergate.constants import FileType, INFLUXDB_MEASUREMENT
88

@@ -76,9 +76,24 @@ class SlurmJobData(pydantic.BaseModel, extra="ignore"):
7676

7777
job_id: Optional[int] = None
7878
job_state: Optional[str] = None
79-
job_info: Optional[str] = None
79+
job_info: Optional[str] = "{}"
8080
state_reason: Optional[str] = None
8181

82+
@field_validator("job_state", mode="before")
83+
@classmethod
84+
def validate_job_state(cls, value: str | list[str] | None) -> str | None:
85+
"""
86+
Validate the job_state field.
87+
"""
88+
if value is None:
89+
return None
90+
91+
if isinstance(value, list):
92+
if len(value) != 1:
93+
raise ValueError("job_state does not have exactly one value.")
94+
return value[0]
95+
return value
96+
8297

8398
class InfluxDBMeasurementDict(TypedDict):
8499
"""

‎jobbergate-agent/tests/jobbergate/test_update.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
)
2525
from jobbergate_agent.jobbergate.constants import INFLUXDB_MEASUREMENT
2626
from jobbergate_agent.settings import SETTINGS
27-
from jobbergate_agent.utils.exception import JobbergateApiError, JobbergateAgentError
27+
from jobbergate_agent.utils.exception import JobbergateApiError, JobbergateAgentError, SbatchError
2828

2929

3030
@pytest.fixture()
@@ -84,6 +84,55 @@ async def test_fetch_job_data__success():
8484
)
8585

8686

87+
@pytest.mark.asyncio
88+
@pytest.mark.usefixtures("mock_access_token")
89+
async def test_fetch_job_data__handles_list_in_job_state():
90+
"""
91+
Test that the ``fetch_job_data()`` function can successfully retrieve
92+
job data from Slurm as a ``SlurmJobData`` when the job_state from slurm
93+
is reported as a list.
94+
"""
95+
mocked_sbatch = mock.MagicMock()
96+
mocked_sbatch.get_job_info.return_value = dict(
97+
job_state=["FAILED"],
98+
job_id=123,
99+
state_reason="NonZeroExitCode",
100+
foo="bar",
101+
)
102+
103+
result: SlurmJobData = await fetch_job_data(123, mocked_sbatch)
104+
105+
assert result.job_id == 123
106+
assert result.job_state == "FAILED"
107+
assert result.state_reason == "NonZeroExitCode"
108+
assert result.job_info is not None
109+
assert json.loads(result.job_info) == dict(
110+
job_state=["FAILED"],
111+
job_id=123,
112+
state_reason="NonZeroExitCode",
113+
foo="bar",
114+
)
115+
116+
117+
@pytest.mark.asyncio
118+
@pytest.mark.usefixtures("mock_access_token")
119+
async def test_fetch_job_data__raises_error_if_job_state_is_invalid_list():
120+
"""
121+
Test that the ``fetch_job_data()`` function raises an exception
122+
if the list slurm_job_state does not have exactly one value.
123+
"""
124+
mocked_sbatch = mock.MagicMock()
125+
mocked_sbatch.get_job_info.return_value = dict(
126+
job_state=[],
127+
job_id=123,
128+
state_reason="NonZeroExitCode",
129+
foo="bar",
130+
)
131+
132+
with pytest.raises(SbatchError, match="does not have exactly one value"):
133+
await fetch_job_data(123, mocked_sbatch)
134+
135+
87136
@pytest.mark.asyncio
88137
@pytest.mark.usefixtures("mock_access_token")
89138
async def test_fetch_job_data__reports_status_as_UNKOWN_if_slurm_job_id_is_not_found():

0 commit comments

Comments
 (0)
Please sign in to comment.