From 616e16c293ae544fe948528b485a6892c36bf0a6 Mon Sep 17 00:00:00 2001 From: Daniel Neilson <53624638+ddneilson@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:11:43 -0500 Subject: [PATCH] fix: handle case where BatchGetJobEntity returns no jobRunAsUser (#293) Problem: The jobRunAsUser response field of the JobDetailsEntity structure within a BatchGetJobEntity request is an optional field. This Worker Agent currently treats it as a required field; resulting in failed Sessions when the field is absent. Solution: Handle the case of missing the jobRunAsUser field in the response. It is a service invariant that this field is always be present when the Worker is within a CMF. When the Worker is running within an SMF, then the field may be optional; but, further, in this case the Agent will always be running with a local jobRunAsUser override. We fail Sessions when this invariant is violated. Signed-off-by: Daniel Neilson <53624638+ddneilson@users.noreply.github.com> --- src/deadline_worker_agent/api_models.py | 4 +- src/deadline_worker_agent/boto/shim.py | 1 + .../scheduler/scheduler.py | 147 +++++++++---- .../sessions/job_entities/job_details.py | 51 +++-- test/unit/scheduler/test_scheduler.py | 142 ++++++++++++- .../sessions/job_entities/test_job_details.py | 195 ++++-------------- .../job_entities/test_job_entities.py | 13 +- 7 files changed, 320 insertions(+), 233 deletions(-) diff --git a/src/deadline_worker_agent/api_models.py b/src/deadline_worker_agent/api_models.py index 17a10f8c..8d169d76 100644 --- a/src/deadline_worker_agent/api_models.py +++ b/src/deadline_worker_agent/api_models.py @@ -253,14 +253,14 @@ class WindowsUser(TypedDict): class JobRunAsUser(TypedDict): posix: NotRequired[PosixUser] windows: NotRequired[WindowsUser] - runAs: NotRequired[Literal["QUEUE_CONFIGURED_USER", "WORKER_AGENT_USER"]] + runAs: Literal["QUEUE_CONFIGURED_USER", "WORKER_AGENT_USER"] class JobDetailsData(JobDetailsIdentifierFields): jobAttachmentSettings: NotRequired[JobAttachmentQueueSettings] """The queue's job attachment settings""" - jobRunAsUser: JobRunAsUser + jobRunAsUser: NotRequired[JobRunAsUser] """The queue's info on how to run the job processes (ie. posix or windows user/group)""" logGroupName: str diff --git a/src/deadline_worker_agent/boto/shim.py b/src/deadline_worker_agent/boto/shim.py index cedacbaf..cd45b864 100644 --- a/src/deadline_worker_agent/boto/shim.py +++ b/src/deadline_worker_agent/boto/shim.py @@ -253,6 +253,7 @@ def batch_get_job_entity( }, "logGroupName": "/aws/deadline/queue-abc", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "job-user", "group": "job-group", diff --git a/src/deadline_worker_agent/scheduler/scheduler.py b/src/deadline_worker_agent/scheduler/scheduler.py index fd3e12ef..3be2b3e9 100644 --- a/src/deadline_worker_agent/scheduler/scheduler.py +++ b/src/deadline_worker_agent/scheduler/scheduler.py @@ -37,6 +37,7 @@ LogProvisioningError, SessionLogConfigurationParameters, ) +from ..sessions.job_entities.job_details import JobRunAsUser from ..api_models import ( AssignedSession, UpdateWorkerScheduleResponse, @@ -668,6 +669,98 @@ def _fail_all_actions( ) self._wakeup.set() + @staticmethod + def _determine_user_for_session( + *, + host_is_posix: bool, + job_run_as_user: Optional[JobRunAsUser], + job_run_as_user_override: JobsRunAsUserOverride, + queue_id: str, + job_id: str, + session_id: str, + ) -> Optional[SessionUser]: + # Called only in self._create_new_sessions() to determine what os_user the Session should + # run as. + # Raises a ValueError if an impossible situation arises and we need to fail the Session. + os_user: Optional[SessionUser] = None + if not job_run_as_user_override.run_as_agent: + if job_run_as_user_override.job_user is not None: + os_user = job_run_as_user_override.job_user + logger.info( + SessionLogEvent( + subtype=SessionLogEventSubtype.USER, + queue_id=queue_id, + job_id=job_id, + session_id=session_id, + user=os_user.user, + message="Running as host-configured override user.", + ) + ) + elif job_run_as_user is None: + # Terminal error. We need to fail the Session. + # This should *never* happen; it occuring would mean that a service invariant has + # been violated. + message = ( + "FATAL: Queue does not have a jobRunAsUser. This should not be possible. " + "Please report this to the service team." + ) + raise ValueError(message) + elif not job_run_as_user.is_worker_agent_user: + # If we do not have a job-user override & we're not explicitly running + # as the agent's user, then we *MUST* have a jobRunAsUser from the JobDetails. + # Reasons: + # 1) The service always allows service-managed Fleets to associate with + # a Queue. The SMF Worker Agent is *always* run with a local user override. + # 2) The service only allows a customer-managed Fleet to associate with a + # Queue if either: + # a) The jobRunAsUser is explicitly set to WORKER_AGENT_USER; or + # b) The jobRunAsUser is explicitly set to QUEUE_CONFIGURED_USER and + # a user has been defined for the CMF's OS Platform (Linux/MacOS Fleets must + # have a "posix" user; and Windows Fleets must have a "windows" user) + # 3) The service does not allow a Queue's jobRunAsUser to be updated if the constraint + # imposed by (2) above would be violated for one or more of that Queue's current QFAs. + if host_is_posix: + os_user = job_run_as_user.posix + else: + os_user = job_run_as_user.windows + if os_user is None: + # Terminal error. We need to fail the Session. + # This should *never* happen; it occuring would mean that a service invariant has + # been violated. + message = ( + "FATAL: Queue's jobRunAsUser does not define a QUEUE_CONFIGURED_USER for this platform. " + "Please report this to the service team." + ) + raise ValueError(message) + else: + logger.info( + SessionLogEvent( + subtype=SessionLogEventSubtype.USER, + queue_id=queue_id, + job_id=job_id, + session_id=session_id, + user=os_user.user, + message="Running as Queue's jobRunAsUser.", + ) + ) + if os_user is None: + try: + user_to_log = getpass.getuser() + except Exception: + # This is best-effort. If we cannot determine the user we will not log + user_to_log = "UNKNOWN" + logger.warning( + SessionLogEvent( + subtype=SessionLogEventSubtype.USER, + queue_id=queue_id, + job_id=job_id, + session_id=session_id, + user=user_to_log, + message="Running as the Worker Agent's user. This configuration is not recommended; please see the Security chapter of the User Guide.", + ) + ) + return os_user + def _create_new_sessions( self, *, @@ -842,52 +935,28 @@ def _create_new_sessions( queue.replace(actions=session_spec["sessionActions"]) os_user: Optional[SessionUser] = None - if not self._job_run_as_user_override.run_as_agent: - if self._job_run_as_user_override.job_user is not None: - os_user = self._job_run_as_user_override.job_user - logger.info( - SessionLogEvent( - subtype=SessionLogEventSubtype.USER, - queue_id=queue_id, - job_id=job_id, - session_id=new_session_id, - user=os_user.user, - message="Running as host-configured override user.", - ) - ) - elif job_details.job_run_as_user: - if os.name == "posix": - os_user = job_details.job_run_as_user.posix - else: - os_user = job_details.job_run_as_user.windows - if os_user is not None: - logger.info( - SessionLogEvent( - subtype=SessionLogEventSubtype.USER, - queue_id=queue_id, - job_id=job_id, - session_id=new_session_id, - user=os_user.user, - message="Running as Queue's jobRunAsUser.", - ) - ) - - if os_user is None: - try: - user_to_log = getpass.getuser() - except Exception: - # This is best-effort. If we cannot determine the user we will not log - user_to_log = "UNKNOWN" - logger.warning( + try: + os_user = self._determine_user_for_session( + host_is_posix=os.name == "posix", + job_run_as_user=job_details.job_run_as_user, + job_run_as_user_override=self._job_run_as_user_override, + queue_id=queue_id, + job_id=job_id, + session_id=new_session_id, + ) + except ValueError as e: + message = str(e) + self._fail_all_actions(session_spec, message) + logger.error( SessionLogEvent( subtype=SessionLogEventSubtype.USER, queue_id=queue_id, job_id=job_id, session_id=new_session_id, - user=user_to_log, - message="Running as the Worker Agent's user.", + message=message, ) ) + continue queue_credentials: QueueAwsCredentials | None = None asset_sync: AssetSync | None = None diff --git a/src/deadline_worker_agent/sessions/job_entities/job_details.py b/src/deadline_worker_agent/sessions/job_entities/job_details.py index eb23fb15..a7e032a0 100644 --- a/src/deadline_worker_agent/sessions/job_entities/job_details.py +++ b/src/deadline_worker_agent/sessions/job_entities/job_details.py @@ -91,33 +91,39 @@ def job_run_as_user_api_model_to_worker_agent( """Converts the 'JobRunAsUser' api model to the 'JobRunAsUser' dataclass expected by the Worker Agent. """ - if "runAs" in job_run_as_user_data and job_run_as_user_data["runAs"] == "WORKER_AGENT_USER": + # Only two options for "runAs": WORKER_AGENT_USER & QUEUE_CONFIGURED_USER + if job_run_as_user_data["runAs"] == "WORKER_AGENT_USER": job_run_as_user = JobRunAsUser(is_worker_agent_user=True) return job_run_as_user + # We have a QUEUE_CONFIGURED_USER, so extract the data for this platform. if os.name == "posix": - user = "" - group = "" - if job_run_as_user_posix := job_run_as_user_data.get("posix", None): - user = job_run_as_user_posix["user"] - group = job_run_as_user_posix["group"] - else: + job_run_as_user_posix = job_run_as_user_data.get("posix", None) + if job_run_as_user_posix is None: + # Note: This may happen in an SMF case as follows: + # Customer has a Windows-based CMF, and configures the QUEUE_CONFIGURED_USER + # for Windows, but also connects the Queue to a posix-based SMF. + # So, this would mean that we're in a posix-based SMF. Return None; the agent + # must have been started with a jobRunAsUser override. return None - if "runAs" not in job_run_as_user_data and not group and not user: - return None job_run_as_user = JobRunAsUser( posix=PosixSessionUser( - user=user, - group=group, + user=job_run_as_user_posix["user"], + group=job_run_as_user_posix["group"], ), ) else: - job_run_as_user_windows = job_run_as_user_data.get("windows", {}) - user = job_run_as_user_windows.get("user", "") - passwordArn = job_run_as_user_windows.get("passwordArn", "") - if not (user and passwordArn): + job_run_as_user_windows = job_run_as_user_data.get("windows", None) + if job_run_as_user_windows is None: + # Note: This may happen in an SMF case as follows: + # Customer has a posix-based CMF, and configures the QUEUE_CONFIGURED_USER + # for posix, but also connects the Queue to a Windows-based SMF. + # So, this would mean that we're in a Windows-based SMF. Return None; the agent + # must have been started with a jobRunAsUser override. return None + user = job_run_as_user_windows["user"] + passwordArn = job_run_as_user_windows["passwordArn"] job_run_as_user = JobRunAsUser( windows_settings=JobRunAsWindowsUser(user=user, passwordArn=passwordArn), ) @@ -238,9 +244,11 @@ def from_boto(cls, job_details_data: JobDetailsData) -> JobDetails: if job_attachment_settings_boto := job_details_data.get("jobAttachmentSettings", None): job_attachment_settings = JobAttachmentSettings.from_boto(job_attachment_settings_boto) - job_run_as_user_data = job_details_data["jobRunAsUser"] - job_run_as_user: JobRunAsUser | None = job_run_as_user_api_model_to_worker_agent( - job_run_as_user_data + job_run_as_user_data = job_details_data.get("jobRunAsUser", None) + job_run_as_user: JobRunAsUser | None = ( + job_run_as_user_api_model_to_worker_agent(job_run_as_user_data) + if job_run_as_user_data is not None + else None ) # Note: Record the empty string as a None as well. @@ -290,7 +298,6 @@ def validate_entity_data(cls, entity_data: dict[str, Any]) -> JobDetailsData: Field(key="jobId", expected_type=str, required=True), Field(key="logGroupName", expected_type=str, required=True), Field(key="schemaVersion", expected_type=str, required=True), - Field(key="osUser", expected_type=str, required=False), Field( key="parameters", expected_type=dict, @@ -304,7 +311,7 @@ def validate_entity_data(cls, entity_data: dict[str, Any]) -> JobDetailsData: Field( key="jobRunAsUser", expected_type=dict, - required=True, + required=False, fields=( Field( key="posix", @@ -318,7 +325,7 @@ def validate_entity_data(cls, entity_data: dict[str, Any]) -> JobDetailsData: Field( key="runAs", expected_type=str, - required=False, + required=True, ), Field( key="windows", @@ -367,7 +374,7 @@ def validate_entity_data(cls, entity_data: dict[str, Any]) -> JobDetailsData: ) # Validate jobRunAsUser -> runAs is one of ("QUEUE_CONFIGURED_USER" / "WORKER_AGENT_USER") - if run_as_value := entity_data["jobRunAsUser"].get("runAs", None): + if run_as_value := entity_data.get("jobRunAsUser", dict()).get("runAs", None): if run_as_value not in ("QUEUE_CONFIGURED_USER", "WORKER_AGENT_USER"): raise ValueError( f'Expected "jobRunAs" -> "runAs" to be one of "QUEUE_CONFIGURED_USER", "WORKER_AGENT_USER" but got "{run_as_value}"' diff --git a/test/unit/scheduler/test_scheduler.py b/test/unit/scheduler/test_scheduler.py index 9f4a4e24..30ff03e6 100644 --- a/test/unit/scheduler/test_scheduler.py +++ b/test/unit/scheduler/test_scheduler.py @@ -4,10 +4,10 @@ from datetime import timedelta from pathlib import Path -from typing import Generator +from typing import Generator, Optional from unittest.mock import ANY, MagicMock, Mock, call, patch -from openjd.sessions import ActionState, ActionStatus +from openjd.sessions import ActionState, ActionStatus, SessionUser from botocore.exceptions import ClientError import pytest import os @@ -953,6 +953,144 @@ def test_job_details_run_as_worker_agent_user_windows( assert action_update.start_time is None assert action_update.end_time is None + class MockSessionUser(SessionUser): + user: str + + def __init__(self, user) -> None: + self.user = user + + def __eq__(self, other) -> bool: + return self.user == other.user + + @staticmethod + def _get_process_user() -> str: + return "user" + + @pytest.mark.parametrize( + "host_is_posix,job_run_as_user,job_run_as_user_override,expected_result,expected_exception", + [ + pytest.param( + True, + JobRunAsUser( + posix=MockSessionUser("posix"), # type: ignore[arg-type] + windows=MockSessionUser("windows"), # type: ignore[arg-type] + windows_settings=None, + is_worker_agent_user=False, + ), + JobsRunAsUserOverride(run_as_agent=True, job_user=None), + None, + None, + id="Run as agent override", + ), + pytest.param( + True, + JobRunAsUser( + posix=MockSessionUser("posix"), # type: ignore[arg-type] + windows=MockSessionUser("windows"), # type: ignore[arg-type] + windows_settings=None, + is_worker_agent_user=False, + ), + JobsRunAsUserOverride(run_as_agent=False, job_user=MockSessionUser("override")), + MockSessionUser("override"), + None, + id="Override job user", + ), + pytest.param( + True, + None, + JobsRunAsUserOverride(run_as_agent=False, job_user=None), + None, + r"^FATAL: Queue does not have a jobRunAsUser\. .*", + id="Invariant violated: No override or queue user", + ), + pytest.param( + True, + JobRunAsUser( + posix=MockSessionUser("posix"), # type: ignore[arg-type] + windows=MockSessionUser("windows"), # type: ignore[arg-type] + windows_settings=None, + is_worker_agent_user=True, + ), + JobsRunAsUserOverride(run_as_agent=False, job_user=None), + None, + None, + id="Selects agent user", + ), + pytest.param( + True, + JobRunAsUser( + posix=MockSessionUser("posix"), # type: ignore[arg-type] + windows=MockSessionUser("windows"), # type: ignore[arg-type] + windows_settings=None, + is_worker_agent_user=False, + ), + JobsRunAsUserOverride(run_as_agent=False, job_user=None), + MockSessionUser("posix"), + None, + id="Selects posix user", + ), + pytest.param( + False, + JobRunAsUser( + posix=MockSessionUser("posix"), # type: ignore[arg-type] + windows=MockSessionUser("windows"), # type: ignore[arg-type] + windows_settings=None, + is_worker_agent_user=False, + ), + JobsRunAsUserOverride(run_as_agent=False, job_user=None), + MockSessionUser("windows"), + None, + id="Selects windows user", + ), + pytest.param( + True, + JobRunAsUser( + posix=None, + windows=None, + windows_settings=None, + is_worker_agent_user=False, + ), + JobsRunAsUserOverride(run_as_agent=False, job_user=None), + None, + r"^FATAL: Queue's jobRunAsUser does not define a QUEUE_CONFIGURED_USER for this platform\. .*", + id="Invariant violated: Missing platform-specific queue user", + ), + ], + ) + def test_determine_user_for_session( + self, + host_is_posix: bool, + job_run_as_user: Optional[JobRunAsUser], + job_run_as_user_override: JobsRunAsUserOverride, + expected_result: Optional[SessionUser], + expected_exception: Optional[str], + ) -> None: + + # WHEN + if expected_exception is not None: + with pytest.raises(ValueError, match=expected_exception): + WorkerScheduler._determine_user_for_session( + host_is_posix=host_is_posix, + job_run_as_user=job_run_as_user, + job_run_as_user_override=job_run_as_user_override, + queue_id="queue-1234", + job_id="job-1234", + session_id="session-1234", + ) + return + + result = WorkerScheduler._determine_user_for_session( + host_is_posix=host_is_posix, + job_run_as_user=job_run_as_user, + job_run_as_user_override=job_run_as_user_override, + queue_id="queue-1234", + job_id="job-1234", + session_id="session-1234", + ) + + # THEN + assert result == expected_result + class TestQueueAwsCredentialsManagement: """Tests that validate that we are constructing and destroying credentials objects diff --git a/test/unit/sessions/job_entities/test_job_details.py b/test/unit/sessions/job_entities/test_job_details.py index a714c5e3..822c8b30 100644 --- a/test/unit/sessions/job_entities/test_job_details.py +++ b/test/unit/sessions/job_entities/test_job_details.py @@ -66,84 +66,8 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "jobId": "job-0000", "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - }, - }, - id="only required fields - posix", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "windows": { - "user": "user1", - "passwordArn": "anarn", - }, - }, }, - id="only required fields - windows", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "posix": { - "user": "", - "group": "", - }, - }, - }, - id="only required fields, empty user", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "posix": { - "user": "", - "group": "", - }, - }, - }, - id="only required fields, empty user", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "posix": { - "user": "", - "group": "", - }, - }, - }, - id="only required fields, empty user", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": { - "posix": { - "user": "", - "group": "", - }, - }, - }, - id="only required fields, empty user", + id="only required fields", ), pytest.param( { @@ -158,12 +82,6 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "path": "param2value", }, }, - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - }, }, id="valid parameters", ), @@ -173,12 +91,6 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", "pathMappingRules": [], - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - }, }, id="valid pathMappingRules - empty list", ), @@ -194,12 +106,6 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "destinationPath": "/destination/path", }, ], - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - }, }, id="valid pathMappingRules", ), @@ -208,9 +114,11 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "jobId": "job-0000", "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", - "jobRunAsUser": {}, + "jobRunAsUser": { + "runAs": "WORKER_AGENT_USER", + }, }, - id="valid jobRunAsUser - empty dict", + id="valid agent user", ), pytest.param( { @@ -218,14 +126,17 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "user1", "group": "group1", }, - # (no "runAs" here) }, }, - id="valid old jobRunAsUser", + marks=pytest.mark.skipif( + os.name != "posix", reason="validation logic is platform-specific" + ), + id="valid new jobRunAsUser - posix only", ), pytest.param( { @@ -233,6 +144,25 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", + "windows": { + "user": "user1", + "passwordArn": "anarn", + }, + }, + }, + marks=pytest.mark.skipif( + os.name == "posix", reason="validation logic is platform-specific" + ), + id="valid new jobRunAsUser - windows only", + ), + pytest.param( + { + "jobId": "job-0000", + "logGroupName": "/aws/deadline/queue-0000", + "schemaVersion": "jobtemplate-0000-00", + "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "user1", "group": "group1", @@ -241,10 +171,9 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "user": "user1", "passwordArn": "anarn", }, - "runAs": "QUEUE_CONFIGURED_USER", }, }, - id="valid new jobRunAsUser", + id="valid new jobRunAsUser - all platforms", ), pytest.param( { @@ -255,12 +184,6 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "s3BucketName": "mybucket", "rootPrefix": "myprefix", }, - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - }, }, id="valid jobAttachmentSettings", ), @@ -269,7 +192,6 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: "jobId": "job-0000", "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-0000-00", - "osUser": "", "parameters": { "param1": { "string": "param1value", @@ -286,10 +208,15 @@ def job_details_only_run_as_worker_agent_user() -> JobDetails: }, ], "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "user1", "group": "group1", }, + "windows": { + "user": "user1", + "passwordArn": "anarn", + }, }, "jobAttachmentSettings": { "s3BucketName": "mybucket", @@ -315,6 +242,7 @@ def test_input_validation_success(data: dict[str, Any]) -> None: "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-2023-09", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "user1", "group": "group1", @@ -328,26 +256,6 @@ def test_input_validation_success(data: dict[str, Any]) -> None: "job_details_with_user", id="only required fields", ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-2023-09", - "jobRunAsUser": { - "posix": { - "user": "user1", - "group": "group1", - }, - "windows": { - "user": "user1", - "passwordArn": "anarn", - }, - "runAs": "QUEUE_CONFIGURED_USER", - }, - }, - "job_details_with_user", - id="required fields with runAs QUEUE_CONFIGURED_USER", - ), pytest.param( { "jobId": "job-0000", @@ -388,30 +296,9 @@ def test_input_validation_success(data: dict[str, Any]) -> None: "jobId": "job-0000", "logGroupName": "/aws/deadline/queue-0000", "schemaVersion": "jobtemplate-2023-09", - "jobRunAsUser": { - "posix": { - "user": "", - "group": "", - }, - }, - }, - "job_details_no_user", - id="required with empty posix user/group", - ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-2023-09", - "jobRunAsUser": { - "windows": { - "user": "", - "passwordArn": "", - }, - }, }, "job_details_no_user", - id="required with empty windows user", + id="required with no user", ), pytest.param( { @@ -673,14 +560,6 @@ def test_convert_job_user_from_boto(data: JobDetailsData, expected: JobDetails, }, id="nonvalid jobRunAsUser - not dict", ), - pytest.param( - { - "jobId": "job-0000", - "logGroupName": "/aws/deadline/queue-0000", - "schemaVersion": "jobtemplate-0000-00", - }, - id="missing jobRunAsUser", - ), pytest.param( { "jobId": "job-0000", diff --git a/test/unit/sessions/job_entities/test_job_entities.py b/test/unit/sessions/job_entities/test_job_entities.py index fbc4c866..d625044f 100644 --- a/test/unit/sessions/job_entities/test_job_entities.py +++ b/test/unit/sessions/job_entities/test_job_entities.py @@ -209,16 +209,6 @@ def test_has_path_mapping_rules( "jobId": job_id, "schemaVersion": "jobtemplate-2023-09", "logGroupName": "fake-name", - "jobRunAsUser": { - "posix": { - "user": "job-user", - "group": "job-group", - }, - "windows": { - "user": "job-user", - "passwordArn": "job-password-arn", - }, - }, }, ) response: BatchGetJobEntityResponse = { @@ -261,6 +251,7 @@ def test_job_run_as_user( api_response: dict = { "jobId": "job-123", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": expected_user, "group": expected_group, @@ -306,6 +297,7 @@ def test_job_details( "schemaVersion": "jobtemplate-2023-09", "logGroupName": "/aws/deadline/queue-0000", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "user", "group": "group", @@ -599,6 +591,7 @@ def test_cache_entities( "logGroupName": "/aws/service/loggroup", "schemaVersion": "jobtemplate-2023-09", "jobRunAsUser": { + "runAs": "QUEUE_CONFIGURED_USER", "posix": { "user": "job-user", "group": "job-group",