This is an automated email from the ASF dual-hosted git repository. github-bot pushed a commit to branch cherry-pick-branch-1.0-081103390054403b9cce90b8481c48242a096655 in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit 5ec6ef84df4cf63f5c0195c83667065b507004fb Author: Jerry Shao <[email protected]> AuthorDate: Tue Oct 14 11:17:43 2025 +0800 [#8642] feat(doc): Add the IT and doc for job template alteration (#8791) ### What changes were proposed in this pull request? This PR adds the IT and docs for job template alteration. ### Why are the changes needed? This is the final PR for job template alteration. Fix: #8642 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? ITs. --- .../gravitino/client/integration/test/JobIT.java | 106 +++++ .../gravitino/client/dto_converters.py | 8 +- .../tests/integration/test_supports_jobs.py | 110 ++++++ docs/manage-jobs-in-gravitino.md | 89 +++++ docs/open-api/jobs.yaml | 440 +++++++++++++++++---- 5 files changed, 662 insertions(+), 91 deletions(-) diff --git a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JobIT.java b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JobIT.java index 59043422aa..f5e66b304d 100644 --- a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JobIT.java +++ b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JobIT.java @@ -37,6 +37,7 @@ import org.apache.gravitino.integration.test.util.BaseIT; import org.apache.gravitino.integration.test.util.GravitinoITUtils; import org.apache.gravitino.job.JobHandle; import org.apache.gravitino.job.JobTemplate; +import org.apache.gravitino.job.JobTemplateChange; import org.apache.gravitino.job.ShellJobTemplate; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; @@ -177,6 +178,111 @@ public class JobIT extends BaseIT { Assertions.assertTrue(registeredTemplates.isEmpty()); } + @Test + public void testRegisterAndAlterJobTemplate() { + ShellJobTemplate template = builder.withName("test_alter").build(); + Assertions.assertDoesNotThrow(() -> metalake.registerJobTemplate(template)); + + // Rename the job template + JobTemplate renamedTemplate = + metalake.alterJobTemplate(template.name(), JobTemplateChange.rename("renamed_test_alter")); + + // Verify the job template is renamed + Assertions.assertEquals("renamed_test_alter", renamedTemplate.name()); + Assertions.assertEquals(template.comment(), renamedTemplate.comment()); + Assertions.assertEquals(template.executable(), renamedTemplate.executable()); + Assertions.assertEquals(template.arguments(), renamedTemplate.arguments()); + Assertions.assertEquals(template.environments(), renamedTemplate.environments()); + Assertions.assertEquals(template.customFields(), renamedTemplate.customFields()); + Assertions.assertEquals(template.scripts(), ((ShellJobTemplate) renamedTemplate).scripts()); + + JobTemplate fetchedTemplate = metalake.getJobTemplate(renamedTemplate.name()); + Assertions.assertEquals(renamedTemplate, fetchedTemplate); + + // Update the job template's comment + JobTemplate updatedTemplate = + metalake.alterJobTemplate( + renamedTemplate.name(), JobTemplateChange.updateComment("Updated comment")); + + // Verify the job template comment is updated + Assertions.assertEquals("Updated comment", updatedTemplate.comment()); + Assertions.assertEquals(renamedTemplate.name(), updatedTemplate.name()); + Assertions.assertEquals(template.executable(), updatedTemplate.executable()); + Assertions.assertEquals(template.arguments(), updatedTemplate.arguments()); + Assertions.assertEquals(template.environments(), updatedTemplate.environments()); + Assertions.assertEquals(template.customFields(), updatedTemplate.customFields()); + Assertions.assertEquals(template.scripts(), ((ShellJobTemplate) updatedTemplate).scripts()); + + // Fetch the updated template and verify + JobTemplate fetchedUpdatedTemplate = metalake.getJobTemplate(updatedTemplate.name()); + Assertions.assertEquals(updatedTemplate, fetchedUpdatedTemplate); + + // Update the job template's executable, arguments, and environments + JobTemplateChange.ShellTemplateUpdate update = + JobTemplateChange.ShellTemplateUpdate.builder() + .withNewExecutable("/new/path/to/executable.sh") + .withNewArguments(Lists.newArrayList("newArg1", "newArg2")) + .withNewEnvironments(ImmutableMap.of("NEW_ENV", "newValue")) + .build(); + + JobTemplate modifiedTemplate = + metalake.alterJobTemplate(updatedTemplate.name(), JobTemplateChange.updateTemplate(update)); + + // Verify the job template fields are updated + Assertions.assertEquals(update.getNewExecutable(), modifiedTemplate.executable()); + Assertions.assertEquals(update.getNewArguments(), modifiedTemplate.arguments()); + Assertions.assertEquals(update.getNewEnvironments(), modifiedTemplate.environments()); + Assertions.assertEquals(updatedTemplate.customFields(), modifiedTemplate.customFields()); + Assertions.assertEquals( + ((ShellJobTemplate) updatedTemplate).scripts(), + ((ShellJobTemplate) modifiedTemplate).scripts()); + + // Fetch the modified template and verify + JobTemplate fetchedModifiedTemplate = metalake.getJobTemplate(modifiedTemplate.name()); + Assertions.assertEquals(modifiedTemplate, fetchedModifiedTemplate); + + // Update the job template's custom fields and scripts + JobTemplateChange.ShellTemplateUpdate update1 = + JobTemplateChange.ShellTemplateUpdate.builder() + .withNewCustomFields(ImmutableMap.of("customKey", "customValue")) + .withNewScripts(Lists.newArrayList(testLibScriptPath, "/new/path/to/script.sh")) + .build(); + + JobTemplate finalTemplate = + metalake.alterJobTemplate( + modifiedTemplate.name(), JobTemplateChange.updateTemplate(update1)); + + // Verify the job template fields are updated + Assertions.assertEquals(modifiedTemplate.executable(), finalTemplate.executable()); + Assertions.assertEquals(modifiedTemplate.arguments(), finalTemplate.arguments()); + Assertions.assertEquals(modifiedTemplate.environments(), finalTemplate.environments()); + Assertions.assertEquals(update1.getNewCustomFields(), finalTemplate.customFields()); + Assertions.assertEquals(update1.getNewScripts(), ((ShellJobTemplate) finalTemplate).scripts()); + + // Fetch the final template and verify + JobTemplate fetchedFinalTemplate = metalake.getJobTemplate(finalTemplate.name()); + Assertions.assertEquals(finalTemplate, fetchedFinalTemplate); + + // Test altering a non-existent job template + Assertions.assertThrows( + NoSuchJobTemplateException.class, + () -> + metalake.alterJobTemplate( + "non_existent_template", JobTemplateChange.rename("new_name"))); + + // Test altering with wrong change type + JobTemplateChange.SparkTemplateUpdate wrongUpdate = + JobTemplateChange.SparkTemplateUpdate.builder() + .withNewClassName("com.example.Main") + .build(); + + Assertions.assertThrows( + IllegalArgumentException.class, + () -> + metalake.alterJobTemplate( + finalTemplate.name(), JobTemplateChange.updateTemplate(wrongUpdate))); + } + @Test public void testRunAndListJobs() { JobTemplate template = builder.withName("test_run").build(); diff --git a/clients/client-python/gravitino/client/dto_converters.py b/clients/client-python/gravitino/client/dto_converters.py index 5283075318..9b0c3775c6 100644 --- a/clients/client-python/gravitino/client/dto_converters.py +++ b/clients/client-python/gravitino/client/dto_converters.py @@ -143,7 +143,7 @@ class DTOConverters: ) @staticmethod - def _to_shell_job_template(template: JobTemplate) -> ShellJobTemplate: + def to_shell_job_template(template: JobTemplate) -> ShellJobTemplate: if isinstance(template, ShellJobTemplate): return template @@ -152,7 +152,7 @@ class DTOConverters: ) @staticmethod - def _to_spark_job_template(template: JobTemplate) -> SparkJobTemplate: + def to_spark_job_template(template: JobTemplate) -> SparkJobTemplate: if isinstance(template, SparkJobTemplate): return template @@ -199,7 +199,7 @@ class DTOConverters: @staticmethod def to_job_template_dto(template: JobTemplate) -> JobTemplateDTO: if isinstance(template, ShellJobTemplate): - shell_template = DTOConverters._to_shell_job_template(template) + shell_template = DTOConverters.to_shell_job_template(template) return ShellJobTemplateDTO( _job_type=shell_template.job_type(), _name=shell_template.name, @@ -212,7 +212,7 @@ class DTOConverters: ) if isinstance(template, SparkJobTemplate): - spark_template = DTOConverters._to_spark_job_template(template) + spark_template = DTOConverters.to_spark_job_template(template) return SparkJobTemplateDTO( _job_type=spark_template.job_type(), _name=spark_template.name, diff --git a/clients/client-python/tests/integration/test_supports_jobs.py b/clients/client-python/tests/integration/test_supports_jobs.py index 2235050b58..4a5195a530 100644 --- a/clients/client-python/tests/integration/test_supports_jobs.py +++ b/clients/client-python/tests/integration/test_supports_jobs.py @@ -23,11 +23,18 @@ from time import sleep from gravitino import GravitinoAdminClient, GravitinoMetalake from gravitino.api.job.job_handle import JobHandle +from gravitino.api.job.job_template_change import ( + JobTemplateChange, + ShellTemplateUpdate, + SparkTemplateUpdate, +) from gravitino.api.job.shell_job_template import ShellJobTemplate +from gravitino.client.dto_converters import DTOConverters from gravitino.exceptions.base import ( JobTemplateAlreadyExistsException, NoSuchJobTemplateException, NoSuchJobException, + IllegalArgumentException, ) from tests.integration.integration_test_env import IntegrationTestEnv @@ -160,6 +167,109 @@ class TestSupportsJobs(IntegrationTestEnv): registered_templates = self._metalake.list_job_templates() self.assertTrue(len(registered_templates) == 0) + def test_register_and_alter_job_template(self): + template = self.builder.with_name("test_alter").build() + self._metalake.register_job_template(template) + + # Rename the job template + updated_template = self._metalake.alter_job_template( + template.name, JobTemplateChange.rename("test_alter_renamed") + ) + self.assertEqual("test_alter_renamed", updated_template.name) + self.assertEqual(template.executable, updated_template.executable) + self.assertEqual(template.arguments, updated_template.arguments) + self.assertEqual(template.environments, updated_template.environments) + self.assertEqual(template.custom_fields, updated_template.custom_fields) + self.assertEqual( + template.scripts, + DTOConverters.to_shell_job_template(updated_template).scripts, + ) + + fetched_template = self._metalake.get_job_template("test_alter_renamed") + self.assertEqual(updated_template, fetched_template) + + # Update the comment of the job template + updated_template = self._metalake.alter_job_template( + "test_alter_renamed", JobTemplateChange.update_comment("Updated comment") + ) + self.assertEqual("Updated comment", updated_template.comment) + self.assertEqual("test_alter_renamed", updated_template.name) + self.assertEqual(template.executable, updated_template.executable) + self.assertEqual(template.arguments, updated_template.arguments) + self.assertEqual(template.environments, updated_template.environments) + self.assertEqual(template.custom_fields, updated_template.custom_fields) + self.assertEqual( + template.scripts, + DTOConverters.to_shell_job_template(updated_template).scripts, + ) + + fetched_template = self._metalake.get_job_template("test_alter_renamed") + self.assertEqual(updated_template, fetched_template) + + # Update the content of the job template + updated_template_content = ShellTemplateUpdate( + new_executable="/bin/echo", + new_arguments=["Hello", "World"], + new_environments={"NEW_ENV": "new_value"}, + ) + updated_template = self._metalake.alter_job_template( + "test_alter_renamed", + JobTemplateChange.update_template(updated_template_content), + ) + + self.assertEqual("/bin/echo", updated_template.executable) + self.assertEqual(["Hello", "World"], updated_template.arguments) + self.assertEqual({"NEW_ENV": "new_value"}, updated_template.environments) + self.assertEqual("Updated comment", updated_template.comment) + self.assertEqual("test_alter_renamed", updated_template.name) + self.assertEqual(template.custom_fields, updated_template.custom_fields) + self.assertEqual( + template.scripts, + DTOConverters.to_shell_job_template(updated_template).scripts, + ) + + fetched_template = self._metalake.get_job_template("test_alter_renamed") + self.assertEqual(updated_template, fetched_template) + + # Update the custom fields and scripts of the job template + updated_template_content = ShellTemplateUpdate( + new_custom_fields={"key1": "value1", "key2": "value2"}, + new_scripts=["/bin/script1.sh", "/bin/script2.sh"], + ) + updated_template = self._metalake.alter_job_template( + "test_alter_renamed", + JobTemplateChange.update_template(updated_template_content), + ) + + self.assertEqual("/bin/echo", updated_template.executable) + self.assertEqual(["Hello", "World"], updated_template.arguments) + self.assertEqual({"NEW_ENV": "new_value"}, updated_template.environments) + self.assertEqual("Updated comment", updated_template.comment) + self.assertEqual("test_alter_renamed", updated_template.name) + self.assertEqual( + {"key1": "value1", "key2": "value2"}, updated_template.custom_fields + ) + self.assertEqual( + ["/bin/script1.sh", "/bin/script2.sh"], + DTOConverters.to_shell_job_template(updated_template).scripts, + ) + + fetched_template = self._metalake.get_job_template("test_alter_renamed") + self.assertEqual(updated_template, fetched_template) + + # Test altering a non-existent job template + with self.assertRaises(NoSuchJobTemplateException): + self._metalake.alter_job_template( + "non_existent", JobTemplateChange.rename("should_fail") + ) + + # Test altering with the wrong type of change + with self.assertRaises(IllegalArgumentException): + wrong_update = SparkTemplateUpdate(new_executable="/bin/echo") + self._metalake.alter_job_template( + "test_alter_renamed", JobTemplateChange.update_template(wrong_update) + ) + def test_run_and_list_jobs(self): template = self.builder.with_name("test_run").build() self._metalake.register_job_template(template) diff --git a/docs/manage-jobs-in-gravitino.md b/docs/manage-jobs-in-gravitino.md index 271dc6019d..d94ad6d204 100644 --- a/docs/manage-jobs-in-gravitino.md +++ b/docs/manage-jobs-in-gravitino.md @@ -343,6 +343,95 @@ curl -X DELETE -H "Accept: application/vnd.gravitino.v1+json" \ </TabItem> </Tabs> +### Alter a registered job template + +You can alter a registered job template by its name using the REST API or the Java and Python +SDKs. Gravitino supports altering the `name`, `comment` and `template` fields of the job template. + +<Tabs groupId='language' queryString> +<TabItem value="shell" label="Shell"> + +```shell +curl -X PUT -H "Accept: application/vnd.gravitino.v1+json" \ + -H "Content-Type: application/json" \ + -d '{ + "updates": [ + { + "@type": "rename", + "newName": "altered_shell_job_template" + }, + { + "@type": "comment", + "newComment": "An altered shell job template" + }, + { + "@type": "updateTemplate", + "newTemplate": { + "@type": "shell", + "newExecutable": "/new/path/to/my_script.sh", + "newArguments": ["{{new_arg1}}", "{{new_arg2}}"], + "newEnvironments": { + "NEW_ENV_VAR1": "{{new_value1}}", + "NEW_ENV_VAR2": "{{new_value2}}" + }, + "newCustomFields": { + "new_field1": "{{new_value1}}", + "new_field2": "{{new_value2}}" + }, + "newScripts": ["/new/path/to/script1.sh", "/new/path/to/script2.sh"] + } + } + ] + + }' http://localhost:8090/api/metalakes/test/jobs/templates/my_shell_job_template +``` + +</TabItem> +<TabItem value="java" label="Java"> + +```java + ShellTemplateUpdate newTemplate = ShellTemplateUpdate.builder() + .withNewExecutable("/new/path/to/my_script.sh") + .withNewArguments(ImmutableList.of("{{new_arg1}}", "{{new_arg2}}")) + .withNewEnvironments(ImmutableMap.of("NEW_ENV_VAR1", "{{new_value1}}", "NEW_ENV_VAR2", "{{new_value2}}")) + .withNewCustomFields(ImmutableMap.of("new_field1", "{{new_value1}}", "new_field2", "{{new_value2}}")) + .withNewScripts(List.of("/new/path/to/script1.sh", "/new/path/to/script2.sh")) + .build(); + + List<JobTemplateChange> changes = List.of( + JobTemplateChange.rename("altered_shell_job_template"), + JobTemplateChange.updateComment("An altered shell job template"), + JobTemplateChange.updateTemplateUpdateJobTemplate(newTemplate)); + + GravitinoClient client = ...; + client.alterJobTemplate("my_shell_job_template", changes); +``` + +</TabItem> +<TabItem value="python" label="Python"> + +```python + new_template = ShellTemplateUpdate( + new_executable="/new/path/to/my_script.sh", + new_arguments=["{{new_arg1}}", "{{new_arg2}}"], + new_environments={"NEW_ENV_VAR1": "{{new_value1}}", "NEW_ENV_VAR2": "{{new_value2}}"}, + new_custom_fields={"new_field1": "{{new_value1}}", "new_field2": "{{new_value2}}"}, + new_scripts=["/new/path/to/script1.sh", "/new/path/to/script2.sh"] + ) + + changes = [ + JobTemplateChange.rename("altered_shell_job_template"), + JobTemplateChange.update_comment("An altered shell job template"), + JobTemplateChange.update_template(new_template) + ] + + client = GravitinoClient(...) + client.alter_job_template("my_shell_job_template", changes) +``` + +</TabItem> +</Tabs> + ### Run a job based on a job template To run a job based on the registered job template, you can use the REST API or the Java and Python SDKs. diff --git a/docs/open-api/jobs.yaml b/docs/open-api/jobs.yaml index d5be5bc109..951cda10c5 100644 --- a/docs/open-api/jobs.yaml +++ b/docs/open-api/jobs.yaml @@ -137,6 +137,54 @@ paths: "5xx": $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + put: + tags: + - job + summary: Update job template + operationId: updateJobTemplate + description: Updates a job template in the specified metalake + requestBody: + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "#/components/requests/JobTemplateUpdatesRequest" + examples: + JobTemplateRegisterRequest: + $ref: "#/components/examples/JobTemplateUpdatesRequest" + + responses: + "200": + description: Returns the updated job template object + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "#/components/responses/JobTemplateResponse" + examples: + JobTemplateResponse: + $ref: "#/components/examples/JobTemplateResponse" + "404": + description: Not Found - The specified job template does not exist in the specified metalake + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "./openapi.yaml#/components/schemas/ErrorModel" + examples: + NoSuchMetalakeException: + $ref: "./metalakes.yaml#/components/examples/NoSuchMetalakeException" + NoSuchJobTemplateException: + $ref: "#/components/examples/NoSuchJobTemplateException" + "400": + description: Bad Request - The changes in the request cannot be applied to the job template + content: + application/vnd.gravitino.v1+json: + schema: + $ref: "./openapi.yaml#/components/schemas/ErrorModel" + examples: + IllegalArgumentException: + $ref: "#/components/examples/IllegalArgumentException" + "5xx": + $ref: "./openapi.yaml#/components/responses/ServerErrorResponse" + /metalakes/{metalake}/jobs/runs: parameters: - $ref: "./openapi.yaml#/components/parameters/metalake" @@ -368,103 +416,216 @@ components: $ref: "./openapi.yaml#/components/schemas/Audit" SparkJobTemplate: - type: object - description: A job template object for Spark jobs - required: - - name - - jobType - - mainClass - properties: - name: + type: object + description: A job template object for Spark jobs + required: + - name + - jobType + - mainClass + properties: + name: + type: string + description: The name of the job template + jobType: + type: string + description: The type of the job template + enum: + - "spark" + comment: + type: string + description: A comment about the job template + nullable: true + executable: + type: string + description: The executable command of the job template + arguments: + type: array + description: The arguments of the job template + items: type: string - description: The name of the job template - jobType: + nullable: true + environments: + type: object + description: Configured string to string map of environment variables for the job template + default: { } + additionalProperties: type: string - description: The type of the job template - enum: - - "spark" - comment: + customFields: + type: object + description: Configured string to string map of custom fields for the job template + default: { } + additionalProperties: type: string - description: A comment about the job template - nullable: true - executable: + mainClass: + type: string + description: The main class of the Spark job template + jars: + type: array + description: The JAR files of the Spark job template + items: type: string - description: The executable command of the job template - arguments: - type: array - description: The arguments of the job template - items: - type: string - nullable: true - environments: - type: object - description: Configured string to string map of environment variables for the job template - default: { } - additionalProperties: - type: string - customFields: - type: object - description: Configured string to string map of custom fields for the job template - default: { } - additionalProperties: - type: string - mainClass: + nullable: true + files: + type: array + description: The files of the Spark job template + items: type: string - description: The main class of the Spark job template - jars: - type: array - description: The JAR files of the Spark job template - items: - type: string - nullable: true - files: - type: array - description: The files of the Spark job template - items: - type: string - nullable: true - archives: - type: array - description: The archives of the Spark job template - items: - type: string - nullable: true - configs: - type: object - description: Configured string to string map of Spark configurations for the job template - default: { } - additionalProperties: - type: string - audit: - $ref: "./openapi.yaml#/components/schemas/Audit" + nullable: true + archives: + type: array + description: The archives of the Spark job template + items: + type: string + nullable: true + configs: + type: object + description: Configured string to string map of Spark configurations for the job template + default: { } + additionalProperties: + type: string + audit: + $ref: "./openapi.yaml#/components/schemas/Audit" Job: - type: object - description: A job object - required: - - jobId - - jobTemplateName - - status - - audit - properties: - jobId: + type: object + description: A job object + required: + - jobId + - jobTemplateName + - status + - audit + properties: + jobId: + type: string + description: The unique identifier of the job + jobTemplateName: + type: string + description: The name of the job template used to create the job + status: + type: string + description: The status of the job + enum: + - "queued" + - "started" + - "failed" + - "succeeded" + - "cancelling" + - "canceled" + audit: + $ref: "./openapi.yaml#/components/schemas/Audit" + + + TemplateUpdate: + oneOf: + - $ref: "#/components/schemas/ShellTemplateUpdate" + - $ref: "#/components/schemas/SparkTemplateUpdate" + discriminator: + propertyName: "@type" + mapping: + shell: "#/components/schemas/ShellTemplateUpdate" + spark: "#/components/schemas/SparkTemplateUpdate" + + ShellTemplateUpdate: + type: object + description: A job template update object for shell jobs + required: + - "@type" + properties: + "@type": + type: string + description: The type of the job template + enum: + - "shell" + newExecutable: + type: string + description: The new executable command of the job template + nullable: true + newArguments: + type: array + description: The new arguments of the job template + items: type: string - description: The unique identifier of the job - jobTemplateName: + nullable: true + newEnvironments: + type: object + description: The new configured string to string map of environment variables for the job template + additionalProperties: + type: string + nullable: true + newCustomFields: + type: object + description: The new configured string to string map of custom fields for the job template + additionalProperties: type: string - description: The name of the job template used to create the job - status: + nullable: true + newScripts: + type: array + description: The new scripts of the job template + items: type: string - description: The status of the job - enum: - - "queued" - - "started" - - "failed" - - "succeeded" - - "cancelling" - - "canceled" - audit: - $ref: "./openapi.yaml#/components/schemas/Audit" + nullable: true + + SparkTemplateUpdate: + type: object + description: A job template update object for Spark jobs + required: + - "@type" + properties: + "@type": + type: string + description: The type of the job template + enum: + - "spark" + newExecutable: + type: string + description: The new executable command of the job template + nullable: true + newArguments: + type: array + description: The new arguments of the job template + items: + type: string + nullable: true + newEnvironments: + type: object + description: The new configured string to string map of environment variables for the job template + additionalProperties: + type: string + nullable: true + newCustomFields: + type: object + description: The new configured string to string map of custom fields for the job template + additionalProperties: + type: string + nullable: true + newClassName: + type: string + description: The new class name of the Spark job template + nullable: true + newJars: + type: array + description: The new JAR files of the Spark job template + items: + type: string + nullable: true + newFiles: + type: array + description: The new files of the Spark job template + items: + type: string + nullable: true + newArchives: + type: array + description: The new archives of the Spark job template + items: + type: string + nullable: true + newConfigs: + type: object + description: The new configured string to string map of Spark configurations for the job template + additionalProperties: + type: string + nullable: true requests: @@ -476,6 +637,69 @@ components: jobTemplate: $ref: "#/components/schemas/JobTemplate" + JobTemplateUpdatesRequest: + type: object + required: + - updates + properties: + updates: + type: array + items: + $ref: "#/components/requests/JobTemplateUpdateRequest" + + JobTemplateUpdateRequest: + oneOf: + - $ref: "#/components/requests/RenameJobTemplateRequest" + - $ref: "#/components/requests/UpdateJobTemplateCommentRequest" + - $ref: "#/components/requests/UpdateJobTemplateContentRequest" + discriminator: + propertyName: "@type" + mapping: + rename: "#/components/requests/RenameJobTemplateRequest" + updateComment: "#/components/requests/UpdateJobTemplateCommentRequest" + updateTemplate: "#/components/requests/UpdateJobTemplateContentRequest" + + RenameJobTemplateRequest: + type: object + required: + - "@type" + - newName + properties: + "@type": + type: string + enum: + - "rename" + newName: + type: string + description: The new name of the job template + + UpdateJobTemplateCommentRequest: + type: object + required: + - "@type" + - newComment + properties: + "@type": + type: string + enum: + - "updateComment" + newComment: + type: string + description: The new comment of the job template + + UpdateJobTemplateContentRequest: + type: object + required: + - "@type" + - newTemplate + properties: + "@type": + type: string + enum: + - "updateTemplate" + newTemplate: + $ref: "#/components/schemas/TemplateUpdate" + JobRunRequest: type: object required: @@ -621,6 +845,37 @@ components: } } + JobTemplateUpdatesRequest: + value: { + "updates": [ + { + "@type": "rename", + "newName": "new_test_run_get" + }, + { + "@type": "updateComment", + "newComment": "Updated comment for the job template" + }, + { + "@type": "updateTemplate", + "newTemplate": { + "@type": "shell", + "newExecutable": "/var/folders/90/v1d9hxsd6pj8m0jnn6f22tkr0000gn/T/tmpy65fiugc/updated-test-job.sh", + "newArguments": ["{{new_arg1}}", "{{new_arg2}}"], + "newEnvironments": { + "NEW_ENV_VAR": "{{new_env_var}}" + }, + "newCustomFields": { + "field1": "value1" + }, + "newScripts": [ + "/var/folders/90/v1d9hxsd6pj8m0jnn6f22tkr0000gn/T/tmpy65fiugc/updated-common.sh" + ] + } + } + ] + } + JobRunRequest: value: { "jobTemplateName": "test_run_get", @@ -724,3 +979,14 @@ components: "..." ] } + + IllegalArgumentException: + value: { + "code": 1001, + "type": "IllegalArgumentException", + "message": "Failed to operate job template(s) [my_job] operation [UPDATE], reason [IllegalArgumentException]", + "stack": [ + "java.lang.IllegalArgumentException: Invalid argument xxx", + "..." + ] + }
