Skip to content

Commit

Permalink
feat: support JSON output in bundle GUI submitter (#357)
Browse files Browse the repository at this point in the history
* feat: support JSON output in bundle GUI submitter

Signed-off-by: Stephen Crowe <crowest@amazon.com>
  • Loading branch information
crowecawcaw authored Jun 24, 2024
1 parent 59ab8a2 commit aad9a49
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 3 deletions.
71 changes: 68 additions & 3 deletions src/deadline/client/cli/_groups/bundle_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"""
from __future__ import annotations

import json
import logging
import re
from typing import Any, Dict, Optional

import click
from contextlib import ExitStack
Expand Down Expand Up @@ -249,8 +251,25 @@ def _decide_cancel_submission(upload_group: AssetUploadGroup) -> bool:
is_flag=True,
help="Allows user to choose Bundle and adds a 'Load a different job bundle' option to the Job-Specific Settings UI",
)
@click.option(
"--output",
type=click.Choice(
["verbose", "json"],
case_sensitive=False,
),
default="verbose",
help="Specifies the output format of the messages printed to stdout.\n"
"VERBOSE: Displays messages in a human-readable text format.\n"
"JSON: Displays messages in JSON line format, so that the info can be easily "
"parsed/consumed by custom scripts.",
)
@click.option(
"--extra-info",
is_flag=True,
help="Returns additional information about the submitted job. Only valid with JSON output.",
)
@_handle_error
def bundle_gui_submit(job_bundle_dir, browse, **args):
def bundle_gui_submit(job_bundle_dir, browse, output, extra_info, **args):
"""
Opens GUI to submit an Open Job Description job bundle to AWS Deadline Cloud.
"""
Expand All @@ -263,6 +282,11 @@ def bundle_gui_submit(job_bundle_dir, browse, **args):
raise DeadlineOperationError(
"Specify a job bundle directory or run the bundle command with the --browse flag"
)
output = output.lower()
if output != "json" and extra_info:
raise DeadlineOperationError(
"--extra-info is only availalbe with JSON output. Add the --output JSON option."
)

submitter = show_job_bundle_submitter(input_job_bundle_dir=job_bundle_dir, browse=browse)

Expand All @@ -276,10 +300,51 @@ def bundle_gui_submit(job_bundle_dir, browse, **args):
response = None
if submitter:
response = submitter.create_job_response
if response:

_print_response(
output=output,
extra_info=extra_info,
submitted=True if response else False,
job_bundle_dir=job_bundle_dir,
job_id=response["jobId"] if response else None,
parameter_values=submitter.parameter_values,
asset_references=submitter.job_attachments.get_asset_references().to_dict()[
"assetReferences"
],
)


def _print_response(
output: str,
extra_info: bool,
submitted: bool,
job_bundle_dir: str,
job_id: Optional[str],
parameter_values: Optional[list[Dict[str, Any]]],
asset_references: Dict[str, Any],
):
if output == "json":
if submitted:
response: dict[str, Any] = {
"status": "SUBMITTED",
"jobId": job_id,
"jobBundleDirectory": job_bundle_dir,
}
if extra_info:
response.update(
{
"parameterValues": parameter_values,
"assetReferences": asset_references,
}
)
click.echo(json.dumps(response))
else:
click.echo(json.dumps({"status": "CANCELED"}))
else:
if submitted:
click.echo("Submitted job bundle:")
click.echo(f" {job_bundle_dir}")
click.echo(f"Job ID: {response['jobId']}")
click.echo(f"Job ID: {job_id}")
else:
click.echo("Job submission canceled.")

Expand Down
14 changes: 14 additions & 0 deletions src/deadline/client/ui/dialogs/submit_job_to_deadline_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def __init__(
self.job_settings_type = type(initial_job_settings)
self.on_create_job_bundle_callback = on_create_job_bundle_callback
self.create_job_response: Optional[Dict[str, Any]] = None
self.parameter_values: Optional[list[Dict[str, Any]]] = None
self.deadline_authentication_status = DeadlineAuthenticationStatus.getInstance()
self.show_host_requirements_tab = show_host_requirements_tab

Expand Down Expand Up @@ -409,6 +410,19 @@ def on_submit(self):
settings.submitter_name, settings.name
)

# First filter the queue parameters to exclude any from the job template,
# then extend it with the job template parameters.
job_parameter_names = {param["name"] for param in settings.parameters}
parameter_values: list[dict[str, Any]] = [
{"name": param["name"], "value": param["value"]}
for param in queue_parameters
if param["name"] not in job_parameter_names
]
parameter_values.extend(
{"name": param["name"], "value": param["value"]} for param in settings.parameters
)
self.parameter_values = parameter_values

if self.show_host_requirements_tab:
requirements = self.host_requirements.get_requirements()
self.on_create_job_bundle_callback(
Expand Down
67 changes: 67 additions & 0 deletions test/unit/deadline_client/cli/test_cli_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os
import tempfile
import json
from unittest import mock
from unittest.mock import ANY, patch, Mock

import boto3 # type: ignore[import]
Expand All @@ -21,6 +22,7 @@
from deadline.job_attachments.upload import S3AssetManager
from deadline.job_attachments.models import JobAttachmentsFileSystem
from deadline.job_attachments.progress_tracker import SummaryStatistics
from deadline.client.cli._groups.bundle_group import _print_response

from ..api.test_job_bundle_submission import (
MOCK_CREATE_JOB_RESPONSE,
Expand Down Expand Up @@ -750,3 +752,68 @@ def test_cli_bundle_reject_upload_confirmation(fresh_deadline_config, temp_job_b

upload_attachments_mock.assert_not_called()
assert result.exit_code == 0


def test_cli_bundle_gui_submit_format_output():
"""
Verify that the GUI submitter returns responses correctly.
"""
with mock.patch("deadline.client.cli._groups.bundle_group.click") as mock_click:
_print_response(
output="json",
extra_info=True,
submitted=False,
job_bundle_dir="./test",
job_id="job-1234",
parameter_values=[],
asset_references={},
)
mock_click.echo.assert_called_with('{"status": "CANCELED"}')

_print_response(
output="json",
extra_info=False,
submitted=True,
job_bundle_dir="./test",
job_id="job-1234",
parameter_values=[{"name": "Frames", "value": "1-4"}],
asset_references={"inputs": {"filenames:": ["test.file"]}},
)
mock_click.echo.assert_called_with(
'{"status": "SUBMITTED", "jobId": "job-1234", "jobBundleDirectory": "./test"}'
)

_print_response(
output="json",
extra_info=True,
submitted=True,
job_bundle_dir="./test",
job_id="job-1234",
parameter_values=[{"name": "Frames", "value": "1-4"}],
asset_references={"inputs": {"filenames:": ["test.file"]}},
)
mock_click.echo.assert_called_with(
'{"status": "SUBMITTED", "jobId": "job-1234", "jobBundleDirectory": "./test", "parameterValues": [{"name": "Frames", "value": "1-4"}], "assetReferences": {"inputs": {"filenames:": ["test.file"]}}}'
)

_print_response(
output="verbose",
extra_info=False,
submitted=False,
job_bundle_dir="./test",
job_id="job-1234",
parameter_values=[],
asset_references={},
)
mock_click.echo.assert_called_with("Job submission canceled.")

_print_response(
output="verbose",
extra_info=False,
submitted=True,
job_bundle_dir="./test",
job_id="job-1234",
parameter_values=[],
asset_references={},
)
mock_click.echo.assert_any_call("Submitted job bundle:")

0 comments on commit aad9a49

Please sign in to comment.