diff --git a/docs/screenplay/e2e-journey-operation.ipynb b/docs/screenplay/e2e-journey-operation.ipynb
new file mode 100644
index 0000000..55bec23
--- /dev/null
+++ b/docs/screenplay/e2e-journey-operation.ipynb
@@ -0,0 +1,1060 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "4f77e0ee",
+ "metadata": {},
+ "source": [
+ "# Getting Started with PrimeHub Python SDK\n",
+ "PrimeHub Python SDK makes you automation with PrimeHub Platform.\n",
+ "\n",
+ "In order to make the SDK working, you have to\n",
+ "\n",
+ "- install the library with pip\n",
+ "- create a config file in the ~/.primehub/config.json"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4604b5a2",
+ "metadata": {},
+ "source": [
+ "# Part 1: prerequisite: Configure the environment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6299410e",
+ "metadata": {},
+ "source": [
+ "## 1. Install with pip\n",
+ "Let's install PrimeHub Python SDK with pip."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "907df9ff",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Requirement already satisfied: primehub-python-sdk in /opt/conda/lib/python3.7/site-packages (0.3.8)\n",
+ "Requirement already satisfied: tabulate==0.8.9 in /opt/conda/lib/python3.7/site-packages (from primehub-python-sdk) (0.8.9)\n",
+ "Requirement already satisfied: types-tabulate==0.8.2 in /opt/conda/lib/python3.7/site-packages (from primehub-python-sdk) (0.8.2)\n",
+ "Requirement already satisfied: types-requests in /opt/conda/lib/python3.7/site-packages (from primehub-python-sdk) (2.28.11.5)\n",
+ "Requirement already satisfied: requests in /opt/conda/lib/python3.7/site-packages (from primehub-python-sdk) (2.27.1)\n",
+ "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.7/site-packages (from requests->primehub-python-sdk) (3.3)\n",
+ "Requirement already satisfied: charset-normalizer~=2.0.0 in /opt/conda/lib/python3.7/site-packages (from requests->primehub-python-sdk) (2.0.12)\n",
+ "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.7/site-packages (from requests->primehub-python-sdk) (2020.6.20)\n",
+ "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /opt/conda/lib/python3.7/site-packages (from requests->primehub-python-sdk) (1.26.9)\n",
+ "Requirement already satisfied: types-urllib3<1.27 in /opt/conda/lib/python3.7/site-packages (from types-requests->primehub-python-sdk) (1.26.25.4)\n"
+ ]
+ }
+ ],
+ "source": [
+ "!pip install primehub-python-sdk"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f1cb62e",
+ "metadata": {},
+ "source": [
+ "## 2. Request the API Token\n",
+ "In order to get the token, you have to have an account in the PrimeHub cluster, the following process will ask you loing with your account.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "2c6b24ab",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# PLEASE UPDATE PRIMEHUB_CLUSTER to your cluster\n",
+ "PRIMEHUB_CLUSTER = 'http://primehub-python-sdk.primehub.io'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "eeb4218a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "from primehub import PrimeHub, PrimeHubConfig\n",
+ "\n",
+ "ph = PrimeHub(PrimeHubConfig())\n",
+ "if not os.path.isfile(os.path.join(os.getenv(\"HOME\"), \".primehub/config.json\")):\n",
+ " ph.config.generate(PRIMEHUB_CLUSTER)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "04943d0e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "PrimeHub Python SDK setup successfully\n",
+ "Current Group: {'id': '11945641-279a-4042-8688-ef88769c21ca', 'name': 'demo_showcase', 'displayName': 'demo_showcase'}\n"
+ ]
+ }
+ ],
+ "source": [
+ "ph = PrimeHub(PrimeHubConfig())\n",
+ "if ph.is_ready():\n",
+ " print(\"PrimeHub Python SDK setup successfully\")\n",
+ " print(\"Current Group:\", ph.primehub_config.current_group)\n",
+ "else:\n",
+ " print(\"PrimeHub Python SDK couldn't get the group information, please check the configuration.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "75a015ef",
+ "metadata": {},
+ "source": [
+ "## 3. Check the account is Admin account\n",
+ "\n",
+ "Use `ph.me.me` to know that the account is admin account."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "98c6e517",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "account_information = ph.me.me()\n",
+ "account_information['isAdmin']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "87d72f53",
+ "metadata": {},
+ "source": [
+ "## 4. Clean up the previous testing data.\n",
+ "\n",
+ "We need to clean up the previous data to prevent the notebook error,"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "a2c205c5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28ca4583",
+ "metadata": {},
+ "source": [
+ "# Part 2: End-User Journey or End2End ML Journey\n",
+ "We will test:\n",
+ "\n",
+ "- Submit a Job/schedule job\n",
+ "- List running jobs(status) submitted by the user\n",
+ "- List registered models with all of versions\n",
+ "- Submit a registered model as a deployment\n",
+ "- Update the deployment with other version of the model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9ba000a8",
+ "metadata": {},
+ "source": [
+ "### 1. Submit a Job/schedule job"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "2f02cbf7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'id': 'job-202211280818-5ojjpm', 'displayName': 'short-job', 'cancel': False, 'command': 'echo \"test1\"\\necho \"test2\"', 'groupId': '11945641-279a-4042-8688-ef88769c21ca', 'groupName': 'demo_showcase', 'image': 'base-notebook', 'instanceType': {'id': 'cpu-1', 'name': 'cpu-1', 'displayName': 'CPU 1', 'cpuLimit': 1, 'memoryLimit': 2, 'gpuLimit': 0}, 'userId': '35985b6b-21c9-4362-902d-4d6bb89074bf', 'userName': 'simonliu@infuseai.io', 'phase': 'Pending', 'reason': None, 'message': None, 'createTime': '2022-11-28T08:18:18Z', 'startTime': None, 'finishTime': None, 'recurrence': None}\n",
+ "[ Waiting ]\n",
+ "[ Job Done ]\n",
+ "[ Job Logs ]\n",
+ "test1\n",
+ "test2\n",
+ "Artifacts: no artifact found\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Submit a job\n",
+ "config = {\n",
+ " \"instanceType\": \"cpu-1\",\n",
+ " \"image\": \"base-notebook\",\n",
+ " \"displayName\": \"short-job\",\n",
+ " \"command\": \"echo \\\"test1\\\"\\necho \\\"test2\\\"\"\n",
+ "}\n",
+ "\n",
+ "short_job = ph.jobs.submit(config)\n",
+ "print(short_job)\n",
+ "\n",
+ "# Wait the job to be done\n",
+ "print('[ Waiting ]')\n",
+ "ph.jobs.wait(short_job['id'])\n",
+ "print('[ Job Done ]')\n",
+ "\n",
+ "# Get logs\n",
+ "logs = ph.jobs.logs(short_job['id'])\n",
+ "print('[ Job Logs ]')\n",
+ "for l in logs:\n",
+ " print(l.decode(\"utf-8\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "ec484cf1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'id': 'recurrence-9oybl9', 'displayName': 'test', 'recurrence': {'type': 'daily', 'cron': ''}, 'invalid': False, 'message': None, 'command': 'echo \"test!\"', 'groupId': '11945641-279a-4042-8688-ef88769c21ca', 'groupName': 'demo_showcase', 'image': 'base-notebook', 'instanceType': {'id': 'cpu-1', 'name': 'cpu-1', 'displayName': 'CPU 1', 'cpuLimit': 1, 'memoryLimit': 2, 'gpuLimit': 0}, 'userId': '35985b6b-21c9-4362-902d-4d6bb89074bf', 'userName': 'simonliu@infuseai.io', 'nextRunTime': None}\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Create a recurring job that runs at every 4 AM\n",
+ "config = {\n",
+ " \"instanceType\": \"cpu-1\",\n",
+ " \"image\": \"base-notebook\",\n",
+ " \"displayName\": \"test\",\n",
+ " \"command\": \"echo \\\"test!\\\"\",\n",
+ " \"recurrence\": {\n",
+ " \"type\":\"daily\",\n",
+ " \"cron\":\"\"\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "recurring_job = ph.recurring_jobs.create(config)\n",
+ "print(recurring_job)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "4286e865",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " id | \n",
+ " displayName | \n",
+ " recurrence | \n",
+ " invalid | \n",
+ " message | \n",
+ " command | \n",
+ " groupId | \n",
+ " groupName | \n",
+ " image | \n",
+ " instanceType | \n",
+ " userId | \n",
+ " userName | \n",
+ " nextRunTime | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " recurrence-9oybl9 | \n",
+ " test | \n",
+ " {'type': 'daily', 'cron': ''} | \n",
+ " False | \n",
+ " None | \n",
+ " echo \"test!\" | \n",
+ " 11945641-279a-4042-8688-ef88769c21ca | \n",
+ " demo_showcase | \n",
+ " base-notebook | \n",
+ " {'id': 'cpu-1', 'name': 'cpu-1', 'displayName'... | \n",
+ " 35985b6b-21c9-4362-902d-4d6bb89074bf | \n",
+ " simonliu@infuseai.io | \n",
+ " 2022-11-28T20:00:00Z | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id displayName recurrence invalid \\\n",
+ "0 recurrence-9oybl9 test {'type': 'daily', 'cron': ''} False \n",
+ "\n",
+ " message command groupId groupName \\\n",
+ "0 None echo \"test!\" 11945641-279a-4042-8688-ef88769c21ca demo_showcase \n",
+ "\n",
+ " image instanceType \\\n",
+ "0 base-notebook {'id': 'cpu-1', 'name': 'cpu-1', 'displayName'... \n",
+ "\n",
+ " userId userName \\\n",
+ "0 35985b6b-21c9-4362-902d-4d6bb89074bf simonliu@infuseai.io \n",
+ "\n",
+ " nextRunTime \n",
+ "0 2022-11-28T20:00:00Z "
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(list(ph.recurring_jobs.list()))\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "51b9df81",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'id': 'recurrence-9oybl9'}"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ph.recurring_jobs.delete(recurring_job['id'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c158195c",
+ "metadata": {},
+ "source": [
+ "### 2. List running jobs(status) submitted by the user\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "id": "4324fe2c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " id | \n",
+ " displayName | \n",
+ " cancel | \n",
+ " command | \n",
+ " groupId | \n",
+ " groupName | \n",
+ " image | \n",
+ " instanceType | \n",
+ " userId | \n",
+ " userName | \n",
+ " phase | \n",
+ " reason | \n",
+ " message | \n",
+ " createTime | \n",
+ " startTime | \n",
+ " finishTime | \n",
+ " recurrence | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " job-202211280835-c4lbkd | \n",
+ " short-job | \n",
+ " None | \n",
+ " echo \"test1\"\\necho \"test2\" | \n",
+ " 11945641-279a-4042-8688-ef88769c21ca | \n",
+ " demo_showcase | \n",
+ " base-notebook | \n",
+ " {'id': 'cpu-1', 'name': 'cpu-1', 'displayName'... | \n",
+ " 35985b6b-21c9-4362-902d-4d6bb89074bf | \n",
+ " simonliu@infuseai.io | \n",
+ " Running | \n",
+ " PodRunning | \n",
+ " Job is currently running | \n",
+ " 2022-11-28T08:35:27Z | \n",
+ " 2022-11-28T08:35:32Z | \n",
+ " None | \n",
+ " None | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id displayName cancel command \\\n",
+ "0 job-202211280835-c4lbkd short-job None echo \"test1\"\\necho \"test2\" \n",
+ "\n",
+ " groupId groupName image \\\n",
+ "0 11945641-279a-4042-8688-ef88769c21ca demo_showcase base-notebook \n",
+ "\n",
+ " instanceType \\\n",
+ "0 {'id': 'cpu-1', 'name': 'cpu-1', 'displayName'... \n",
+ "\n",
+ " userId userName phase \\\n",
+ "0 35985b6b-21c9-4362-902d-4d6bb89074bf simonliu@infuseai.io Running \n",
+ "\n",
+ " reason message createTime \\\n",
+ "0 PodRunning Job is currently running 2022-11-28T08:35:27Z \n",
+ "\n",
+ " startTime finishTime recurrence \n",
+ "0 2022-11-28T08:35:32Z None None "
+ ]
+ },
+ "execution_count": 41,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(list(ph.jobs.list()))\n",
+ "df[(df['phase']==\"Running\") & (df['userName']==\"simonliu@infuseai.io\")]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "82408add",
+ "metadata": {},
+ "source": [
+ "### 3. List registered models with all of versions\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 73,
+ "id": "e7c49418",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " name | \n",
+ " creationTimestamp | \n",
+ " lastUpdatedTimestamp | \n",
+ " description | \n",
+ " latestVersion | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " mnist | \n",
+ " 2021-09-30 04:48:39 | \n",
+ " 2021-09-30 05:15:16 | \n",
+ " None | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " tf-screw-model | \n",
+ " 2021-11-18 16:43:53 | \n",
+ " 2022-01-17 04:01:03 | \n",
+ " None | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " example | \n",
+ " 2022-07-14 06:28:53 | \n",
+ " 2022-07-14 06:28:54 | \n",
+ " None | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " mask-detection-model | \n",
+ " 2022-10-05 05:20:37 | \n",
+ " 2022-11-14 06:50:29 | \n",
+ " None | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " name creationTimestamp lastUpdatedTimestamp description \\\n",
+ "0 mnist 2021-09-30 04:48:39 2021-09-30 05:15:16 None \n",
+ "1 tf-screw-model 2021-11-18 16:43:53 2022-01-17 04:01:03 None \n",
+ "2 example 2022-07-14 06:28:53 2022-07-14 06:28:54 None \n",
+ "3 mask-detection-model 2022-10-05 05:20:37 2022-11-14 06:50:29 None \n",
+ "\n",
+ " latestVersion \n",
+ "0 2 \n",
+ "1 1 \n",
+ "2 1 \n",
+ "3 4 "
+ ]
+ },
+ "execution_count": 73,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(ph.models.list())\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 72,
+ "id": "ab62447a",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " name | \n",
+ " version | \n",
+ " creationTimestamp | \n",
+ " lastUpdatedTimestamp | \n",
+ " deployedBy | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " mnist | \n",
+ " 1 | \n",
+ " 2021-09-30 04:48:39 | \n",
+ " 2021-09-30 04:48:39 | \n",
+ " [{'id': 'mnist-1209-a9wjo', 'name': 'mnist-120... | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " mnist | \n",
+ " 2 | \n",
+ " 2021-09-30 05:15:16 | \n",
+ " 2021-09-30 05:15:16 | \n",
+ " [{'id': 'mnist-9ofpg', 'name': 'mnist'}] | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " name version creationTimestamp lastUpdatedTimestamp \\\n",
+ "0 mnist 1 2021-09-30 04:48:39 2021-09-30 04:48:39 \n",
+ "1 mnist 2 2021-09-30 05:15:16 2021-09-30 05:15:16 \n",
+ "\n",
+ " deployedBy \n",
+ "0 [{'id': 'mnist-1209-a9wjo', 'name': 'mnist-120... \n",
+ "1 [{'id': 'mnist-9ofpg', 'name': 'mnist'}] "
+ ]
+ },
+ "execution_count": 72,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(ph.models.list_versions('mnist'))\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3d617436",
+ "metadata": {},
+ "source": [
+ "### 4. Submit a registered model as a deployment\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 75,
+ "id": "b2894613",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'id': 'deploymeny-from-sdk-zxy', 'name': 'deploymeny-from-sdk', 'modelImage': 'base-notebook', 'imagePullSecret': None, 'description': None, 'replicas': 1, 'stop': False, 'endpointAccessType': 'public', 'endpointClients': [], 'status': 'Deploying', 'endpoint': None, 'availableReplicas': None, 'message': None, 'pods': []}\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Create a deployment\n",
+ "config = {\n",
+ " \"id\": \"deploymeny-from-sdk-zxy\",\n",
+ " \"name\": \"deploymeny-from-sdk\",\n",
+ " \"modelImage\": \"base-notebook\",\n",
+ " \"modelURI\": \"test/module/uri\",\n",
+ " \"instanceType\": \"cpu-1\",\n",
+ " \"replicas\": 1\n",
+ "}\n",
+ "\n",
+ "deployment = ph.deployments.create(config)\n",
+ "print(deployment)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "id": "fd6cdd5f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " id | \n",
+ " name | \n",
+ " modelImage | \n",
+ " imagePullSecret | \n",
+ " description | \n",
+ " replicas | \n",
+ " stop | \n",
+ " endpointAccessType | \n",
+ " endpointClients | \n",
+ " status | \n",
+ " endpoint | \n",
+ " availableReplicas | \n",
+ " message | \n",
+ " pods | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " deploymeny-from-sdk-zxy | \n",
+ " deploymeny-from-sdk | \n",
+ " base-notebook | \n",
+ " None | \n",
+ " None | \n",
+ " 1 | \n",
+ " False | \n",
+ " public | \n",
+ " [] | \n",
+ " Deploying | \n",
+ " https://c.demo.primehub.io/deployment/deployme... | \n",
+ " NaN | \n",
+ " Failed because of wrong image settings.\\npod[d... | \n",
+ " [{'name': 'deploy-deploymeny-from-sdk-zxy-cf9b... | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id name modelImage \\\n",
+ "0 deploymeny-from-sdk-zxy deploymeny-from-sdk base-notebook \n",
+ "\n",
+ " imagePullSecret description replicas stop endpointAccessType \\\n",
+ "0 None None 1 False public \n",
+ "\n",
+ " endpointClients status \\\n",
+ "0 [] Deploying \n",
+ "\n",
+ " endpoint availableReplicas \\\n",
+ "0 https://c.demo.primehub.io/deployment/deployme... NaN \n",
+ "\n",
+ " message \\\n",
+ "0 Failed because of wrong image settings.\\npod[d... \n",
+ "\n",
+ " pods \n",
+ "0 [{'name': 'deploy-deploymeny-from-sdk-zxy-cf9b... "
+ ]
+ },
+ "execution_count": 76,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(ph.deployments.list())\n",
+ "df[df['name'] == \"deploymeny-from-sdk\"]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6843b2b1",
+ "metadata": {},
+ "source": [
+ "### 5. Update the deployment with other version of the model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 77,
+ "id": "cfe67c0d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'id': 'deploymeny-from-sdk-zxy',\n",
+ " 'name': 'deploymeny-from-sdk',\n",
+ " 'modelImage': 'base-notebook',\n",
+ " 'imagePullSecret': None,\n",
+ " 'description': None,\n",
+ " 'replicas': 2,\n",
+ " 'stop': False,\n",
+ " 'endpointAccessType': 'public',\n",
+ " 'endpointClients': [],\n",
+ " 'status': 'Deploying',\n",
+ " 'endpoint': 'https://c.demo.primehub.io/deployment/deploymeny-from-sdk-zxy/api/v1.0/predictions',\n",
+ " 'availableReplicas': None,\n",
+ " 'message': 'Failed because of wrong image settings.\\npod[deploy-deploymeny-from-sdk-zxy-cf9b9bc6f-fmd7d] failed\\n reason: ContainersNotInitialized, message: containers with incomplete status: [model-storage-initializer]\\n container state: Waiting, reason: ImagePullBackOff, message Back-off pulling image \"gcr.io/kfserving/storage-initializer:v0.4.0\"',\n",
+ " 'pods': [{'name': 'deploy-deploymeny-from-sdk-zxy-cf9b9bc6f-fmd7d'}]}"
+ ]
+ },
+ "execution_count": 77,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Update the deployment\n",
+ "update_config = {\n",
+ " \"replicas\": 2\n",
+ "}\n",
+ "\n",
+ "ph.deployments.update(deployment['id'], update_config)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 78,
+ "id": "4e934562",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " id | \n",
+ " name | \n",
+ " modelImage | \n",
+ " imagePullSecret | \n",
+ " description | \n",
+ " replicas | \n",
+ " stop | \n",
+ " endpointAccessType | \n",
+ " endpointClients | \n",
+ " status | \n",
+ " endpoint | \n",
+ " availableReplicas | \n",
+ " message | \n",
+ " pods | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " deploymeny-from-sdk-zxy | \n",
+ " deploymeny-from-sdk | \n",
+ " base-notebook | \n",
+ " None | \n",
+ " None | \n",
+ " 2 | \n",
+ " False | \n",
+ " public | \n",
+ " [] | \n",
+ " Deploying | \n",
+ " https://c.demo.primehub.io/deployment/deployme... | \n",
+ " NaN | \n",
+ " Failed because of wrong image settings.\\npod[d... | \n",
+ " [{'name': 'deploy-deploymeny-from-sdk-zxy-cf9b... | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id name modelImage \\\n",
+ "0 deploymeny-from-sdk-zxy deploymeny-from-sdk base-notebook \n",
+ "\n",
+ " imagePullSecret description replicas stop endpointAccessType \\\n",
+ "0 None None 2 False public \n",
+ "\n",
+ " endpointClients status \\\n",
+ "0 [] Deploying \n",
+ "\n",
+ " endpoint availableReplicas \\\n",
+ "0 https://c.demo.primehub.io/deployment/deployme... NaN \n",
+ "\n",
+ " message \\\n",
+ "0 Failed because of wrong image settings.\\npod[d... \n",
+ "\n",
+ " pods \n",
+ "0 [{'name': 'deploy-deploymeny-from-sdk-zxy-cf9b... "
+ ]
+ },
+ "execution_count": 78,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(ph.deployments.list())\n",
+ "df[df['name'] == \"deploymeny-from-sdk\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 79,
+ "id": "3ef611a1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'id': 'deploymeny-from-sdk-zxy'}"
+ ]
+ },
+ "execution_count": 79,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Delete a deployment\n",
+ "ph.deployments.delete(deployment['id'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 80,
+ "id": "2f21afc6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " id | \n",
+ " name | \n",
+ " modelImage | \n",
+ " imagePullSecret | \n",
+ " description | \n",
+ " replicas | \n",
+ " stop | \n",
+ " endpointAccessType | \n",
+ " endpointClients | \n",
+ " status | \n",
+ " endpoint | \n",
+ " availableReplicas | \n",
+ " message | \n",
+ " pods | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "Empty DataFrame\n",
+ "Columns: [id, name, modelImage, imagePullSecret, description, replicas, stop, endpointAccessType, endpointClients, status, endpoint, availableReplicas, message, pods]\n",
+ "Index: []"
+ ]
+ },
+ "execution_count": 80,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.DataFrame.from_records(ph.deployments.list())\n",
+ "df[df['name'] == \"deploymeny-from-sdk\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13803df3",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/screenplay/insight-operation.ipynb b/docs/screenplay/insight-operation.ipynb
new file mode 100644
index 0000000..bcc0d93
--- /dev/null
+++ b/docs/screenplay/insight-operation.ipynb
@@ -0,0 +1,291 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "721c2b0e",
+ "metadata": {},
+ "source": [
+ "In order to make the SDK working, you have to\n",
+ "\n",
+ "- install the library with pip\n",
+ "- create a config file in the ~/.primehub/config.json"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43754ebb",
+ "metadata": {},
+ "source": [
+ "# Part 1: prerequisite: Configure the environment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9f960f00",
+ "metadata": {},
+ "source": [
+ "## 1. Install with pip\n",
+ "Let's install PrimeHub Python SDK with pip."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "00159582",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!pip install -q primehub-python-sdk"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bd8c43ab",
+ "metadata": {},
+ "source": [
+ "## 2. Request the API Token\n",
+ "In order to get the token, you have to have an account in the PrimeHub cluster, the following process will ask you loing with your account.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "bc0382a7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# PLEASE UPDATE PRIMEHUB_CLUSTER to your cluster\n",
+ "PRIMEHUB_CLUSTER = 'http://primehub-python-sdk.primehub.io'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "796d206c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "from primehub import PrimeHub, PrimeHubConfig\n",
+ "\n",
+ "ph = PrimeHub(PrimeHubConfig())\n",
+ "if not os.path.isfile(os.path.join(os.getenv(\"HOME\"), \".primehub/config.json\")):\n",
+ " ph.config.generate(PRIMEHUB_CLUSTER)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2e9fd865",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "PrimeHub Python SDK setup successfully\n",
+ "Current Group: {'id': '11945641-279a-4042-8688-ef88769c21ca', 'name': 'demo_showcase', 'displayName': 'demo_showcase'}\n"
+ ]
+ }
+ ],
+ "source": [
+ "ph = PrimeHub(PrimeHubConfig())\n",
+ "if ph.is_ready():\n",
+ " print(\"PrimeHub Python SDK setup successfully\")\n",
+ " print(\"Current Group:\", ph.primehub_config.current_group)\n",
+ "else:\n",
+ " print(\"PrimeHub Python SDK couldn't get the group information, please check the configuration.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15d83e19",
+ "metadata": {},
+ "source": [
+ "## 3. Check the account is Admin account\n",
+ "\n",
+ "Use `ph.me.me` to know that the account is admin account."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "afeb3b85",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "account_information = ph.me.me()\n",
+ "account_information['isAdmin']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5f8aa428",
+ "metadata": {},
+ "source": [
+ "# Part 2: Insight operation\n",
+ "We will test:\n",
+ " \n",
+ "- Get a user list of a group\n",
+ "- Get a group list\n",
+ "- Get a self-hosted image list (with size)\n",
+ "- To learn the summary of occupied resources by running Notebooks(user) & Jobs(user) & Deployments(user) & Apps(user) (of a group)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a10f85c0",
+ "metadata": {},
+ "source": [
+ "## 1. Get a user list of a group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1dfd6a6a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6031d352",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame.from_records(list(ph.admin.groups.list()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "88e91909",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame.from_records(list(ph.admin.users.list()))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1b36937d",
+ "metadata": {},
+ "source": [
+ "## 2. Get a group list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6d4b852e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame.from_records(list(ph.admin.groups.list()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4eef640b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame.from_records(list(ph.groups.list()))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48a4543a",
+ "metadata": {},
+ "source": [
+ "### 3. Get a self-hosted image list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1406dd20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame.from_records(list(ph.admin.images.list()))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30ad5bfb",
+ "metadata": {},
+ "source": [
+ "### 4. To learn the summary of occupied resources by running Notebooks(user) & Jobs(user) & Deployments(user) & Apps(user) (of a group)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f4dbaa86",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame.from_records(list(ph.jobs.list()))\n",
+ "df[df['userName'] == \"hlb@infuseai.io\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "502bdfb4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame.from_records(list(ph.deployments.list()))\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "177665a3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame.from_records(list(ph.apps.list()))\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0d213e0b",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}