From 569af3b8be23cc09386631f472fd8bfffa4c6315 Mon Sep 17 00:00:00 2001 From: Stephen Crowe Date: Thu, 1 Aug 2024 15:36:00 -0500 Subject: [PATCH] feat: support --submitter-name option for bundle GUI submitter command (#416) * feat: support --submitter-name option for bundle submitter commands Signed-off-by: Stephen Crowe --- src/deadline/client/api/_submit_job_bundle.py | 3 +- .../client/cli/_groups/bundle_group.py | 18 ++++++++-- .../dialogs/submit_job_to_deadline_dialog.py | 19 ++++++----- .../client/ui/job_bundle_submitter.py | 8 ++++- .../deadline_client/cli/test_cli_bundle.py | 34 ++++++++++++++++++- 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/deadline/client/api/_submit_job_bundle.py b/src/deadline/client/api/_submit_job_bundle.py index 592a1e0a..4fa3e094 100644 --- a/src/deadline/client/api/_submit_job_bundle.py +++ b/src/deadline/client/api/_submit_job_bundle.py @@ -65,6 +65,7 @@ def create_job_from_job_bundle( upload_progress_callback: Optional[Callable[[ProgressReportMetadata], bool]] = None, create_job_result_callback: Optional[Callable[[], bool]] = None, require_paths_exist: bool = False, + submitter_name: str = "CLI", ) -> Union[str, None]: """ Creates a job in the AWS Deadline Cloud farm/queue configured as default for the @@ -310,7 +311,7 @@ def create_job_from_job_bundle( api.get_deadline_cloud_library_telemetry_client().record_event( event_type="com.amazon.rum.deadline.submission", - event_details={}, + event_details={"submitter_name": submitter_name}, ) create_job_response = deadline.create_job(**create_job_args) diff --git a/src/deadline/client/cli/_groups/bundle_group.py b/src/deadline/client/cli/_groups/bundle_group.py index 919e5469..a920dc5c 100644 --- a/src/deadline/client/cli/_groups/bundle_group.py +++ b/src/deadline/client/cli/_groups/bundle_group.py @@ -107,6 +107,11 @@ def validate_parameters(ctx, param, value): is_flag=True, help="Require all input paths to exist", ) +@click.option( + "--submitter-name", + type=click.STRING, + help="Name of the application submitting the bundle.", +) @click.argument("job_bundle_dir") @_handle_error def bundle_submit( @@ -119,6 +124,7 @@ def bundle_submit( max_failed_tasks_count, max_retries_per_task, require_paths_exist, + submitter_name, **args, ): """ @@ -199,6 +205,7 @@ def _decide_cancel_submission(upload_group: AssetUploadGroup) -> bool: print_function_callback=click.echo, decide_cancel_submission_callback=_decide_cancel_submission, require_paths_exist=require_paths_exist, + submitter_name=submitter_name, ) # Check Whether the CLI options are modifying any of the default settings that affect @@ -256,6 +263,11 @@ def _decide_cancel_submission(upload_group: AssetUploadGroup) -> bool: is_flag=True, help="Installs GUI dependencies if they are not installed already", ) +@click.option( + "--submitter-name", + type=click.STRING, + help="Name of the application submitting the bundle. If a name is specified, the GUI will automatically close after submitting the job.", +) @click.option( "--output", type=click.Choice( @@ -269,7 +281,7 @@ def _decide_cancel_submission(upload_group: AssetUploadGroup) -> bool: "parsed/consumed by custom scripts.", ) @_handle_error -def bundle_gui_submit(job_bundle_dir, browse, output, install_gui, **args): +def bundle_gui_submit(job_bundle_dir, browse, output, install_gui, submitter_name, **args): """ Opens GUI to submit an Open Job Description job bundle to AWS Deadline Cloud. """ @@ -284,7 +296,9 @@ def bundle_gui_submit(job_bundle_dir, browse, output, install_gui, **args): ) output = output.lower() - submitter = show_job_bundle_submitter(input_job_bundle_dir=job_bundle_dir, browse=browse) + submitter = show_job_bundle_submitter( + input_job_bundle_dir=job_bundle_dir, browse=browse, submitter_name=submitter_name + ) if not submitter: return diff --git a/src/deadline/client/ui/dialogs/submit_job_to_deadline_dialog.py b/src/deadline/client/ui/dialogs/submit_job_to_deadline_dialog.py index 6e4644bc..61b8d0a3 100644 --- a/src/deadline/client/ui/dialogs/submit_job_to_deadline_dialog.py +++ b/src/deadline/client/ui/dialogs/submit_job_to_deadline_dialog.py @@ -71,6 +71,7 @@ class SubmitJobToDeadlineDialog(QDialog): f: Qt Window Flags show_host_requirements_tab: Display the host requirements tab in dialog if set to True. Default to False. + submitter_name: Override the default submitter_name value """ def __init__( @@ -85,6 +86,7 @@ def __init__( parent=None, f=Qt.WindowFlags(), show_host_requirements_tab=False, + submitter_name: Optional[str] = None, ): # The Qt.Tool flag makes sure our widget stays in front of the main application window super().__init__(parent=parent, f=f) @@ -92,6 +94,7 @@ def __init__( self.setMinimumSize(400, 400) self.job_settings_type = type(initial_job_settings) + self.submitter_name = submitter_name or self.job_settings_type().submitter_name self.on_create_job_bundle_callback = on_create_job_bundle_callback self.create_job_response: Optional[Dict[str, Any]] = None self.job_history_bundle_dir: Optional[str] = None @@ -341,7 +344,7 @@ def on_export_bundle(self): # Save the bundle try: self.job_history_bundle_dir = create_job_history_bundle_dir( - settings.submitter_name, settings.name + self.submitter_name, settings.name ) if self.show_host_requirements_tab: @@ -372,7 +375,7 @@ def on_export_bundle(self): os.startfile(self.job_history_bundle_dir) QMessageBox.information( self, - f"{settings.submitter_name} job submission", + f"{self.submitter_name} job submission", f"Saved the submission as a job bundle:\n{self.job_history_bundle_dir}", ) # Close the submitter window to signal the submission is done @@ -380,7 +383,7 @@ def on_export_bundle(self): except Exception as exc: logger.exception("Error saving bundle") message = str(exc) - QMessageBox.warning(self, f"{settings.submitter_name} job submission", message) + QMessageBox.warning(self, f"{self.submitter_name} job submission", message) def on_submit(self): """ @@ -407,7 +410,7 @@ def on_submit(self): deadline = api.get_boto3_client("deadline") self.job_history_bundle_dir = create_job_history_bundle_dir( - settings.submitter_name, settings.name + self.submitter_name, settings.name ) if self.show_host_requirements_tab: @@ -465,7 +468,7 @@ def on_submit(self): api.get_deadline_cloud_library_telemetry_client().record_event( event_type="com.amazon.rum.deadline.submission", event_details={ - "submitter_name": settings.submitter_name, + "submitter_name": self.submitter_name, }, from_gui=True, ) @@ -483,7 +486,7 @@ def on_submit(self): ) except UserInitiatedCancel as uic: logger.info("Canceling submission.") - QMessageBox.information(self, f"{settings.submitter_name} job submission", str(uic)) + QMessageBox.information(self, f"{self.submitter_name} job submission", str(uic)) job_progress_dialog.close() except Exception as exc: logger.exception("error submitting job") @@ -492,11 +495,11 @@ def on_submit(self): exception_type=str(type(exc)), from_gui=True, ) - QMessageBox.warning(self, f"{settings.submitter_name} job submission", str(exc)) + QMessageBox.warning(self, f"{self.submitter_name} job submission", str(exc)) job_progress_dialog.close() if self.create_job_response: # Close the submitter window to signal the submission is done but # keep the standalone gui submitter open - if settings.submitter_name != "JobBundle": + if self.submitter_name != "JobBundle": self.close() diff --git a/src/deadline/client/ui/job_bundle_submitter.py b/src/deadline/client/ui/job_bundle_submitter.py index 7654f98f..78f8b944 100644 --- a/src/deadline/client/ui/job_bundle_submitter.py +++ b/src/deadline/client/ui/job_bundle_submitter.py @@ -38,7 +38,12 @@ def show_job_bundle_submitter( - *, input_job_bundle_dir: str = "", browse: bool = False, parent=None, f=Qt.WindowFlags() + *, + input_job_bundle_dir: str = "", + browse: bool = False, + parent=None, + f=Qt.WindowFlags(), + submitter_name="JobBundle", ) -> Optional[SubmitJobToDeadlineDialog]: """ Opens an AWS Deadline Cloud job submission dialog for the provided job bundle. @@ -177,6 +182,7 @@ def on_create_job_bundle_callback( on_create_job_bundle_callback=on_create_job_bundle_callback, parent=parent, f=f, + submitter_name=submitter_name, ) submitter_dialog.show() return submitter_dialog diff --git a/test/unit/deadline_client/cli/test_cli_bundle.py b/test/unit/deadline_client/cli/test_cli_bundle.py index 970c4455..77e06620 100644 --- a/test/unit/deadline_client/cli/test_cli_bundle.py +++ b/test/unit/deadline_client/cli/test_cli_bundle.py @@ -4,6 +4,7 @@ Tests for the CLI job bundle commands. """ import os +import sys import tempfile import json from unittest.mock import ANY, patch, Mock @@ -399,7 +400,11 @@ def test_cli_bundle_job_parameter_from_cli(fresh_deadline_config): Verify that job parameters specified at the CLI are passed to the CreateJob call """ # Use a temporary directory for the job bundle - with tempfile.TemporaryDirectory() as tmpdir, patch.object(boto3, "Session") as session_mock: + with tempfile.TemporaryDirectory() as tmpdir, patch.object( + boto3, "Session" + ) as session_mock, patch.object( + bundle_group.api, "get_deadline_cloud_library_telemetry_client" + ) as telemetry_mock: session_mock().client("deadline").create_job.return_value = MOCK_CREATE_JOB_RESPONSE session_mock().client("deadline").get_job.return_value = MOCK_GET_JOB_RESPONSE session_mock.reset_mock() @@ -425,6 +430,8 @@ def test_cli_bundle_job_parameter_from_cli(fresh_deadline_config): "priority=90", "--priority", "45", + "--submitter-name", + "MyDCC", ], ) @@ -440,6 +447,11 @@ def test_cli_bundle_job_parameter_from_cli(fresh_deadline_config): priority=45, ) + telemetry_mock.return_value.record_event.assert_any_call( + event_type="com.amazon.rum.deadline.submission", + event_details={"submitter_name": "MyDCC"}, + ) + assert result.exit_code == 0 @@ -750,3 +762,23 @@ def test_cli_bundle_reject_upload_confirmation(fresh_deadline_config, temp_job_b upload_attachments_mock.assert_not_called() assert result.exit_code == 0 + + +@patch("deadline.client.ui.gui_context_for_cli") +def test_gui_submit_submitter_name(_mock_context): + """ + Verify that the --submitter-name arg gets passed through correctly + """ + + # Unconventional mocking pattern because of how the function is imported in code + mock_job_bundle_submitter = Mock() + sys.modules["deadline.client.ui.job_bundle_submitter"] = mock_job_bundle_submitter + mock_job_bundle_submitter.show_job_bundle_submitter + + runner = CliRunner() + runner.invoke( + main, + ["bundle", "gui-submit", "--browse", "--submitter-name", "MyDCC"], + ) + _args, kwargs = mock_job_bundle_submitter.show_job_bundle_submitter.call_args + assert kwargs["submitter_name"] == "MyDCC"