This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch branch-1.0
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.0 by this push:
     new 154d35a0b7 [#8642] feat(doc): Add the IT and doc for job template 
alteration (#8810)
154d35a0b7 is described below

commit 154d35a0b70db5335dd2294e11224cff227aac2f
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Oct 14 14:08:42 2025 +0800

    [#8642] feat(doc): Add the IT and doc for job template alteration (#8810)
    
    ### 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.
    
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../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",
+          "..."
+        ]
+      }


Reply via email to