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

cdmikechen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new 6103f2a9 SUBMARINE-1363. Git-Sync container can not pull specified 
branch or main codes
6103f2a9 is described below

commit 6103f2a9e60f0cd165e2ec43b1e5f92180fabf7e
Author: cdmikechen <cdmikec...@apache.org>
AuthorDate: Fri Jun 23 08:01:46 2023 +0800

    SUBMARINE-1363. Git-Sync container can not pull specified branch or main 
codes
    
    ### What is this PR for?
    Make submarine support for pulling git with branch, username and password.
    In the meantime, some python CI issues have been discovered while changing 
codes. This has now been fixed as well.
    
    ### What type of PR is it?
    Bug Fix
    
    ### Todos
    * [x] - Submarine Server
    * [x] - e2e test
    * [x] - Submarine Workbench
    * [x] - Submarine API Documents
    * [x] - Submarine SDK
    * [x] - Fix some CI error in python workflow
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1363
    
    ### How should this be tested?
    cicd
    
    ### Screenshots (if appropriate)
    <img width="1029" alt="image" 
src="https://github.com/apache/submarine/assets/12069428/a2f5bc33-293b-4bf4-b242-06890a5933ec";>
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? Yes
    * Does this need new documentation? Yes
    
    Author: cdmikechen <cdmikec...@apache.org>
    
    Signed-off-by: cdmikechen <cdmikec...@apache.org>
    
    Closes #1064 from cdmikechen/SUBMARINE-1363 and squashes the following 
commits:
    
    0632373a [cdmikechen] remove df command
    82ddd84d [cdmikechen] replace step
    c5e09617 [cdmikechen] clear some mvn cache
    8327d96f [cdmikechen] remove images
    b2ee2369 [cdmikechen] check storage
    99a5229e [cdmikechen] change apis
    c3773e09 [cdmikechen] fix in integration
    780b3d4b [cdmikechen] remove --no-cache-dir
    108d4511 [cdmikechen] fix tensorflow-estimator version
    a4e950d5 [cdmikechen] fix sed
    c60375b1 [cdmikechen] test pipeline
    2b471918 [cdmikechen] replace name
    d103d5ae [cdmikechen] fix python ci jdk error
    579b4d06 [cdmikechen] fix python error
    b0eb7cc8 [cdmikechen] Regenerate openapi.json
    bc669926 [cdmikechen] Regenerate the api for the sdk
    515938c0 [cdmikechen] add GitCodeSpec in front
    cc2145ab [cdmikechen] fix construction
    ed6861ee [cdmikechen] fix git url
    05ce4144 [cdmikechen] fix npe
    3896c494 [cdmikechen] backend change
---
 .github/scripts/build-image-locally-v3.sh          |   2 +
 .github/workflows/python.yml                       |  51 +-
 dev-support/pysubmarine/openapi.json               | 574 +++++++++++----------
 .../example/submarine_experiment_sdk.ipynb         |   6 +-
 submarine-sdk/pysubmarine/setup.py                 |   2 +-
 .../pysubmarine/submarine/client/__init__.py       |   1 +
 .../submarine/client/models/__init__.py            |   1 +
 .../submarine/client/models/code_spec.py           |  34 +-
 .../client/models/experiment_task_spec.py          |  54 +-
 .../{notebook_pod_spec.py => git_code_spec.py}     | 164 +++---
 .../submarine/client/models/notebook_pod_spec.py   |  54 +-
 .../pysubmarine/tests/cli/test_experiment.py       |   3 +-
 .../tests/experiment/test_experiment_client.py     |   3 +-
 .../apache/submarine/server/api/spec/CodeSpec.java |  18 +-
 .../submarine/server/api/spec/ExperimentSpec.java  |   2 +-
 .../server/api/spec/code/GitCodeSpec.java          |  92 ++++
 .../codelocalizer/AbstractCodeLocalizer.java       |  34 +-
 .../codelocalizer/DummyCodeLocalizer.java          |   3 +-
 .../experiment/codelocalizer/GitCodeLocalizer.java |  87 ++--
 .../codelocalizer/HTTPGitCodeLocalizer.java        |   5 +-
 .../codelocalizer/SSHGitCodeLocalizer.java         |   5 +-
 .../submitter/k8s/parser/ExperimentSpecParser.java |   3 +-
 .../K8sResourceUtils.java}                         |  22 +-
 .../pytorch_job_req_http_git_code_localizer.json   |   4 +-
 .../pytorch_job_req_ssh_git_code_localizer.json    |   4 +-
 .../tf-mnist-with-http-git-code-localizer-req.json |   4 +-
 .../tf-mnist-with-ssh-git-code-localizer-req.json  |   4 +-
 .../src/app/interfaces/experiment-spec.ts          |   8 +
 .../experiment-customized-form.component.html      |  39 +-
 .../experiment-customized-form.component.ts        |  24 +-
 website/docs/api/experiment-template.md            |  21 +-
 website/docs/api/experiment.md                     |  16 +-
 website/docs/gettingStarted/notebook.md            |   2 +-
 33 files changed, 801 insertions(+), 545 deletions(-)

diff --git a/.github/scripts/build-image-locally-v3.sh 
b/.github/scripts/build-image-locally-v3.sh
index 00fdb770..e8525469 100755
--- a/.github/scripts/build-image-locally-v3.sh
+++ b/.github/scripts/build-image-locally-v3.sh
@@ -33,5 +33,7 @@ do
   echo "Execute ./dev-support/docker-images/${FOLDER_LIST[i]}/build.sh"
   ./dev-support/docker-images/"${FOLDER_LIST[i]}"/build.sh
   kind load docker-image "${IMAGE_LIST[i]}"
+  # remove docker image to reduce current space
+  docker rmi "${IMAGE_LIST[i]}"
 done
 
diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
index c0727ee4..11c2a7b2 100644
--- a/.github/workflows/python.yml
+++ b/.github/workflows/python.yml
@@ -73,8 +73,9 @@ jobs:
       - name: Install pysubmarine with tf2 and pytorch
         if: startsWith(matrix.tf-version, '2.')
         run: |
+          sed -i "s/tensorflow>=2.6.0,<2.10.0/tensorflow~=${{ 
matrix.tf-version }}/" ./submarine-sdk/pysubmarine/setup.py
+          sed -i 
"s/tensorflow-estimator>=2.6.0,<2.10.0/tensorflow-estimator~=${{ 
matrix.tf-version }}/" ./submarine-sdk/pysubmarine/setup.py
           pip install --no-cache-dir -e 
./submarine-sdk/pysubmarine/.[tf2,pytorch]
-          pip install --no-cache-dir 'tensorflow~=${{ matrix.tf-version }}'
       - name: List installed packages
         run: pip list && pipdeptree
       - name: Run unit test
@@ -109,10 +110,31 @@ jobs:
       - uses: actions/checkout@v3
         with:
           fetch-depth: 50
-      - name: Set up JDK 1.8
+      - name: Setup python environment
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Install tf1 dependencies
+        if: ${{ matrix.tf-version == '1.15.0' }}
+        run: |
+          pip install --upgrade pip setuptools wheel
+          pip install --no-cache-dir -e 
./submarine-sdk/pysubmarine/.[tf,pytorch]
+          pip install -r 
./submarine-sdk/pysubmarine/github-actions/test-requirements.txt
+      - name: Install tf2 dependencies
+        if: startsWith(matrix.tf-version, '2.')
+        run: |
+          pip install --upgrade pip setuptools wheel
+          sed -i "s/tensorflow>=2.6.0,<2.10.0/tensorflow~=${{ 
matrix.tf-version }}/" ./submarine-sdk/pysubmarine/setup.py
+          sed -i 
"s/tensorflow-estimator>=2.6.0,<2.10.0/tensorflow-estimator~=${{ 
matrix.tf-version }}/" ./submarine-sdk/pysubmarine/setup.py
+          pip install --no-cache-dir -e 
./submarine-sdk/pysubmarine/.[tf2,pytorch]
+          pip install -r 
./submarine-sdk/pysubmarine/github-actions/test-requirements.txt
+          pip cache purge
+      - name: List installed packages
+        run: pip list
+      - name: Set up JDK 11
         uses: actions/setup-java@v1
         with:
-          java-version: "1.8"
+          java-version: "11"
       - name: Set up Maven 3.6.3
         uses: stCarolas/setup-maven@v4
         with:
@@ -145,28 +167,11 @@ jobs:
           restore-keys: |
             ${{ runner.os }}-maven-
       - name: Build Image locally
-        run: .github/scripts/build-image-locally-v3.sh
+        run: 
+          .github/scripts/build-image-locally-v3.sh
+          mvn clean
       - name: Start submarine
         run: bash ./.github/scripts/start-submarine.sh
-      - name: Setup python environment
-        uses: actions/setup-python@v4
-        with:
-          python-version: ${{ matrix.python-version }}
-      - name: Install tf1 dependencies
-        if: ${{ matrix.tf-version == '1.15.0' }}
-        run: |
-          pip install --upgrade pip setuptools wheel
-          pip install --no-cache-dir -e 
./submarine-sdk/pysubmarine/.[tf,pytorch]
-          pip install -r 
./submarine-sdk/pysubmarine/github-actions/test-requirements.txt
-      - name: Install tf2 dependencies
-        if: startsWith(matrix.tf-version, '2.')
-        run: |
-          pip install --upgrade pip setuptools wheel
-          pip install --no-cache-dir -e 
./submarine-sdk/pysubmarine/.[tf2,pytorch]
-          pip install --no-cache-dir 'tensorflow~=${{ matrix.tf-version }}'
-          pip install -r 
./submarine-sdk/pysubmarine/github-actions/test-requirements.txt
-      - name: List installed packages
-        run: pip list
       - name: Set CLI config for e2e pytest
         run: |
           submarine config set connection.hostname localhost
diff --git a/dev-support/pysubmarine/openapi.json 
b/dev-support/pysubmarine/openapi.json
index f04cf32c..0a13aafd 100644
--- a/dev-support/pysubmarine/openapi.json
+++ b/dev-support/pysubmarine/openapi.json
@@ -174,33 +174,68 @@
         }
       }
     },
-    "/v1/experiment/{name}" : {
-      "post" : {
+    "/v1/experiment/logs/{id}" : {
+      "get" : {
         "tags" : [ "experiment" ],
-        "summary" : "use experiment template to create an experiment",
-        "operationId" : "SubmitExperimentTemplate",
+        "summary" : "Log experiment by id",
+        "operationId" : "getLog",
         "parameters" : [ {
-          "name" : "name",
+          "name" : "id",
           "in" : "path",
           "required" : true,
           "schema" : {
             "type" : "string"
           }
         } ],
-        "requestBody" : {
-          "content" : {
-            "application/yaml" : {
-              "schema" : {
-                "$ref" : "#/components/schemas/ExperimentTemplateSubmit"
+        "responses" : {
+          "default" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/JsonResponse"
+                }
               }
-            },
-            "application/json" : {
-              "schema" : {
-                "$ref" : "#/components/schemas/ExperimentTemplateSubmit"
+            }
+          },
+          "404" : {
+            "description" : "Experiment not found"
+          }
+        }
+      }
+    },
+    "/v1/experiment/ping" : {
+      "get" : {
+        "tags" : [ "experiment" ],
+        "summary" : "Ping submarine server",
+        "description" : "Return the Pong message for test the connectivity",
+        "operationId" : "ping",
+        "responses" : {
+          "200" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "type" : "string"
+                }
               }
             }
           }
-        },
+        }
+      }
+    },
+    "/v1/experiment/logs" : {
+      "get" : {
+        "tags" : [ "experiment" ],
+        "summary" : "List experiment's log",
+        "operationId" : "listLog",
+        "parameters" : [ {
+          "name" : "status",
+          "in" : "query",
+          "schema" : {
+            "type" : "string"
+          }
+        } ],
         "responses" : {
           "default" : {
             "description" : "successful operation",
@@ -272,6 +307,47 @@
         }
       }
     },
+    "/v1/experiment/{name}" : {
+      "post" : {
+        "tags" : [ "experiment" ],
+        "summary" : "use experiment template to create an experiment",
+        "operationId" : "SubmitExperimentTemplate",
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "path",
+          "required" : true,
+          "schema" : {
+            "type" : "string"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/yaml" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/ExperimentTemplateSubmit"
+              }
+            },
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/ExperimentTemplateSubmit"
+              }
+            }
+          }
+        },
+        "responses" : {
+          "default" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/JsonResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/v1/experiment/{id}" : {
       "get" : {
         "tags" : [ "experiment" ],
@@ -402,19 +478,11 @@
         }
       }
     },
-    "/v1/experiment/logs/{id}" : {
+    "/v1/experiment/tensorboard" : {
       "get" : {
         "tags" : [ "experiment" ],
-        "summary" : "Log experiment by id",
-        "operationId" : "getLog",
-        "parameters" : [ {
-          "name" : "id",
-          "in" : "path",
-          "required" : true,
-          "schema" : {
-            "type" : "string"
-          }
-        } ],
+        "summary" : "Get tensorboard's information",
+        "operationId" : "getTensorboardInfo",
         "responses" : {
           "default" : {
             "description" : "successful operation",
@@ -427,7 +495,7 @@
             }
           },
           "404" : {
-            "description" : "Experiment not found"
+            "description" : "Tensorboard not found"
           }
         }
       }
@@ -454,74 +522,6 @@
         }
       }
     },
-    "/v1/experiment/tensorboard" : {
-      "get" : {
-        "tags" : [ "experiment" ],
-        "summary" : "Get tensorboard's information",
-        "operationId" : "getTensorboardInfo",
-        "responses" : {
-          "default" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "$ref" : "#/components/schemas/JsonResponse"
-                }
-              }
-            }
-          },
-          "404" : {
-            "description" : "Tensorboard not found"
-          }
-        }
-      }
-    },
-    "/v1/experiment/logs" : {
-      "get" : {
-        "tags" : [ "experiment" ],
-        "summary" : "List experiment's log",
-        "operationId" : "listLog",
-        "parameters" : [ {
-          "name" : "status",
-          "in" : "query",
-          "schema" : {
-            "type" : "string"
-          }
-        } ],
-        "responses" : {
-          "default" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "$ref" : "#/components/schemas/JsonResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/v1/experiment/ping" : {
-      "get" : {
-        "tags" : [ "experiment" ],
-        "summary" : "Ping submarine server",
-        "description" : "Return the Pong message for test the connectivity",
-        "operationId" : "ping",
-        "responses" : {
-          "200" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "type" : "string"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
     "/v1/template" : {
       "get" : {
         "tags" : [ "experimentTemplates" ],
@@ -679,6 +679,26 @@
         }
       }
     },
+    "/v1/model-version/ping" : {
+      "get" : {
+        "tags" : [ "model-version" ],
+        "summary" : "Ping submarine server",
+        "description" : "Return the Pong message for test the connectivity",
+        "operationId" : "ping_1",
+        "responses" : {
+          "200" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "type" : "string"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/v1/model-version" : {
       "post" : {
         "tags" : [ "model-version" ],
@@ -748,31 +768,17 @@
         }
       }
     },
-    "/v1/model-version/tag" : {
-      "post" : {
+    "/v1/model-version/{name}" : {
+      "get" : {
         "tags" : [ "model-version" ],
-        "summary" : "Create a model version tag instance",
-        "operationId" : "createModelVersionTag",
+        "summary" : "List model versions",
+        "operationId" : "listModelVersions",
         "parameters" : [ {
           "name" : "name",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        }, {
-          "name" : "version",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        }, {
-          "name" : "tag",
-          "in" : "query",
+          "in" : "path",
+          "required" : true,
           "schema" : {
-            "type" : "string",
-            "default" : ""
+            "type" : "string"
           }
         } ],
         "responses" : {
@@ -787,31 +793,27 @@
             }
           }
         }
-      },
-      "delete" : {
+      }
+    },
+    "/v1/model-version/{name}/{version}" : {
+      "get" : {
         "tags" : [ "model-version" ],
-        "summary" : "Delete a model version tag instance",
-        "operationId" : "deleteModelVersionTag",
+        "summary" : "Get detailed info about the model version",
+        "operationId" : "getModelVersion",
         "parameters" : [ {
           "name" : "name",
-          "in" : "query",
+          "in" : "path",
+          "required" : true,
           "schema" : {
-            "type" : "string",
-            "default" : ""
+            "type" : "string"
           }
         }, {
           "name" : "version",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        }, {
-          "name" : "tag",
-          "in" : "query",
+          "in" : "path",
+          "required" : true,
           "schema" : {
-            "type" : "string",
-            "default" : ""
+            "type" : "integer",
+            "format" : "int32"
           }
         } ],
         "responses" : {
@@ -824,15 +826,16 @@
                 }
               }
             }
+          },
+          "404" : {
+            "description" : "ModelVersionEntity not found"
           }
         }
-      }
-    },
-    "/v1/model-version/{name}/{version}" : {
-      "get" : {
+      },
+      "delete" : {
         "tags" : [ "model-version" ],
-        "summary" : "Get detailed info about the model version",
-        "operationId" : "getModelVersion",
+        "summary" : "Delete the model version",
+        "operationId" : "deleteModelVersion",
         "parameters" : [ {
           "name" : "name",
           "in" : "path",
@@ -864,25 +867,33 @@
             "description" : "ModelVersionEntity not found"
           }
         }
-      },
-      "delete" : {
+      }
+    },
+    "/v1/model-version/tag" : {
+      "post" : {
         "tags" : [ "model-version" ],
-        "summary" : "Delete the model version",
-        "operationId" : "deleteModelVersion",
+        "summary" : "Create a model version tag instance",
+        "operationId" : "createModelVersionTag",
         "parameters" : [ {
           "name" : "name",
-          "in" : "path",
-          "required" : true,
+          "in" : "query",
           "schema" : {
-            "type" : "string"
+            "type" : "string",
+            "default" : ""
           }
         }, {
           "name" : "version",
-          "in" : "path",
-          "required" : true,
+          "in" : "query",
           "schema" : {
-            "type" : "integer",
-            "format" : "int32"
+            "type" : "string",
+            "default" : ""
+          }
+        }, {
+          "name" : "tag",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
           }
         } ],
         "responses" : {
@@ -895,24 +906,33 @@
                 }
               }
             }
-          },
-          "404" : {
-            "description" : "ModelVersionEntity not found"
           }
         }
-      }
-    },
-    "/v1/model-version/{name}" : {
-      "get" : {
+      },
+      "delete" : {
         "tags" : [ "model-version" ],
-        "summary" : "List model versions",
-        "operationId" : "listModelVersions",
+        "summary" : "Delete a model version tag instance",
+        "operationId" : "deleteModelVersionTag",
         "parameters" : [ {
           "name" : "name",
-          "in" : "path",
-          "required" : true,
+          "in" : "query",
           "schema" : {
-            "type" : "string"
+            "type" : "string",
+            "default" : ""
+          }
+        }, {
+          "name" : "version",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
+          }
+        }, {
+          "name" : "tag",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
           }
         } ],
         "responses" : {
@@ -929,12 +949,12 @@
         }
       }
     },
-    "/v1/model-version/ping" : {
+    "/v1/notebook/ping" : {
       "get" : {
-        "tags" : [ "model-version" ],
+        "tags" : [ "notebook" ],
         "summary" : "Ping submarine server",
         "description" : "Return the Pong message for test the connectivity",
-        "operationId" : "ping_1",
+        "operationId" : "ping_2",
         "responses" : {
           "200" : {
             "description" : "successful operation",
@@ -1064,12 +1084,12 @@
         }
       }
     },
-    "/v1/notebook/ping" : {
+    "/v1/registered-model/ping" : {
       "get" : {
-        "tags" : [ "notebook" ],
+        "tags" : [ "registered-model" ],
         "summary" : "Ping submarine server",
         "description" : "Return the Pong message for test the connectivity",
-        "operationId" : "ping_2",
+        "operationId" : "ping_3",
         "responses" : {
           "200" : {
             "description" : "successful operation",
@@ -1134,72 +1154,6 @@
         }
       }
     },
-    "/v1/registered-model/tag" : {
-      "post" : {
-        "tags" : [ "registered-model" ],
-        "summary" : "Create a registered model tag instance",
-        "operationId" : "createRegisteredModelTag",
-        "parameters" : [ {
-          "name" : "name",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        }, {
-          "name" : "tag",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        } ],
-        "responses" : {
-          "default" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "$ref" : "#/components/schemas/JsonResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "delete" : {
-        "tags" : [ "registered-model" ],
-        "summary" : "Delete a registered model tag instance",
-        "operationId" : "deleteRegisteredModelTag",
-        "parameters" : [ {
-          "name" : "name",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        }, {
-          "name" : "tag",
-          "in" : "query",
-          "schema" : {
-            "type" : "string",
-            "default" : ""
-          }
-        } ],
-        "responses" : {
-          "default" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "$ref" : "#/components/schemas/JsonResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
     "/v1/registered-model/{name}" : {
       "get" : {
         "tags" : [ "registered-model" ],
@@ -1301,12 +1255,78 @@
         }
       }
     },
-    "/v1/registered-model/ping" : {
-      "get" : {
+    "/v1/registered-model/tag" : {
+      "post" : {
+        "tags" : [ "registered-model" ],
+        "summary" : "Create a registered model tag instance",
+        "operationId" : "createRegisteredModelTag",
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
+          }
+        }, {
+          "name" : "tag",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
+          }
+        } ],
+        "responses" : {
+          "default" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/JsonResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "delete" : {
         "tags" : [ "registered-model" ],
+        "summary" : "Delete a registered model tag instance",
+        "operationId" : "deleteRegisteredModelTag",
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
+          }
+        }, {
+          "name" : "tag",
+          "in" : "query",
+          "schema" : {
+            "type" : "string",
+            "default" : ""
+          }
+        } ],
+        "responses" : {
+          "default" : {
+            "description" : "successful operation",
+            "content" : {
+              "application/json; charset=utf-8" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/JsonResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/v1/serve/ping" : {
+      "get" : {
+        "tags" : [ "serve" ],
         "summary" : "Ping submarine server",
         "description" : "Return the Pong message for test the connectivity",
-        "operationId" : "ping_3",
+        "operationId" : "ping_4",
         "responses" : {
           "200" : {
             "description" : "successful operation",
@@ -1382,26 +1402,6 @@
           }
         }
       }
-    },
-    "/v1/serve/ping" : {
-      "get" : {
-        "tags" : [ "serve" ],
-        "summary" : "Ping submarine server",
-        "description" : "Return the Pong message for test the connectivity",
-        "operationId" : "ping_4",
-        "responses" : {
-          "200" : {
-            "description" : "successful operation",
-            "content" : {
-              "application/json; charset=utf-8" : {
-                "schema" : {
-                  "type" : "string"
-                }
-              }
-            }
-          }
-        }
-      }
     }
   },
   "components" : {
@@ -1473,28 +1473,14 @@
           }
         }
       },
-      "ExperimentTemplateSubmit" : {
-        "type" : "object",
-        "properties" : {
-          "name" : {
-            "type" : "string"
-          },
-          "params" : {
-            "type" : "object",
-            "additionalProperties" : {
-              "type" : "string"
-            }
-          }
-        }
-      },
       "CodeSpec" : {
         "type" : "object",
         "properties" : {
           "syncMode" : {
             "type" : "string"
           },
-          "url" : {
-            "type" : "string"
+          "git" : {
+            "$ref" : "#/components/schemas/GitCodeSpec"
           }
         }
       },
@@ -1581,14 +1567,48 @@
               "type" : "string"
             }
           },
+          "memory" : {
+            "type" : "string"
+          },
           "cpu" : {
             "type" : "string"
           },
           "gpu" : {
             "type" : "string"
+          }
+        }
+      },
+      "GitCodeSpec" : {
+        "type" : "object",
+        "properties" : {
+          "url" : {
+            "type" : "string"
           },
-          "memory" : {
+          "branch" : {
+            "type" : "string"
+          },
+          "username" : {
+            "type" : "string"
+          },
+          "password" : {
+            "type" : "string"
+          },
+          "trustCerts" : {
+            "type" : "boolean"
+          }
+        }
+      },
+      "ExperimentTemplateSubmit" : {
+        "type" : "object",
+        "properties" : {
+          "name" : {
             "type" : "string"
+          },
+          "params" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "type" : "string"
+            }
           }
         }
       },
@@ -1721,13 +1741,13 @@
           "resources" : {
             "type" : "string"
           },
-          "cpu" : {
+          "memory" : {
             "type" : "string"
           },
-          "gpu" : {
+          "cpu" : {
             "type" : "string"
           },
-          "memory" : {
+          "gpu" : {
             "type" : "string"
           }
         }
diff --git a/submarine-sdk/pysubmarine/example/submarine_experiment_sdk.ipynb 
b/submarine-sdk/pysubmarine/example/submarine_experiment_sdk.ipynb
index 63012a41..13b2214d 100644
--- a/submarine-sdk/pysubmarine/example/submarine_experiment_sdk.ipynb
+++ b/submarine-sdk/pysubmarine/example/submarine_experiment_sdk.ipynb
@@ -95,7 +95,7 @@
     "\n",
     "worker_spec = ExperimentTaskSpec(resources=\"cpu=1,memory=1024M\", 
replicas=1)\n",
     "ps_spec = ExperimentTaskSpec(resources=\"cpu=1,memory=1024M\", 
replicas=1)\n",
-    "code_spec = CodeSpec(sync_mode=\"git\", 
url=\"https://github.com/apache/submarine.git\";)\n",
+    "code_spec = CodeSpec(sync_mode=\"git\", 
GitCodeSpec=(url=\"https://github.com/apache/submarine.git\";))\n",
     "\n",
     "experiment_spec = ExperimentSpec(\n",
     "    meta=experiment_meta,\n",
@@ -159,7 +159,7 @@
        "    'envVars': None,\n",
        "    'resourceMap': {'memory': '1024M', 'cpu': '1'}}},\n",
        "  'code': {'syncMode': 'git',\n",
-       "   'url': 'https://github.com/apache/submarine.git'}}}"
+       "   'git': {'url': 'https://github.com/apache/submarine.git'}}}}"
       ]
      },
      "execution_count": 5,
@@ -520,7 +520,7 @@
        "    'envVars': None,\n",
        "    'resourceMap': {'memory': '1024M', 'cpu': '1'}}},\n",
        "  'code': {'syncMode': 'git',\n",
-       "   'url': 'https://github.com/apache/submarine.git'}}}"
+       "   'git': {'url': 'https://github.com/apache/submarine.git'}}}}"
       ]
      },
      "execution_count": 10,
diff --git a/submarine-sdk/pysubmarine/setup.py 
b/submarine-sdk/pysubmarine/setup.py
index 506d616d..d66520c1 100644
--- a/submarine-sdk/pysubmarine/setup.py
+++ b/submarine-sdk/pysubmarine/setup.py
@@ -52,7 +52,7 @@ setup(
             "keras>=2.6.0",
             "protobuf>=3.9.2,<3.20",
             "tensorflow-addons==0.17.0",
-            "tensorflow-estimator>=2.9.0rc0,<2.10.0",
+            "tensorflow-estimator>=2.6.0,<2.10.0",
             "tf_slim==1.1.0",
             # todo(cdmikechen): Based on SUBMARINE-1372, typeguard has 
recently been upgraded to version 3.0,
             #                   which will restrict some python syntax and 
types more tightly.
diff --git a/submarine-sdk/pysubmarine/submarine/client/__init__.py 
b/submarine-sdk/pysubmarine/submarine/client/__init__.py
index ae9d7b53..08034ec8 100644
--- a/submarine-sdk/pysubmarine/submarine/client/__init__.py
+++ b/submarine-sdk/pysubmarine/submarine/client/__init__.py
@@ -64,6 +64,7 @@ from submarine.client.models.experiment_template_param_spec 
import (
 )
 from submarine.client.models.experiment_template_spec import 
ExperimentTemplateSpec
 from submarine.client.models.experiment_template_submit import 
ExperimentTemplateSubmit
+from submarine.client.models.git_code_spec import GitCodeSpec
 from submarine.client.models.json_response import JsonResponse
 from submarine.client.models.kernel_spec import KernelSpec
 from submarine.client.models.model_version_entity import ModelVersionEntity
diff --git a/submarine-sdk/pysubmarine/submarine/client/models/__init__.py 
b/submarine-sdk/pysubmarine/submarine/client/models/__init__.py
index 1cb407d9..84995761 100644
--- a/submarine-sdk/pysubmarine/submarine/client/models/__init__.py
+++ b/submarine-sdk/pysubmarine/submarine/client/models/__init__.py
@@ -40,6 +40,7 @@ from submarine.client.models.experiment_template_param_spec 
import (
 )
 from submarine.client.models.experiment_template_spec import 
ExperimentTemplateSpec
 from submarine.client.models.experiment_template_submit import 
ExperimentTemplateSubmit
+from submarine.client.models.git_code_spec import GitCodeSpec
 from submarine.client.models.json_response import JsonResponse
 from submarine.client.models.kernel_spec import KernelSpec
 from submarine.client.models.model_version_entity import ModelVersionEntity
diff --git a/submarine-sdk/pysubmarine/submarine/client/models/code_spec.py 
b/submarine-sdk/pysubmarine/submarine/client/models/code_spec.py
index 2cd8e0ab..499850a5 100644
--- a/submarine-sdk/pysubmarine/submarine/client/models/code_spec.py
+++ b/submarine-sdk/pysubmarine/submarine/client/models/code_spec.py
@@ -48,24 +48,24 @@ class CodeSpec(object):
       attribute_map (dict): The key is attribute name
                             and the value is json key in definition.
     """
-    openapi_types = {'sync_mode': 'str', 'url': 'str'}
+    openapi_types = {'sync_mode': 'str', 'git': 'GitCodeSpec'}
 
-    attribute_map = {'sync_mode': 'syncMode', 'url': 'url'}
+    attribute_map = {'sync_mode': 'syncMode', 'git': 'git'}
 
-    def __init__(self, sync_mode=None, url=None, 
local_vars_configuration=None):  # noqa: E501
+    def __init__(self, sync_mode=None, git=None, 
local_vars_configuration=None):  # noqa: E501
         """CodeSpec - a model defined in OpenAPI"""  # noqa: E501
         if local_vars_configuration is None:
             local_vars_configuration = Configuration()
         self.local_vars_configuration = local_vars_configuration
 
         self._sync_mode = None
-        self._url = None
+        self._git = None
         self.discriminator = None
 
         if sync_mode is not None:
             self.sync_mode = sync_mode
-        if url is not None:
-            self.url = url
+        if git is not None:
+            self.git = git
 
     @property
     def sync_mode(self):
@@ -89,25 +89,25 @@ class CodeSpec(object):
         self._sync_mode = sync_mode
 
     @property
-    def url(self):
-        """Gets the url of this CodeSpec.  # noqa: E501
+    def git(self):
+        """Gets the git of this CodeSpec.  # noqa: E501
 
 
-        :return: The url of this CodeSpec.  # noqa: E501
-        :rtype: str
+        :return: The git of this CodeSpec.  # noqa: E501
+        :rtype: GitCodeSpec
         """
-        return self._url
+        return self._git
 
-    @url.setter
-    def url(self, url):
-        """Sets the url of this CodeSpec.
+    @git.setter
+    def git(self, git):
+        """Sets the git of this CodeSpec.
 
 
-        :param url: The url of this CodeSpec.  # noqa: E501
-        :type: str
+        :param git: The git of this CodeSpec.  # noqa: E501
+        :type: GitCodeSpec
         """
 
-        self._url = url
+        self._git = git
 
     def to_dict(self):
         """Returns the model properties as a dict"""
diff --git 
a/submarine-sdk/pysubmarine/submarine/client/models/experiment_task_spec.py 
b/submarine-sdk/pysubmarine/submarine/client/models/experiment_task_spec.py
index 70f896d4..274e433e 100644
--- a/submarine-sdk/pysubmarine/submarine/client/models/experiment_task_spec.py
+++ b/submarine-sdk/pysubmarine/submarine/client/models/experiment_task_spec.py
@@ -55,9 +55,9 @@ class ExperimentTaskSpec(object):
         'image': 'str',
         'cmd': 'str',
         'env_vars': 'dict(str, str)',
+        'memory': 'str',
         'cpu': 'str',
         'gpu': 'str',
-        'memory': 'str',
     }
 
     attribute_map = {
@@ -67,9 +67,9 @@ class ExperimentTaskSpec(object):
         'image': 'image',
         'cmd': 'cmd',
         'env_vars': 'envVars',
+        'memory': 'memory',
         'cpu': 'cpu',
         'gpu': 'gpu',
-        'memory': 'memory',
     }
 
     def __init__(
@@ -80,9 +80,9 @@ class ExperimentTaskSpec(object):
         image=None,
         cmd=None,
         env_vars=None,
+        memory=None,
         cpu=None,
         gpu=None,
-        memory=None,
         local_vars_configuration=None,
     ):  # noqa: E501
         """ExperimentTaskSpec - a model defined in OpenAPI"""  # noqa: E501
@@ -96,9 +96,9 @@ class ExperimentTaskSpec(object):
         self._image = None
         self._cmd = None
         self._env_vars = None
+        self._memory = None
         self._cpu = None
         self._gpu = None
-        self._memory = None
         self.discriminator = None
 
         if replicas is not None:
@@ -113,12 +113,12 @@ class ExperimentTaskSpec(object):
             self.cmd = cmd
         if env_vars is not None:
             self.env_vars = env_vars
+        if memory is not None:
+            self.memory = memory
         if cpu is not None:
             self.cpu = cpu
         if gpu is not None:
             self.gpu = gpu
-        if memory is not None:
-            self.memory = memory
 
     @property
     def replicas(self):
@@ -246,6 +246,27 @@ class ExperimentTaskSpec(object):
 
         self._env_vars = env_vars
 
+    @property
+    def memory(self):
+        """Gets the memory of this ExperimentTaskSpec.  # noqa: E501
+
+
+        :return: The memory of this ExperimentTaskSpec.  # noqa: E501
+        :rtype: str
+        """
+        return self._memory
+
+    @memory.setter
+    def memory(self, memory):
+        """Sets the memory of this ExperimentTaskSpec.
+
+
+        :param memory: The memory of this ExperimentTaskSpec.  # noqa: E501
+        :type: str
+        """
+
+        self._memory = memory
+
     @property
     def cpu(self):
         """Gets the cpu of this ExperimentTaskSpec.  # noqa: E501
@@ -288,27 +309,6 @@ class ExperimentTaskSpec(object):
 
         self._gpu = gpu
 
-    @property
-    def memory(self):
-        """Gets the memory of this ExperimentTaskSpec.  # noqa: E501
-
-
-        :return: The memory of this ExperimentTaskSpec.  # noqa: E501
-        :rtype: str
-        """
-        return self._memory
-
-    @memory.setter
-    def memory(self, memory):
-        """Sets the memory of this ExperimentTaskSpec.
-
-
-        :param memory: The memory of this ExperimentTaskSpec.  # noqa: E501
-        :type: str
-        """
-
-        self._memory = memory
-
     def to_dict(self):
         """Returns the model properties as a dict"""
         result = {}
diff --git 
a/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py 
b/submarine-sdk/pysubmarine/submarine/client/models/git_code_spec.py
similarity index 56%
copy from submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py
copy to submarine-sdk/pysubmarine/submarine/client/models/git_code_spec.py
index cf1855f4..91b84c0b 100644
--- a/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py
+++ b/submarine-sdk/pysubmarine/submarine/client/models/git_code_spec.py
@@ -34,7 +34,7 @@ import six
 from submarine.client.configuration import Configuration
 
 
-class NotebookPodSpec(object):
+class GitCodeSpec(object):
     """NOTE: This class is auto generated by OpenAPI Generator.
     Ref: https://openapi-generator.tech
 
@@ -49,151 +49,157 @@ class NotebookPodSpec(object):
                             and the value is json key in definition.
     """
     openapi_types = {
-        'env_vars': 'dict(str, str)',
-        'resources': 'str',
-        'cpu': 'str',
-        'gpu': 'str',
-        'memory': 'str',
+        'url': 'str',
+        'branch': 'str',
+        'username': 'str',
+        'password': 'str',
+        'trust_certs': 'bool',
     }
 
     attribute_map = {
-        'env_vars': 'envVars',
-        'resources': 'resources',
-        'cpu': 'cpu',
-        'gpu': 'gpu',
-        'memory': 'memory',
+        'url': 'url',
+        'branch': 'branch',
+        'username': 'username',
+        'password': 'password',
+        'trust_certs': 'trustCerts',
     }
 
     def __init__(
-        self, env_vars=None, resources=None, cpu=None, gpu=None, memory=None, 
local_vars_configuration=None
+        self,
+        url=None,
+        branch=None,
+        username=None,
+        password=None,
+        trust_certs=None,
+        local_vars_configuration=None,
     ):  # noqa: E501
-        """NotebookPodSpec - a model defined in OpenAPI"""  # noqa: E501
+        """GitCodeSpec - a model defined in OpenAPI"""  # noqa: E501
         if local_vars_configuration is None:
             local_vars_configuration = Configuration()
         self.local_vars_configuration = local_vars_configuration
 
-        self._env_vars = None
-        self._resources = None
-        self._cpu = None
-        self._gpu = None
-        self._memory = None
+        self._url = None
+        self._branch = None
+        self._username = None
+        self._password = None
+        self._trust_certs = None
         self.discriminator = None
 
-        if env_vars is not None:
-            self.env_vars = env_vars
-        if resources is not None:
-            self.resources = resources
-        if cpu is not None:
-            self.cpu = cpu
-        if gpu is not None:
-            self.gpu = gpu
-        if memory is not None:
-            self.memory = memory
+        if url is not None:
+            self.url = url
+        if branch is not None:
+            self.branch = branch
+        if username is not None:
+            self.username = username
+        if password is not None:
+            self.password = password
+        if trust_certs is not None:
+            self.trust_certs = trust_certs
 
     @property
-    def env_vars(self):
-        """Gets the env_vars of this NotebookPodSpec.  # noqa: E501
+    def url(self):
+        """Gets the url of this GitCodeSpec.  # noqa: E501
 
 
-        :return: The env_vars of this NotebookPodSpec.  # noqa: E501
-        :rtype: dict(str, str)
+        :return: The url of this GitCodeSpec.  # noqa: E501
+        :rtype: str
         """
-        return self._env_vars
+        return self._url
 
-    @env_vars.setter
-    def env_vars(self, env_vars):
-        """Sets the env_vars of this NotebookPodSpec.
+    @url.setter
+    def url(self, url):
+        """Sets the url of this GitCodeSpec.
 
 
-        :param env_vars: The env_vars of this NotebookPodSpec.  # noqa: E501
-        :type: dict(str, str)
+        :param url: The url of this GitCodeSpec.  # noqa: E501
+        :type: str
         """
 
-        self._env_vars = env_vars
+        self._url = url
 
     @property
-    def resources(self):
-        """Gets the resources of this NotebookPodSpec.  # noqa: E501
+    def branch(self):
+        """Gets the branch of this GitCodeSpec.  # noqa: E501
 
 
-        :return: The resources of this NotebookPodSpec.  # noqa: E501
+        :return: The branch of this GitCodeSpec.  # noqa: E501
         :rtype: str
         """
-        return self._resources
+        return self._branch
 
-    @resources.setter
-    def resources(self, resources):
-        """Sets the resources of this NotebookPodSpec.
+    @branch.setter
+    def branch(self, branch):
+        """Sets the branch of this GitCodeSpec.
 
 
-        :param resources: The resources of this NotebookPodSpec.  # noqa: E501
+        :param branch: The branch of this GitCodeSpec.  # noqa: E501
         :type: str
         """
 
-        self._resources = resources
+        self._branch = branch
 
     @property
-    def cpu(self):
-        """Gets the cpu of this NotebookPodSpec.  # noqa: E501
+    def username(self):
+        """Gets the username of this GitCodeSpec.  # noqa: E501
 
 
-        :return: The cpu of this NotebookPodSpec.  # noqa: E501
+        :return: The username of this GitCodeSpec.  # noqa: E501
         :rtype: str
         """
-        return self._cpu
+        return self._username
 
-    @cpu.setter
-    def cpu(self, cpu):
-        """Sets the cpu of this NotebookPodSpec.
+    @username.setter
+    def username(self, username):
+        """Sets the username of this GitCodeSpec.
 
 
-        :param cpu: The cpu of this NotebookPodSpec.  # noqa: E501
+        :param username: The username of this GitCodeSpec.  # noqa: E501
         :type: str
         """
 
-        self._cpu = cpu
+        self._username = username
 
     @property
-    def gpu(self):
-        """Gets the gpu of this NotebookPodSpec.  # noqa: E501
+    def password(self):
+        """Gets the password of this GitCodeSpec.  # noqa: E501
 
 
-        :return: The gpu of this NotebookPodSpec.  # noqa: E501
+        :return: The password of this GitCodeSpec.  # noqa: E501
         :rtype: str
         """
-        return self._gpu
+        return self._password
 
-    @gpu.setter
-    def gpu(self, gpu):
-        """Sets the gpu of this NotebookPodSpec.
+    @password.setter
+    def password(self, password):
+        """Sets the password of this GitCodeSpec.
 
 
-        :param gpu: The gpu of this NotebookPodSpec.  # noqa: E501
+        :param password: The password of this GitCodeSpec.  # noqa: E501
         :type: str
         """
 
-        self._gpu = gpu
+        self._password = password
 
     @property
-    def memory(self):
-        """Gets the memory of this NotebookPodSpec.  # noqa: E501
+    def trust_certs(self):
+        """Gets the trust_certs of this GitCodeSpec.  # noqa: E501
 
 
-        :return: The memory of this NotebookPodSpec.  # noqa: E501
-        :rtype: str
+        :return: The trust_certs of this GitCodeSpec.  # noqa: E501
+        :rtype: bool
         """
-        return self._memory
+        return self._trust_certs
 
-    @memory.setter
-    def memory(self, memory):
-        """Sets the memory of this NotebookPodSpec.
+    @trust_certs.setter
+    def trust_certs(self, trust_certs):
+        """Sets the trust_certs of this GitCodeSpec.
 
 
-        :param memory: The memory of this NotebookPodSpec.  # noqa: E501
-        :type: str
+        :param trust_certs: The trust_certs of this GitCodeSpec.  # noqa: E501
+        :type: bool
         """
 
-        self._memory = memory
+        self._trust_certs = trust_certs
 
     def to_dict(self):
         """Returns the model properties as a dict"""
@@ -227,14 +233,14 @@ class NotebookPodSpec(object):
 
     def __eq__(self, other):
         """Returns true if both objects are equal"""
-        if not isinstance(other, NotebookPodSpec):
+        if not isinstance(other, GitCodeSpec):
             return False
 
         return self.to_dict() == other.to_dict()
 
     def __ne__(self, other):
         """Returns true if both objects are not equal"""
-        if not isinstance(other, NotebookPodSpec):
+        if not isinstance(other, GitCodeSpec):
             return True
 
         return self.to_dict() != other.to_dict()
diff --git 
a/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py 
b/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py
index cf1855f4..2e0969b8 100644
--- a/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py
+++ b/submarine-sdk/pysubmarine/submarine/client/models/notebook_pod_spec.py
@@ -51,21 +51,21 @@ class NotebookPodSpec(object):
     openapi_types = {
         'env_vars': 'dict(str, str)',
         'resources': 'str',
+        'memory': 'str',
         'cpu': 'str',
         'gpu': 'str',
-        'memory': 'str',
     }
 
     attribute_map = {
         'env_vars': 'envVars',
         'resources': 'resources',
+        'memory': 'memory',
         'cpu': 'cpu',
         'gpu': 'gpu',
-        'memory': 'memory',
     }
 
     def __init__(
-        self, env_vars=None, resources=None, cpu=None, gpu=None, memory=None, 
local_vars_configuration=None
+        self, env_vars=None, resources=None, memory=None, cpu=None, gpu=None, 
local_vars_configuration=None
     ):  # noqa: E501
         """NotebookPodSpec - a model defined in OpenAPI"""  # noqa: E501
         if local_vars_configuration is None:
@@ -74,21 +74,21 @@ class NotebookPodSpec(object):
 
         self._env_vars = None
         self._resources = None
+        self._memory = None
         self._cpu = None
         self._gpu = None
-        self._memory = None
         self.discriminator = None
 
         if env_vars is not None:
             self.env_vars = env_vars
         if resources is not None:
             self.resources = resources
+        if memory is not None:
+            self.memory = memory
         if cpu is not None:
             self.cpu = cpu
         if gpu is not None:
             self.gpu = gpu
-        if memory is not None:
-            self.memory = memory
 
     @property
     def env_vars(self):
@@ -132,6 +132,27 @@ class NotebookPodSpec(object):
 
         self._resources = resources
 
+    @property
+    def memory(self):
+        """Gets the memory of this NotebookPodSpec.  # noqa: E501
+
+
+        :return: The memory of this NotebookPodSpec.  # noqa: E501
+        :rtype: str
+        """
+        return self._memory
+
+    @memory.setter
+    def memory(self, memory):
+        """Sets the memory of this NotebookPodSpec.
+
+
+        :param memory: The memory of this NotebookPodSpec.  # noqa: E501
+        :type: str
+        """
+
+        self._memory = memory
+
     @property
     def cpu(self):
         """Gets the cpu of this NotebookPodSpec.  # noqa: E501
@@ -174,27 +195,6 @@ class NotebookPodSpec(object):
 
         self._gpu = gpu
 
-    @property
-    def memory(self):
-        """Gets the memory of this NotebookPodSpec.  # noqa: E501
-
-
-        :return: The memory of this NotebookPodSpec.  # noqa: E501
-        :rtype: str
-        """
-        return self._memory
-
-    @memory.setter
-    def memory(self, memory):
-        """Sets the memory of this NotebookPodSpec.
-
-
-        :param memory: The memory of this NotebookPodSpec.  # noqa: E501
-        :type: str
-        """
-
-        self._memory = memory
-
     def to_dict(self):
         """Returns the model properties as a dict"""
         result = {}
diff --git a/submarine-sdk/pysubmarine/tests/cli/test_experiment.py 
b/submarine-sdk/pysubmarine/tests/cli/test_experiment.py
index b46bd83e..bd0e3c23 100644
--- a/submarine-sdk/pysubmarine/tests/cli/test_experiment.py
+++ b/submarine-sdk/pysubmarine/tests/cli/test_experiment.py
@@ -18,6 +18,7 @@ from click.testing import CliRunner
 
 import submarine
 from submarine.cli import main
+from submarine.client import GitCodeSpec
 from submarine.client.models.code_spec import CodeSpec
 from submarine.client.models.environment_spec import EnvironmentSpec
 from submarine.client.models.experiment_meta import ExperimentMeta
@@ -56,7 +57,7 @@ def test_all_experiment_e2e():
     worker_spec = ExperimentTaskSpec(resources="cpu=1,memory=1024M", 
replicas=1)
     ps_spec = ExperimentTaskSpec(resources="cpu=1,memory=1024M", replicas=1)
 
-    code_spec = CodeSpec(sync_mode="git", 
url="https://github.com/apache/submarine.git";)
+    code_spec = CodeSpec(sync_mode="git", 
git=GitCodeSpec(url="https://github.com/apache/submarine.git";))
 
     experiment_spec = ExperimentSpec(
         meta=experiment_meta,
diff --git 
a/submarine-sdk/pysubmarine/tests/experiment/test_experiment_client.py 
b/submarine-sdk/pysubmarine/tests/experiment/test_experiment_client.py
index c7c47693..adbd0fff 100644
--- a/submarine-sdk/pysubmarine/tests/experiment/test_experiment_client.py
+++ b/submarine-sdk/pysubmarine/tests/experiment/test_experiment_client.py
@@ -16,6 +16,7 @@
 import pytest
 
 import submarine
+from submarine.client import GitCodeSpec
 from submarine.client.models.code_spec import CodeSpec
 from submarine.client.models.environment_spec import EnvironmentSpec
 from submarine.client.models.experiment_meta import ExperimentMeta
@@ -38,7 +39,7 @@ def test_experiment_e2e():
     worker_spec = ExperimentTaskSpec(resources="cpu=1,memory=1024M", 
replicas=1)
     ps_spec = ExperimentTaskSpec(resources="cpu=1,memory=1024M", replicas=1)
 
-    code_spec = CodeSpec(sync_mode="git", 
url="https://github.com/apache/submarine.git";)
+    code_spec = CodeSpec(sync_mode="git", 
git=GitCodeSpec(url="https://github.com/apache/submarine.git";))
 
     experiment_spec = ExperimentSpec(
         meta=experiment_meta,
diff --git 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/CodeSpec.java
 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/CodeSpec.java
index 71585e1a..e7841088 100644
--- 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/CodeSpec.java
+++ 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/CodeSpec.java
@@ -19,12 +19,14 @@
 
 package org.apache.submarine.server.api.spec;
 
+import org.apache.submarine.server.api.spec.code.GitCodeSpec;
+
 public class CodeSpec {
-  
+
   private String syncMode;
-  
-  private String url;
-  
+
+  private GitCodeSpec git;
+
   public String getSyncMode() {
     return syncMode;
   }
@@ -33,11 +35,11 @@ public class CodeSpec {
     this.syncMode = syncMode;
   }
 
-  public String getUrl() {
-    return url;
+  public GitCodeSpec getGit() {
+    return git;
   }
 
-  public void setUrl(String url) {
-    this.url = url;
+  public void setGit(GitCodeSpec git) {
+    this.git = git;
   }
 }
diff --git 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/ExperimentSpec.java
 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/ExperimentSpec.java
index 8c3024d6..99a36d3b 100644
--- 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/ExperimentSpec.java
+++ 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/ExperimentSpec.java
@@ -64,7 +64,7 @@ public class ExperimentSpec {
   public void setCode(CodeSpec code) {
     this.code = code;
   }
-  
+
   public Map<String, String> getExperimentHandlerSpec() {
     return experimentHandlerSpec;
   }
diff --git 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/code/GitCodeSpec.java
 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/code/GitCodeSpec.java
new file mode 100644
index 00000000..34dcfe6d
--- /dev/null
+++ 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/code/GitCodeSpec.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.api.spec.code;
+
+/**
+ * Describes some of the main variable properties of git code
+ */
+public class GitCodeSpec {
+
+  /**
+   * Default git branch.
+   * The new git branch has changed from master to main
+   */
+  public static final String DEFAULT_BRANCH = "main";
+
+  private String url;
+
+  private String branch = DEFAULT_BRANCH;
+
+  private String username;
+
+  private String password;
+
+  /**
+   * Whether the git-sync should trust a self-signed certificate
+   */
+  private Boolean trustCerts;
+
+  public GitCodeSpec() {
+  }
+
+  public GitCodeSpec(String url) {
+    this.url = url;
+  }
+
+  public void setUrl(String url) {
+    this.url = url;
+  }
+
+  public String getUrl() {
+    return url;
+  }
+
+  public String getBranch() {
+    return branch == null || branch.isBlank() ? DEFAULT_BRANCH : branch;
+  }
+
+  public void setBranch(String branch) {
+    this.branch = branch;
+  }
+
+  public String getUsername() {
+    return username;
+  }
+
+  public void setUsername(String username) {
+    this.username = username;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public Boolean getTrustCerts() {
+    return trustCerts;
+  }
+
+  public void setTrustCerts(Boolean trustCerts) {
+    this.trustCerts = trustCerts;
+  }
+}
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/AbstractCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/AbstractCodeLocalizer.java
index ff25f27c..841cf3c0 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/AbstractCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/AbstractCodeLocalizer.java
@@ -24,6 +24,7 @@ import 
org.apache.submarine.server.api.exception.InvalidSpecException;
 import io.kubernetes.client.openapi.models.V1EmptyDirVolumeSource;
 import io.kubernetes.client.openapi.models.V1PodSpec;
 import io.kubernetes.client.openapi.models.V1Volume;
+import org.apache.submarine.server.api.spec.CodeSpec;
 
 public abstract class AbstractCodeLocalizer implements CodeLocalizer {
 
@@ -31,18 +32,6 @@ public abstract class AbstractCodeLocalizer implements 
CodeLocalizer {
   public static final String CODE_LOCALIZER_MOUNT_NAME = "code-dir";
   public static final String CODE_LOCALIZER_INIT_CONTAINER_NAME = 
"code-localizer";
   public static final String CODE_LOCALIZER_PATH_ENV_VAR = "CODE_PATH";
-  private String url;
-
-  public AbstractCodeLocalizer(String url) {
-    this.url = url;
-  }
-
-  /**
-   * @return the url
-   */
-  public String getUrl() {
-    return url;
-  }
 
   @Override
   public void localize(V1PodSpec podSpec) {
@@ -52,12 +41,13 @@ public abstract class AbstractCodeLocalizer implements 
CodeLocalizer {
     podSpec.addVolumesItem(volume);
   }
 
-  public static CodeLocalizer getCodeLocalizer(String syncMode, String url)
+  public static CodeLocalizer getCodeLocalizer(CodeSpec codeSpec)
       throws InvalidSpecException {
-    if (syncMode.equals(CodeLocalizerModes.GIT.getMode())) {
-      return GitCodeLocalizer.getGitCodeLocalizer(url);
+    CodeLocalizerModes syncMode = 
CodeLocalizerModes.valueOfSyncMode(codeSpec.getSyncMode());
+    if (syncMode.equals(CodeLocalizerModes.GIT)) {
+      return GitCodeLocalizer.getGitCodeLocalizer(codeSpec.getGit());
     } else {
-      return new DummyCodeLocalizer(url);
+      return new DummyCodeLocalizer();
     }
   }
 
@@ -74,5 +64,17 @@ public abstract class AbstractCodeLocalizer implements 
CodeLocalizer {
     public String getMode() {
       return this.mode;
     }
+
+    /**
+     * Get CodeLocalizerModes by code key
+     */
+    public static CodeLocalizerModes valueOfSyncMode(String key) {
+      for (CodeLocalizerModes clm : values()) {
+        if (clm.mode.equals(key)) {
+          return clm;
+        }
+      }
+      return GIT;
+    }
   }
 }
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/DummyCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/DummyCodeLocalizer.java
index 4f08f27f..e7fbdb44 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/DummyCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/DummyCodeLocalizer.java
@@ -23,8 +23,7 @@ import io.kubernetes.client.openapi.models.V1PodSpec;
 
 public class DummyCodeLocalizer extends AbstractCodeLocalizer {
 
-  public DummyCodeLocalizer(String url) {
-    super(url);
+  public DummyCodeLocalizer() {
   }
 
   @Override
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/GitCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/GitCodeLocalizer.java
index bded2c3a..0d818457 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/GitCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/GitCodeLocalizer.java
@@ -24,19 +24,31 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.submarine.server.api.exception.InvalidSpecException;
-
 import io.kubernetes.client.openapi.models.V1Container;
 import io.kubernetes.client.openapi.models.V1EnvVar;
 import io.kubernetes.client.openapi.models.V1PodSpec;
 import io.kubernetes.client.openapi.models.V1VolumeMount;
+import org.apache.submarine.server.api.exception.InvalidSpecException;
+
+import org.apache.submarine.server.api.spec.code.GitCodeSpec;
+import org.apache.submarine.server.submitter.k8s.util.K8sResourceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class GitCodeLocalizer extends AbstractCodeLocalizer {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(GitCodeLocalizer.class);
+
   public static final String GIT_SYNC_IMAGE = 
"apache/submarine:git-sync-3.1.6";
 
-  public GitCodeLocalizer(String url) {
-    super(url);
+  private final GitCodeSpec codeSpec;
+
+  public GitCodeLocalizer(GitCodeSpec codeSpec) {
+    this.codeSpec = codeSpec;
+  }
+
+  public GitCodeSpec getCodeSpec() {
+    return codeSpec;
   }
 
   public void localize(V1PodSpec podSpec) {
@@ -45,27 +57,36 @@ public abstract class GitCodeLocalizer extends 
AbstractCodeLocalizer {
     container.setName(CODE_LOCALIZER_INIT_CONTAINER_NAME);
     container.setImage(GIT_SYNC_IMAGE);
 
-    V1EnvVar repoEnv = new V1EnvVar();
-    repoEnv.setName("GIT_SYNC_REPO");
-    repoEnv.setValue(this.getUrl());
-
-    V1EnvVar rootEnv = new V1EnvVar();
-    rootEnv.setName("GIT_SYNC_ROOT");
-    rootEnv.setValue(CODE_LOCALIZER_PATH);
-
-    V1EnvVar destEnv = new V1EnvVar();
-    destEnv.setName("GIT_SYNC_DEST");
-    destEnv.setValue("current");
+    // Add some default git sync envs
+    // The current git environment variables supported by git-syn can be 
referred to:
+    // https://github.com/kubernetes/git-sync/blob/v3.1.6/cmd/git-sync/main.go
+    List<V1EnvVar> gitSyncEnvVars = new ArrayList<V1EnvVar>();
 
-    V1EnvVar oneTimeEnv = new V1EnvVar();
-    oneTimeEnv.setName("GIT_SYNC_ONE_TIME");
-    oneTimeEnv.setValue("true");
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_REPO", 
getCodeSpec().getUrl()));
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_ROOT", 
CODE_LOCALIZER_PATH));
+    // Our scenario is usually to download the latest code once and execute it,
+    // so we set depth to 1 to prevent the code base from getting too large
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_DEPTH", "1"));
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_DEST", 
"current"));
+    // Download first and then exit
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_ONE_TIME", 
"true"));
+    // branch
+    gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_BRANCH", 
getCodeSpec().getBranch()));
+
+    // Add some optional git sync envs
+    //  username
+    if (getCodeSpec().getUsername() != null) {
+      gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_USERNAME", 
getCodeSpec().getUsername()));
+    }
+    //  password
+    if (getCodeSpec().getPassword() != null) {
+      gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SYNC_PASSWORD", 
getCodeSpec().getPassword()));
+    }
+    //  accept a self-signed certificate host
+    if (getCodeSpec().getTrustCerts() != null && 
getCodeSpec().getTrustCerts()) {
+      gitSyncEnvVars.add(K8sResourceUtils.createEnvVar("GIT_SSL_NO_VERIFY", 
"true"));
+    }
 
-    List<V1EnvVar> gitSyncEnvVars = new ArrayList<V1EnvVar>();
-    gitSyncEnvVars.add(repoEnv);
-    gitSyncEnvVars.add(rootEnv);
-    gitSyncEnvVars.add(destEnv);
-    gitSyncEnvVars.add(oneTimeEnv);
     container.setEnv(gitSyncEnvVars);
 
     V1VolumeMount mount = new V1VolumeMount();
@@ -82,18 +103,24 @@ public abstract class GitCodeLocalizer extends 
AbstractCodeLocalizer {
     super.localize(podSpec);
   }
 
-  public static CodeLocalizer getGitCodeLocalizer(String url)
+  /**
+   * Currently, we mainly support https and ssh.
+   * By default, we use https.
+   */
+  public static CodeLocalizer getGitCodeLocalizer(GitCodeSpec gitCodeSpec)
       throws InvalidSpecException {
 
+    String url = gitCodeSpec.getUrl();
     try {
       URI uriParser = new URI(url);
       String scheme = uriParser.getScheme();
-      if (scheme.equals(GitCodeLocalizerModes.HTTP.getMode())) {
-        return new HTTPGitCodeLocalizer(url);
-      } else if (scheme.equals(GitCodeLocalizerModes.SSH.getMode())) {
-        return new SSHGitCodeLocalizer(url);
+      if (scheme.equals(GitCodeLocalizerModes.SSH.getMode())) {
+        return new SSHGitCodeLocalizer(gitCodeSpec);
+      } else if (scheme.equals(GitCodeLocalizerModes.HTTPS.getMode())) {
+        return new HTTPGitCodeLocalizer(gitCodeSpec);
       } else {
-        return new DummyCodeLocalizer(url);
+        LOG.debug("Unknown url scheme, use https as default localizer.");
+        return new HTTPGitCodeLocalizer(gitCodeSpec);
       }
     } catch (URISyntaxException e) {
       throw new InvalidSpecException(
@@ -103,7 +130,7 @@ public abstract class GitCodeLocalizer extends 
AbstractCodeLocalizer {
 
   public enum GitCodeLocalizerModes {
 
-    HTTP("https"), SSH("ssh");
+    HTTPS("https"), SSH("ssh");
 
     private final String mode;
 
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
index 472135f2..765f7b44 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
@@ -20,11 +20,12 @@
 package org.apache.submarine.server.submitter.k8s.experiment.codelocalizer;
 
 import io.kubernetes.client.openapi.models.V1PodSpec;
+import org.apache.submarine.server.api.spec.code.GitCodeSpec;
 
 public class HTTPGitCodeLocalizer extends GitCodeLocalizer {
 
-  public HTTPGitCodeLocalizer(String url) {
-    super(url);
+  public HTTPGitCodeLocalizer(GitCodeSpec codeSpec) {
+    super(codeSpec);
   }
 
   @Override
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/SSHGitCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/SSHGitCodeLocalizer.java
index d49ef3e3..7460375d 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/SSHGitCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/SSHGitCodeLocalizer.java
@@ -26,6 +26,7 @@ import io.kubernetes.client.openapi.models.V1EnvVar;
 import io.kubernetes.client.openapi.models.V1PodSpec;
 import io.kubernetes.client.openapi.models.V1SecurityContext;
 import io.kubernetes.client.openapi.models.V1VolumeMount;
+import org.apache.submarine.server.api.spec.code.GitCodeSpec;
 
 public class SSHGitCodeLocalizer extends GitCodeLocalizer {
 
@@ -37,8 +38,8 @@ public class SSHGitCodeLocalizer extends GitCodeLocalizer {
   public static final String GIT_SYNC_SSH_NAME = "GIT_SYNC_SSH";
   public static final String GIT_SYNC_SSH_VALUE = "true";
 
-  public SSHGitCodeLocalizer(String url) {
-    super(url);
+  public SSHGitCodeLocalizer(GitCodeSpec codeSpec) {
+    super(codeSpec);
   }
 
   @Override
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/ExperimentSpecParser.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/ExperimentSpecParser.java
index 368ae564..7fd468b3 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/ExperimentSpecParser.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/ExperimentSpecParser.java
@@ -120,8 +120,7 @@ public class ExperimentSpecParser {
      */
     if (experimentSpec.getCode() != null) {
       CodeLocalizer localizer = AbstractCodeLocalizer.getCodeLocalizer(
-          experimentSpec.getCode().getSyncMode(),
-          experimentSpec.getCode().getUrl());
+          experimentSpec.getCode());
       localizer.localize(podSpec);
 
       if (podSpec.getInitContainers() != null
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/K8sResourceUtils.java
similarity index 63%
copy from 
submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
copy to 
submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/K8sResourceUtils.java
index 472135f2..68b14f68 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/experiment/codelocalizer/HTTPGitCodeLocalizer.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/K8sResourceUtils.java
@@ -17,19 +17,21 @@
  * under the License.
  */
 
-package org.apache.submarine.server.submitter.k8s.experiment.codelocalizer;
+package org.apache.submarine.server.submitter.k8s.util;
 
-import io.kubernetes.client.openapi.models.V1PodSpec;
+import io.kubernetes.client.openapi.models.V1EnvVar;
+import io.kubernetes.client.openapi.models.V1EnvVarBuilder;
 
-public class HTTPGitCodeLocalizer extends GitCodeLocalizer {
-
-  public HTTPGitCodeLocalizer(String url) {
-    super(url);
-  }
+/**
+ * Provides some common processing methods for k8s resources
+ */
+public class K8sResourceUtils {
 
-  @Override
-  public void localize(V1PodSpec podSpec) {
-    super.localize(podSpec);
+  /**
+   * Create {@link V1EnvVar} with key and value
+   */
+  public static V1EnvVar createEnvVar(String key, String value) {
+    return new V1EnvVarBuilder().withName(key).withValue(value).build();
   }
 
 }
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_http_git_code_localizer.json
 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_http_git_code_localizer.json
index 408fea0f..af19faee 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_http_git_code_localizer.json
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_http_git_code_localizer.json
@@ -25,6 +25,8 @@
   },
   "code": {
     "syncMode": "git",
-    "url" : "https://github.com/apache/submarine.git";
+    "git": {
+      "url" : "https://github.com/apache/submarine.git";
+    }
   }
 }
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_ssh_git_code_localizer.json
 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_ssh_git_code_localizer.json
index 9afdec4a..a4d6bde0 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_ssh_git_code_localizer.json
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/pytorch_job_req_ssh_git_code_localizer.json
@@ -25,6 +25,8 @@
   },
   "code": {
     "syncMode": "git",
-    "url" : "ssh://g...@github.com/apache/submarine.git"
+    "git": {
+      "url" : "ssh://g...@github.com/apache/submarine.git"
+    }
   }
 }
diff --git 
a/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-http-git-code-localizer-req.json
 
b/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-http-git-code-localizer-req.json
index a47ed17e..fdb08ef7 100644
--- 
a/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-http-git-code-localizer-req.json
+++ 
b/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-http-git-code-localizer-req.json
@@ -23,6 +23,8 @@
   },
   "code": {
     "syncMode": "git",
-    "url" : "https://github.com/apache/submarine.git";
+    "git": {
+      "url" : "https://github.com/apache/submarine.git";
+    }
   }
 }
diff --git 
a/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-ssh-git-code-localizer-req.json
 
b/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-ssh-git-code-localizer-req.json
index c759f887..69e4142d 100644
--- 
a/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-ssh-git-code-localizer-req.json
+++ 
b/submarine-test/test-k8s/src/test/resources/tensorflow/tf-mnist-with-ssh-git-code-localizer-req.json
@@ -23,6 +23,8 @@
   },
   "code": {
     "syncMode": "git",
-    "url" : "ssh://g...@github.com/apache/submarine.git"
+    "git": {
+      "url" : "ssh://g...@github.com/apache/submarine.git"
+    }
   }
 }
diff --git 
a/submarine-workbench/workbench-web/src/app/interfaces/experiment-spec.ts 
b/submarine-workbench/workbench-web/src/app/interfaces/experiment-spec.ts
index 9b2d65c8..5ebf08d1 100644
--- a/submarine-workbench/workbench-web/src/app/interfaces/experiment-spec.ts
+++ b/submarine-workbench/workbench-web/src/app/interfaces/experiment-spec.ts
@@ -46,7 +46,15 @@ export interface Specs {
 
 export interface CodeSpec {
   syncMode: string;
+  git: GitCodeSpec;
+}
+
+// Git code spec
+export interface GitCodeSpec {
   url: string;
+  branch?: string; // default branch should be main
+  username?: string;
+  password?: string;
 }
 
 export interface ExperimentSpec {
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
index 946be87f..f78a3a01 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
@@ -27,7 +27,7 @@
 <div>
   <form [formGroup]="experiment">
     <div [ngSwitch]="step" style="margin-top: 30px">
-      <div *ngSwitchCase="0" id="firstStep">
+      <div *ngSwitchCase="0" id="firstStep" style="max-height: 450px; 
overflow-y: auto" >
         <div class="single-field-group">
           <label for="experimentName">
             <span class="red-star">*</span>
@@ -133,6 +133,43 @@
             <i nz-icon nz-tooltip nzTitle="{{'Copy git repo to /code/current 
in container.' | translate}}" nzType="info-circle"></i>
           </ng-template>
         </div>
+        <div *ngIf="ADVANCED" class="single-field-group">
+          <label for="gitBranch">
+            {{'Git branch' | translate}}
+          </label>
+          <input
+            nz-input
+            type="text"
+            name="gitBranch"
+            id="gitBranch"
+            placeholder="main"
+            formControlName="gitBranch"
+          />
+        </div>
+        <div *ngIf="ADVANCED" class="single-field-group">
+          <label for="gitUsername">
+            {{'Git username' | translate}}
+          </label>
+          <input
+            nz-input
+            type="text"
+            name="gitUsername"
+            id="gitUsername"
+            formControlName="gitUsername"
+          />
+        </div>
+        <div *ngIf="ADVANCED" class="single-field-group">
+          <label for="gitPassword">
+            {{'Git password' | translate}}
+          </label>
+          <input
+            nz-input
+            name="gitPassword"
+            type="password"
+            formControlName="gitPassword"
+            id="gitPassword"
+          />
+        </div>
         <div *ngIf="ADVANCED">
           <ul formArrayName="envs" class="list-container">
             <ng-container *ngFor="let env of envs.controls; index as i">
diff --git 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
index 2fd3da1a..bbacaf60 100644
--- 
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
+++ 
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
@@ -74,7 +74,6 @@ export class ExperimentCustomizedFormComponent implements 
OnInit, OnDestroy {
   framework = 'Tensorflow';
   currentSpecPage = 1;
 
-
   // About update
   @Input() targetId: string = null;
   @Input() targetSpec: ExperimentSpec = null;
@@ -95,7 +94,10 @@ export class ExperimentCustomizedFormComponent implements 
OnInit, OnDestroy {
       image: new FormControl(this.defaultImage, [Validators.required]),
       envs: new FormArray([], 
[this.experimentValidatorService.nameValidatorFactory('key')]),
       specs: new FormArray([], 
[this.experimentValidatorService.nameValidatorFactory('name')]),
-      gitRepo: new FormControl(null, [])
+      gitRepo: new FormControl(null, []),
+      gitBranch: new FormControl(null, []),
+      gitUsername: new FormControl(null, []),
+      gitPassword: new FormControl(null, [])
     });
 
     this.experimentService.fetchExperimentList().subscribe(
@@ -189,6 +191,15 @@ export class ExperimentCustomizedFormComponent implements 
OnInit, OnDestroy {
   get gitRepo() {
     return this.experiment.get('gitRepo');
   }
+  get gitBranch() {
+    return this.experiment.get('gitBranch');
+  }
+  get gitGitUsername() {
+    return this.experiment.get('gitUsername');
+  }
+  get gitGitPassword() {
+    return this.experiment.get('gitPassword');
+  }
 
   /**
    * Reset properties in parent component when the form is about to closed
@@ -367,7 +378,12 @@ export class ExperimentCustomizedFormComponent implements 
OnInit, OnDestroy {
 
     const code: CodeSpec = {
       syncMode: 'git',
-      url: this.gitRepo.value
+      git: {
+        url: this.gitRepo.value,
+        branch: this.gitBranch.value,
+        username: this.gitGitUsername.value,
+        password: this.gitGitPassword.value
+      }
     };
 
     const newExperimentSpec: ExperimentSpec = {
@@ -376,7 +392,7 @@ export class ExperimentCustomizedFormComponent implements 
OnInit, OnDestroy {
       spec: specs
     };
 
-    if (code.url !== null) {
+    if (code.git.url !== null) {
       newExperimentSpec.code = code;
     }
     return newExperimentSpec;
diff --git a/website/docs/api/experiment-template.md 
b/website/docs/api/experiment-template.md
index ccb8d89b..d0217d34 100644
--- a/website/docs/api/experiment-template.md
+++ b/website/docs/api/experiment-template.md
@@ -131,10 +131,23 @@ See more details in [environment api](environment.md).
 
 #### **CodeSpec**
 
-| Field Name | Type   | Description             |
-| ---------- | ------ | ----------------------- |
-| syncMode   | String | sync mode of code spec. |
-| url        | String | url of code spec.       |
+| Field Name | Type        | Description             |
+| ---------- | ----------- | ----------------------- |
+| syncMode   | String      | sync mode of code spec. |
+| url        | GitCodeSpec | git code spec.          |
+
+#### **GitCodeSpec**
+
+Pull variables supported by the git code.
+
+| Field Name | Type    | Description                              |
+| ---------- | ------- | ---------------------------------------- |
+| url        | String  | url of git repo.                         |
+| branch     | String  | the branch of git repo, default is main. |
+| username   | String  | the username of git repo.                |
+| password   | String  | the password of git repo.                |
+| trustCerts | Boolean | accept a self-signed certificate host.   |
+
 ### Example
 
 <details>
diff --git a/website/docs/api/experiment.md b/website/docs/api/experiment.md
index 00f1ac86..090ced53 100644
--- a/website/docs/api/experiment.md
+++ b/website/docs/api/experiment.md
@@ -77,7 +77,19 @@ Currently only support pulling from github. HDFS, NFS and s3 
are in development
 | Field Name | Type                          | Description             | 
Required |
 | ---------- | ----------------------------- | ----------------------- | 
:------: |
 | syncMode   | String \(git\|hdfs\|nfs\|s3\) | sync mode of code spec. |    o  
   |
-| url        | String                        | url of code spec.       |    o  
   |
+| url        | GitCodeSpec                   | git code spec.          |    x  
   |
+
+#### **GitCodeSpec**
+
+Pull variables supported by the git code.
+
+| Field Name | Type    | Description                              | Required |
+| ---------- | ------- | ---------------------------------------- | :------: |
+| url        | String  | url of git repo.                         |    o     |
+| branch     | String  | the branch of git repo, default is main. |    x     |
+| username   | String  | the username of git repo.                |    x     |
+| password   | String  | the password of git repo.                |    x     |
+| trustCerts | Boolean | accept a self-signed certificate host.   |    x     |
 
 ### Example
 <details>
@@ -381,7 +393,7 @@ curl -X GET 
http://127.0.0.1:32080/api/v1/experiment/experiment-1647574374688-00
 | meta        | ExperimentMeta                  | body | Meta data of the 
experiment template.   |    o     |
 | environment | EnvironmentSpec                 | body | Environment of the 
experiment template. |    o     |
 | spec        | Map<String, ExperimentTaskSpec> | body | Spec of pods.         
                  |    o     |
-| code        | CodeSpec                        | body | TODO                  
                  |    x     |
+| code        | CodeSpec                        | body | Experiment codespec.  
                  |    x     |
 ### Example
 
 <details>
diff --git a/website/docs/gettingStarted/notebook.md 
b/website/docs/gettingStarted/notebook.md
index 091b8291..03f5dbda 100644
--- a/website/docs/gettingStarted/notebook.md
+++ b/website/docs/gettingStarted/notebook.md
@@ -94,7 +94,7 @@ worker_spec = 
ExperimentTaskSpec(resources='cpu=1,memory=1024M',
                                  replicas=1)
 ps_spec = ExperimentTaskSpec(resources='cpu=1,memory=1024M',
                                  replicas=1)
-code_spec = CodeSpec(sync_mode='git', 
url='https://github.com/apache/submarine.git')
+code_spec = CodeSpec(sync_mode="git", 
git=GitCodeSpec(url="https://github.com/apache/submarine.git";))
 
 experiment_spec = ExperimentSpec(meta=experiment_meta,
                                  environment=environment,


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@submarine.apache.org
For additional commands, e-mail: dev-h...@submarine.apache.org

Reply via email to