From 9899f56fc99e466c8d4864bd80faa58bac000b43 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 08:50:26 +0100
Subject: [PATCH 01/11] refactor: use API code generators for sessions v2
---
.../sessionsV2/api/sessionsV2.api-config.ts | 32 +++++++++++++++++++
.../features/sessionsV2/api/sessionsV2.api.ts | 0
.../sessionsV2/api/sessionsV2.empty-api.ts | 26 +++++++++++++++
3 files changed, 58 insertions(+)
create mode 100644 client/src/features/sessionsV2/api/sessionsV2.api-config.ts
create mode 100644 client/src/features/sessionsV2/api/sessionsV2.api.ts
create mode 100644 client/src/features/sessionsV2/api/sessionsV2.empty-api.ts
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api-config.ts b/client/src/features/sessionsV2/api/sessionsV2.api-config.ts
new file mode 100644
index 0000000000..eda5fee45b
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionsV2.api-config.ts
@@ -0,0 +1,32 @@
+/*!
+ * Copyright 2025 - Swiss Data Science Center (SDSC)
+ * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
+ * Eidgenössische Technische Hochschule Zürich (ETHZ).
+ *
+ * Licensed 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.
+ */
+
+// Run `npm run generate-api:sessionsV2` to generate the API
+import type { ConfigFile } from "@rtk-query/codegen-openapi";
+import path from "path";
+
+const config: ConfigFile = {
+ apiFile: "./sessionsV2.empty-api.ts",
+ apiImport: "sessionsV2EmptyApi",
+ outputFile: "./sessionsV2.generated-api.ts",
+ exportName: "sessionsV2GeneratedApi",
+ hooks: true,
+ schemaFile: path.join(__dirname, "sessionsV2.openapi.json"),
+};
+
+export default config;
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api.ts b/client/src/features/sessionsV2/api/sessionsV2.api.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/client/src/features/sessionsV2/api/sessionsV2.empty-api.ts b/client/src/features/sessionsV2/api/sessionsV2.empty-api.ts
new file mode 100644
index 0000000000..37f9908e06
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionsV2.empty-api.ts
@@ -0,0 +1,26 @@
+/*!
+ * Copyright 2025 - Swiss Data Science Center (SDSC)
+ * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
+ * Eidgenössische Technische Hochschule Zürich (ETHZ).
+ *
+ * Licensed 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.
+ */
+
+import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
+
+// initialize an empty api service that we'll inject endpoints into later as needed
+export const sessionsV2EmptyApi = createApi({
+ baseQuery: fetchBaseQuery({ baseUrl: "/api/data" }),
+ endpoints: () => ({}),
+ reducerPath: "sessionsV2Api",
+});
From 92346b75ac9affb86b8ed7739b196f44494f92ff Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 11:25:44 +0100
Subject: [PATCH 02/11] a step :)
---
client/package.json | 3 +-
.../src/features/dashboardV2/DashboardV2.tsx | 3 +-
.../session/components/SessionsList.tsx | 8 +-
.../session/useWaitForSessionStatus.hook.ts | 3 +-
.../SessionList/SessionItemDisplay.tsx | 3 +-
.../SessionShowPage/ShowSessionPage.tsx | 29 +-
client/src/features/sessionsV2/SessionsV2.tsx | 3 +-
.../features/sessionsV2/api/sessionsV2.api.ts | 48 +
.../api/sessionsV2.generated-api.ts | 461 ++++++
.../sessionsV2/api/sessionsV2.openapi.json | 1420 +++++++++++++++++
.../SessionButton/ActiveSessionButton.tsx | 10 +-
.../SessionStatus/SessionStatus.tsx | 4 +-
.../src/features/sessionsV2/sessionsV2.api.ts | 2 +-
.../features/sessionsV2/sessionsV2.types.ts | 18 +-
14 files changed, 1977 insertions(+), 38 deletions(-)
create mode 100644 client/src/features/sessionsV2/api/sessionsV2.generated-api.ts
create mode 100644 client/src/features/sessionsV2/api/sessionsV2.openapi.json
diff --git a/client/package.json b/client/package.json
index 8d3c3f3ae7..36cc7a736a 100644
--- a/client/package.json
+++ b/client/package.json
@@ -29,7 +29,8 @@
"generate-api:projectV2": "rtk-query-codegen-openapi src/features/projectsV2/api/projectV2.api-config.ts",
"generate-api:platform": "rtk-query-codegen-openapi src/features/platform/api/platform.api-config.ts",
"generate-api:searchV2": "rtk-query-codegen-openapi src/features/searchV2/api/searchV2.api-config.ts",
- "generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts"
+ "generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts",
+ "generate-api:sessionsV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionsV2.api-config.ts"
},
"type": "module",
"dependencies": {
diff --git a/client/src/features/dashboardV2/DashboardV2.tsx b/client/src/features/dashboardV2/DashboardV2.tsx
index 6ce7b0a54e..72e60cec78 100644
--- a/client/src/features/dashboardV2/DashboardV2.tsx
+++ b/client/src/features/dashboardV2/DashboardV2.tsx
@@ -61,7 +61,8 @@ import CreateProjectV2Button from "../projectsV2/new/CreateProjectV2Button";
import GroupShortHandDisplay from "../projectsV2/show/GroupShortHandDisplay";
import ProjectShortHandDisplay from "../projectsV2/show/ProjectShortHandDisplay";
import SearchV2Bar from "../searchV2/components/SearchV2Bar";
-import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
+// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
+import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/api/sessionsV2.api";
import { useGetUserQuery } from "../usersV2/api/users.api";
import UserAvatar from "../usersV2/show/UserAvatar";
import DashboardV2Sessions from "./DashboardV2Sessions";
diff --git a/client/src/features/session/components/SessionsList.tsx b/client/src/features/session/components/SessionsList.tsx
index 245426a67f..d9d0f8d113 100644
--- a/client/src/features/session/components/SessionsList.tsx
+++ b/client/src/features/session/components/SessionsList.tsx
@@ -315,10 +315,10 @@ function SessionRowProject({ annotations }: SessionRowProjectProps) {
export interface SessionLauncherResources {
name?: string;
- cpu: number;
- memory: number;
- gpu: number;
- storage: number;
+ cpu?: number;
+ memory?: number;
+ gpu?: number;
+ storage?: number;
}
interface SessionRowResourceRequestsProps {
resourceRequests: Session["resources"]["requests"] | SessionLauncherResources;
diff --git a/client/src/features/session/useWaitForSessionStatus.hook.ts b/client/src/features/session/useWaitForSessionStatus.hook.ts
index 8470e57134..c88a267a44 100644
--- a/client/src/features/session/useWaitForSessionStatus.hook.ts
+++ b/client/src/features/session/useWaitForSessionStatus.hook.ts
@@ -18,7 +18,8 @@
import { useEffect, useMemo, useState } from "react";
import { useGetSessionsQuery } from "./sessions.api";
-import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
+// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
+import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/api/sessionsV2.api";
import { SessionStatusState } from "./sessions.types";
const DEFAULT_POLLING_INTERVAL_MS = 5_000;
diff --git a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
index 8a519c1743..31a8a4282d 100644
--- a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
+++ b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
@@ -20,7 +20,8 @@ import { useCallback, useMemo } from "react";
import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
import { Project } from "../../projectsV2/api/projectV2.api";
-import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2.api";
+// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2.api";
+import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../api/sessionsV2.api";
import { SessionView } from "../SessionView/SessionView";
import { SessionLauncher } from "../sessionsV2.types";
import SessionItem from "./SessionItem";
diff --git a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
index 4d267c7ada..29b9d2a822 100644
--- a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
+++ b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
@@ -63,8 +63,9 @@ import PauseOrDeleteSessionModal from "../PauseOrDeleteSessionModal";
import { getSessionFavicon } from "../session.utils";
import {
useGetProjectSessionLaunchersQuery,
- useGetSessionsQuery,
+ // useGetSessionsQuery,
} from "../sessionsV2.api";
+import { useGetSessionsQuery } from "../api/sessionsV2.api";
import { SessionV2 } from "../sessionsV2.types";
import SessionIframe from "./SessionIframe";
import SessionPaused from "./SessionPaused";
@@ -432,18 +433,20 @@ function SessionDetails({
-
+ {session.started && (
+
+ )}
({
+ getNotebooksImages: build.query<
+ GetNotebooksImagesApiResponse,
+ GetNotebooksImagesApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/images`,
+ params: { image_url: queryArg.imageUrl },
+ }),
+ }),
+ getNotebooksLogsByServerName: build.query<
+ GetNotebooksLogsByServerNameApiResponse,
+ GetNotebooksLogsByServerNameApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/logs/${queryArg.serverName}`,
+ params: { max_lines: queryArg.maxLines },
+ }),
+ }),
+ getNotebooksServerOptions: build.query<
+ GetNotebooksServerOptionsApiResponse,
+ GetNotebooksServerOptionsApiArg
+ >({
+ query: () => ({ url: `/notebooks/server_options` }),
+ }),
+ postNotebooksServers: build.mutation<
+ PostNotebooksServersApiResponse,
+ PostNotebooksServersApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/servers`,
+ method: "POST",
+ body: queryArg.launchNotebookRequestOld,
+ }),
+ }),
+ getNotebooksServers: build.query<
+ GetNotebooksServersApiResponse,
+ GetNotebooksServersApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/servers`,
+ params: {
+ project: queryArg.project,
+ commit_sha: queryArg.commitSha,
+ namespace: queryArg["namespace"],
+ branch: queryArg.branch,
+ },
+ }),
+ }),
+ deleteNotebooksServersByServerName: build.mutation<
+ DeleteNotebooksServersByServerNameApiResponse,
+ DeleteNotebooksServersByServerNameApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/servers/${queryArg.serverName}`,
+ method: "DELETE",
+ params: { forced: queryArg.forced },
+ }),
+ }),
+ getNotebooksServersByServerName: build.query<
+ GetNotebooksServersByServerNameApiResponse,
+ GetNotebooksServersByServerNameApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/servers/${queryArg.serverName}`,
+ }),
+ }),
+ patchNotebooksServersByServerName: build.mutation<
+ PatchNotebooksServersByServerNameApiResponse,
+ PatchNotebooksServersByServerNameApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/notebooks/servers/${queryArg.serverName}`,
+ method: "PATCH",
+ body: queryArg.patchServerRequest,
+ }),
+ }),
+ postSessions: build.mutation
({
+ query: (queryArg) => ({
+ url: `/sessions`,
+ method: "POST",
+ body: queryArg.sessionPostRequest,
+ }),
+ }),
+ getSessions: build.query({
+ query: () => ({ url: `/sessions` }),
+ }),
+ getSessionsBySessionId: build.query<
+ GetSessionsBySessionIdApiResponse,
+ GetSessionsBySessionIdApiArg
+ >({
+ query: (queryArg) => ({ url: `/sessions/${queryArg.sessionId}` }),
+ }),
+ deleteSessionsBySessionId: build.mutation<
+ DeleteSessionsBySessionIdApiResponse,
+ DeleteSessionsBySessionIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/sessions/${queryArg.sessionId}`,
+ method: "DELETE",
+ }),
+ }),
+ patchSessionsBySessionId: build.mutation<
+ PatchSessionsBySessionIdApiResponse,
+ PatchSessionsBySessionIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/sessions/${queryArg.sessionId}`,
+ method: "PATCH",
+ body: queryArg.sessionPatchRequest,
+ }),
+ }),
+ getSessionsBySessionIdLogs: build.query<
+ GetSessionsBySessionIdLogsApiResponse,
+ GetSessionsBySessionIdLogsApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/sessions/${queryArg.sessionId}/logs`,
+ params: { max_lines: queryArg.maxLines },
+ }),
+ }),
+ getSessionsImages: build.query<
+ GetSessionsImagesApiResponse,
+ GetSessionsImagesApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/sessions/images`,
+ params: { image_url: queryArg.imageUrl },
+ }),
+ }),
+ }),
+ overrideExisting: false,
+});
+export { injectedRtkApi as sessionsV2GeneratedApi };
+export type GetNotebooksImagesApiResponse = unknown;
+export type GetNotebooksImagesApiArg = {
+ /** The Docker image URL (tag included) that should be fetched. */
+ imageUrl: string;
+};
+export type GetNotebooksLogsByServerNameApiResponse =
+ /** status 200 Server logs. An array of strings where each element is a line of the logs. */ ServerLogs;
+export type GetNotebooksLogsByServerNameApiArg = {
+ /** The name of the server whose logs should be fetched. */
+ serverName: ServerName;
+ /** The maximum number of (most recent) lines to return from the logs. */
+ maxLines?: number;
+};
+export type GetNotebooksServerOptionsApiResponse =
+ /** status 200 Server options such as CPU, memory, storage, etc. */ ServerOptionsEndpointResponse;
+export type GetNotebooksServerOptionsApiArg = void;
+export type PostNotebooksServersApiResponse =
+ /** status 201 The project was created */ NotebookResponse;
+export type PostNotebooksServersApiArg = {
+ launchNotebookRequestOld: LaunchNotebookRequestOld;
+};
+export type GetNotebooksServersApiResponse =
+ /** status 200 Map of all servers for a user. */ ServersGetResponse;
+export type GetNotebooksServersApiArg = {
+ project?: string;
+ commitSha?: string;
+ namespace?: string;
+ branch?: string;
+};
+export type DeleteNotebooksServersByServerNameApiResponse =
+ /** status 204 The server was stopped successfully. */ void;
+export type DeleteNotebooksServersByServerNameApiArg = {
+ /** The name of the server that should be deleted. */
+ serverName: ServerName;
+ /** If true, delete immediately disregarding the grace period
+ of the underlying JupyterServer resource.
+ */
+ forced?: boolean;
+};
+export type GetNotebooksServersByServerNameApiResponse =
+ /** status 200 Server properties. */ NotebookResponse;
+export type GetNotebooksServersByServerNameApiArg = {
+ /** The name of the server for which additional information is required. */
+ serverName: ServerName;
+};
+export type PatchNotebooksServersByServerNameApiResponse =
+ /** status 200 The server was patched successfully. */ NotebookResponse;
+export type PatchNotebooksServersByServerNameApiArg = {
+ /** The name of the server that should be patched. */
+ serverName: ServerName;
+ patchServerRequest: PatchServerRequest;
+};
+export type PostSessionsApiResponse =
+ /** status 200 The session already exists */
+ SessionResponse | /** status 201 The session was created */ SessionResponse;
+export type PostSessionsApiArg = {
+ sessionPostRequest: SessionPostRequest;
+};
+export type GetSessionsApiResponse =
+ /** status 200 Information about the sessions */ SessionListResponse;
+export type GetSessionsApiArg = void;
+export type GetSessionsBySessionIdApiResponse =
+ /** status 200 Information about the session */ SessionResponse;
+export type GetSessionsBySessionIdApiArg = {
+ /** The id of the session */
+ sessionId: string;
+};
+export type DeleteSessionsBySessionIdApiResponse =
+ /** status 204 The session was deleted or it never existed in the first place */ void;
+export type DeleteSessionsBySessionIdApiArg = {
+ /** The id of the session that should be deleted */
+ sessionId: string;
+};
+export type PatchSessionsBySessionIdApiResponse =
+ /** status 200 The session was patched */ SessionResponse;
+export type PatchSessionsBySessionIdApiArg = {
+ /** The id of the session */
+ sessionId: string;
+ sessionPatchRequest: SessionPatchRequest;
+};
+export type GetSessionsBySessionIdLogsApiResponse =
+ /** status 200 The session logs */ SessionLogsResponse;
+export type GetSessionsBySessionIdLogsApiArg = {
+ /** The id of the session */
+ sessionId: string;
+ /** The maximum number of most-recent lines to return for each container */
+ maxLines?: number;
+};
+export type GetSessionsImagesApiResponse =
+ /** status 200 The docker image can be found */ void;
+export type GetSessionsImagesApiArg = {
+ /** The Docker image URL (tag included) that should be fetched. */
+ imageUrl: string;
+};
+export type ServerLogs = {
+ "jupyter-server"?: string;
+ [key: string]: any;
+};
+export type ErrorResponse = {
+ error: {
+ code: number;
+ detail?: string;
+ message: string;
+ };
+};
+export type ServerName = string;
+export type Generated = {
+ enabled: boolean;
+};
+export type StringServerOptionsChoice = {
+ default: string;
+ displayName: string;
+ options?: string[];
+ order: number;
+ type: "enum" | "boolean";
+};
+export type BoolServerOptionsChoice = {
+ default: boolean;
+ displayName: string;
+ order: number;
+ type: "enum" | "boolean";
+};
+export type ServerOptionsEndpointResponse = {
+ cloudstorage: Generated;
+ defaultUrl?: StringServerOptionsChoice;
+ lfs_auto_fetch?: BoolServerOptionsChoice;
+};
+export type UserPodAnnotations = {
+ "jupyter.org/servername"?: string;
+ "jupyter.org/username"?: string;
+ "renku.io/branch": string;
+ "renku.io/commit-sha": string;
+ "renku.io/default_image_used": string;
+ "renku.io/git-host"?: string;
+ "renku.io/gitlabProjectId"?: string;
+ "renku.io/hibernatedSecondsThreshold"?: string;
+ "renku.io/hibernation"?: string;
+ "renku.io/hibernationBranch"?: string;
+ "renku.io/hibernationCommitSha"?: string;
+ "renku.io/hibernationDate"?: string;
+ "renku.io/hibernationDirty"?: string;
+ "renku.io/hibernationSynchronized"?: string;
+ "renku.io/idleSecondsThreshold"?: string;
+ "renku.io/lastActivityDate"?: string;
+ "renku.io/launcherId"?: string;
+ "renku.io/namespace": string;
+ "renku.io/projectId"?: string;
+ "renku.io/projectName": string;
+ "renku.io/renkuVersion"?: string;
+ "renku.io/repository": string;
+ "renku.io/resourceClassId"?: string;
+ "renku.io/servername"?: string;
+ "renku.io/username"?: string;
+ [key: string]: any;
+};
+export type LaunchNotebookResponseCloudStorage = {
+ mount_folder?: any;
+ remote?: any;
+ type?: any;
+};
+export type ResourceRequests = {
+ cpu: any;
+ gpu?: any;
+ memory: any;
+ storage?: any;
+};
+export type ResourceUsage = {
+ cpu?: any;
+ memory?: any;
+ storage?: any;
+};
+export type UserPodResources = {
+ requests?: ResourceRequests;
+ usage?: ResourceUsage;
+};
+export type ServerStatusDetail = {
+ status: "ready" | "waiting" | "executing" | "failed";
+ step: string;
+};
+export type ServerStatusWarning = {
+ critical?: boolean;
+ message: string;
+};
+export type ServerStatus = {
+ details: ServerStatusDetail[];
+ message?: string;
+ readyNumContainers: number;
+ state: "running" | "starting" | "stopping" | "failed" | "hibernated";
+ totalNumContainers: number;
+ warnings?: ServerStatusWarning[];
+};
+export type NotebookResponse = {
+ annotations?: UserPodAnnotations;
+ cloudstorage?: LaunchNotebookResponseCloudStorage[];
+ image?: string;
+ name?: ServerName;
+ resources?: UserPodResources;
+ started?: string | null;
+ state?: object;
+ status?: ServerStatus;
+ url?: string;
+};
+export type RCloneStorageRequest = {
+ configuration?: {
+ [key: string]: any;
+ } | null;
+ readonly?: boolean;
+ source_path?: string;
+ storage_id?: string | null;
+ target_path?: string;
+};
+export type LaunchNotebookRequestServerOptions = {
+ cpu_request?: any;
+ defaultUrl?: string;
+ disk_request?: any;
+ gpu_request?: any;
+ lfs_auto_fetch?: boolean;
+ mem_request?: any;
+};
+export type UserSecrets = {
+ mount_path: any;
+ user_secret_ids: any[];
+};
+export type LaunchNotebookRequestOld = {
+ branch?: string;
+ cloudstorage?: RCloneStorageRequest[];
+ commit_sha: string;
+ default_url?: string;
+ environment_variables?: {
+ [key: string]: string;
+ };
+ image?: string | null;
+ lfs_auto_fetch?: boolean;
+ namespace: string;
+ notebook?: string | null;
+ project: string;
+ resource_class_id?: number | null;
+ serverOptions?: LaunchNotebookRequestServerOptions;
+ storage?: number;
+ user_secrets?: UserSecrets | null;
+};
+export type ServersGetResponse = {
+ servers?: {
+ [key: string]: NotebookResponse;
+ };
+};
+export type PatchServerRequest = {
+ resource_class_id?: number;
+ state?: "running" | "hibernated";
+};
+export type SessionResourcesRequests = {
+ /** Fractional CPUs */
+ cpu?: number;
+ /** Number of GPUs used */
+ gpu?: number;
+ /** Ammount of RAM for the session, in gigabytes */
+ memory?: number;
+ /** The size of disk storage for the session, in gigabytes */
+ storage?: number;
+};
+export type SessionResources = {
+ requests?: SessionResourcesRequests;
+};
+export type SessionStatus = {
+ message?: string;
+ state: "running" | "starting" | "stopping" | "failed" | "hibernated";
+ will_hibernate_at?: string | null;
+ will_delete_at?: string | null;
+ ready_containers: number;
+ total_containers: number;
+};
+export type Ulid = string;
+export type SessionResponse = {
+ image: string;
+ name: ServerName;
+ resources: SessionResources;
+ started: string | null;
+ status: SessionStatus;
+ url: string;
+ project_id: Ulid;
+ launcher_id: Ulid;
+ resource_class_id: number;
+};
+export type SessionCloudStoragePost = {
+ configuration?: {
+ [key: string]: any;
+ };
+ readonly?: boolean;
+ source_path?: string;
+ target_path?: string;
+ storage_id: Ulid & any;
+};
+export type SessionCloudStoragePostList = SessionCloudStoragePost[];
+export type SessionPostRequest = {
+ launcher_id: Ulid;
+ /** The size of disk storage for the session, in gigabytes */
+ disk_storage?: number;
+ resource_class_id?: number | null;
+ cloudstorage?: SessionCloudStoragePostList;
+};
+export type SessionListResponse = SessionResponse[];
+export type SessionPatchRequest = {
+ resource_class_id?: number;
+ state?: "running" | "hibernated";
+};
+export type SessionLogsResponse = {
+ [key: string]: string;
+};
+export const {
+ useGetNotebooksImagesQuery,
+ useGetNotebooksLogsByServerNameQuery,
+ useGetNotebooksServerOptionsQuery,
+ usePostNotebooksServersMutation,
+ useGetNotebooksServersQuery,
+ useDeleteNotebooksServersByServerNameMutation,
+ useGetNotebooksServersByServerNameQuery,
+ usePatchNotebooksServersByServerNameMutation,
+ usePostSessionsMutation,
+ useGetSessionsQuery,
+ useGetSessionsBySessionIdQuery,
+ useDeleteSessionsBySessionIdMutation,
+ usePatchSessionsBySessionIdMutation,
+ useGetSessionsBySessionIdLogsQuery,
+ useGetSessionsImagesQuery,
+} = injectedRtkApi;
diff --git a/client/src/features/sessionsV2/api/sessionsV2.openapi.json b/client/src/features/sessionsV2/api/sessionsV2.openapi.json
new file mode 100644
index 0000000000..c57a70f1cc
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionsV2.openapi.json
@@ -0,0 +1,1420 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "title": "Renku Data Services API",
+ "description": "Service that allows creating, updating, deleting, and managing Renku user sessions.\nAll errors have the same format as the schema called ErrorResponse.\n",
+ "version": "v1"
+ },
+ "servers": [
+ {
+ "url": "/api/data"
+ }
+ ],
+ "paths": {
+ "/notebooks/images": {
+ "get": {
+ "description": "Docker image availability.",
+ "parameters": [
+ {
+ "description": "The Docker image URL (tag included) that should be fetched.",
+ "in": "query",
+ "name": "image_url",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The Docker image is available."
+ },
+ "404": {
+ "description": "The Docker image is not available."
+ }
+ },
+ "tags": ["notebooks"]
+ }
+ },
+ "/notebooks/logs/{server_name}": {
+ "get": {
+ "description": "Server logs.",
+ "parameters": [
+ {
+ "description": "The name of the server whose logs should be fetched.",
+ "in": "path",
+ "name": "server_name",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ServerName"
+ }
+ },
+ {
+ "description": "The maximum number of (most recent) lines to return from the logs.",
+ "in": "query",
+ "name": "max_lines",
+ "required": false,
+ "schema": {
+ "default": 250,
+ "minimum": 0,
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ServerLogs"
+ }
+ }
+ },
+ "description": "Server logs. An array of strings where each element is a line of the logs."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The specified server does not exist."
+ }
+ },
+ "tags": ["notebooks"]
+ }
+ },
+ "/notebooks/server_options": {
+ "get": {
+ "description": "Get the options available to customize when starting a server.",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ServerOptionsEndpointResponse"
+ }
+ }
+ },
+ "description": "Server options such as CPU, memory, storage, etc."
+ }
+ },
+ "tags": ["notebooks"]
+ }
+ },
+ "/notebooks/servers": {
+ "post": {
+ "summary": "Launch a new session",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/LaunchNotebookRequestOld"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The project was created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/NotebookResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["notebooks"]
+ },
+ "get": {
+ "description": "Information about all active servers for a user.",
+ "parameters": [
+ {
+ "in": "query",
+ "name": "project",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "commit_sha",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "namespace",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "branch",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ServersGetResponse"
+ }
+ }
+ },
+ "description": "Map of all servers for a user."
+ }
+ },
+ "tags": ["notebooks"]
+ }
+ },
+ "/notebooks/servers/{server_name}": {
+ "delete": {
+ "description": "Stop a running server by name.",
+ "parameters": [
+ {
+ "description": "The name of the server that should be deleted.",
+ "in": "path",
+ "name": "server_name",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ServerName"
+ }
+ },
+ {
+ "description": "If true, delete immediately disregarding the grace period\nof the underlying JupyterServer resource.\n",
+ "in": "query",
+ "name": "forced",
+ "required": false,
+ "schema": {
+ "default": false,
+ "type": "boolean"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "The server was stopped successfully."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The server cannot be found."
+ },
+ "500": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The server exists but could not be successfully deleted."
+ }
+ },
+ "tags": ["notebooks"]
+ },
+ "get": {
+ "description": "Information about an active server.",
+ "parameters": [
+ {
+ "description": "The name of the server for which additional information is required.",
+ "in": "path",
+ "name": "server_name",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ServerName"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/NotebookResponse"
+ }
+ }
+ },
+ "description": "Server properties."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The specified server does not exist."
+ }
+ },
+ "tags": ["notebooks"]
+ },
+ "patch": {
+ "description": "Patch a running server by name.",
+ "parameters": [
+ {
+ "description": "The name of the server that should be patched.",
+ "in": "path",
+ "name": "server_name",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ServerName"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/PatchServerRequest"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/NotebookResponse"
+ }
+ }
+ },
+ "description": "The server was patched successfully."
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid json argument value."
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The server cannot be found."
+ },
+ "500": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "The server exists but could not be successfully hibernated."
+ }
+ },
+ "tags": ["notebooks"]
+ }
+ },
+ "/sessions": {
+ "post": {
+ "summary": "Launch a new session",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionPostRequest"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The session already exists",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionResponse"
+ }
+ }
+ }
+ },
+ "201": {
+ "description": "The session was created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ },
+ "get": {
+ "summary": "Get a list of all sessions for a user",
+ "responses": {
+ "200": {
+ "description": "Information about the sessions",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionListResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ }
+ },
+ "/sessions/{session_id}": {
+ "get": {
+ "summary": "Get information about a specific session",
+ "parameters": [
+ {
+ "description": "The id of the session",
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Information about the session",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ },
+ "delete": {
+ "parameters": [
+ {
+ "description": "The id of the session that should be deleted",
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "summary": "Fully remove a session",
+ "responses": {
+ "204": {
+ "description": "The session was deleted or it never existed in the first place"
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ },
+ "patch": {
+ "summary": "Patch a session",
+ "parameters": [
+ {
+ "description": "The id of the session",
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionPatchRequest"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The session was patched",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ }
+ },
+ "/sessions/{session_id}/logs": {
+ "get": {
+ "summary": "Get all logs from a specific session",
+ "parameters": [
+ {
+ "description": "The id of the session",
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "description": "The maximum number of most-recent lines to return for each container",
+ "in": "query",
+ "name": "max_lines",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "default": 250
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The session logs",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLogsResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ }
+ },
+ "/sessions/images": {
+ "get": {
+ "summary": "Check if a session image exists",
+ "parameters": [
+ {
+ "description": "The Docker image URL (tag included) that should be fetched.",
+ "in": "query",
+ "name": "image_url",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The docker image can be found"
+ },
+ "404": {
+ "description": "The docker image cannot be found or the user does not have permissions to access it",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["sessions"]
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "BoolServerOptionsChoice": {
+ "properties": {
+ "default": {
+ "type": "boolean"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "order": {
+ "type": "integer"
+ },
+ "type": {
+ "enum": ["enum", "boolean"],
+ "type": "string"
+ }
+ },
+ "required": ["default", "displayName", "order", "type"],
+ "type": "object"
+ },
+ "CullingThreshold": {
+ "properties": {
+ "hibernation": {
+ "type": "integer"
+ },
+ "idle": {
+ "type": "integer"
+ }
+ },
+ "required": ["hibernation", "idle"],
+ "type": "object"
+ },
+ "DefaultCullingThresholds": {
+ "properties": {
+ "anonymous": {
+ "$ref": "#/components/schemas/CullingThreshold"
+ },
+ "registered": {
+ "$ref": "#/components/schemas/CullingThreshold"
+ }
+ },
+ "required": ["anonymous", "registered"],
+ "type": "object"
+ },
+ "ErrorResponse": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "integer",
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "example": 1404
+ },
+ "detail": {
+ "type": "string",
+ "example": "A more detailed optional message showing what the problem was"
+ },
+ "message": {
+ "type": "string",
+ "example": "Something went wrong - please try again later"
+ }
+ },
+ "required": ["code", "message"]
+ }
+ },
+ "required": ["error"]
+ },
+ "Generated": {
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ }
+ },
+ "required": ["enabled"],
+ "type": "object"
+ },
+ "LaunchNotebookRequest": {
+ "properties": {
+ "project_id": {
+ "type": "string"
+ },
+ "launcher_id": {
+ "type": "string"
+ },
+ "image": {
+ "type": "string"
+ },
+ "repositories": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "$ref": "#/components/schemas/LaunchNotebookRequestRepository"
+ }
+ },
+ "cloudstorage": {
+ "default": [],
+ "items": {
+ "$ref": "#/components/schemas/RCloneStorageRequest"
+ },
+ "type": "array"
+ },
+ "storage": {
+ "default": 1,
+ "type": "integer"
+ },
+ "resource_class_id": {
+ "default": null,
+ "nullable": true,
+ "type": "integer"
+ },
+ "environment_variables": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "default": {},
+ "type": "object"
+ },
+ "user_secrets": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/UserSecrets"
+ }
+ ],
+ "default": null,
+ "nullable": true
+ }
+ },
+ "required": ["project_id", "launcher_id"],
+ "type": "object"
+ },
+ "LaunchNotebookRequestRepository": {
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "dirname": {
+ "type": "string"
+ },
+ "branch": {
+ "type": "string"
+ },
+ "commit_sha": {
+ "type": "string"
+ }
+ },
+ "required": ["url"]
+ },
+ "LaunchNotebookRequestOld": {
+ "properties": {
+ "branch": {
+ "default": "master",
+ "type": "string"
+ },
+ "cloudstorage": {
+ "default": [],
+ "items": {
+ "$ref": "#/components/schemas/RCloneStorageRequest"
+ },
+ "type": "array"
+ },
+ "commit_sha": {
+ "type": "string"
+ },
+ "default_url": {
+ "default": "/lab",
+ "type": "string"
+ },
+ "environment_variables": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "default": {},
+ "type": "object"
+ },
+ "image": {
+ "default": null,
+ "nullable": true,
+ "type": "string"
+ },
+ "lfs_auto_fetch": {
+ "default": false,
+ "type": "boolean"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "notebook": {
+ "default": null,
+ "nullable": true,
+ "type": "string"
+ },
+ "project": {
+ "type": "string"
+ },
+ "resource_class_id": {
+ "default": null,
+ "nullable": true,
+ "type": "integer"
+ },
+ "serverOptions": {
+ "$ref": "#/components/schemas/LaunchNotebookRequestServerOptions"
+ },
+ "storage": {
+ "default": 1,
+ "type": "integer"
+ },
+ "user_secrets": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/UserSecrets"
+ }
+ ],
+ "default": null,
+ "nullable": true
+ }
+ },
+ "required": ["commit_sha", "namespace", "project"],
+ "type": "object"
+ },
+ "LaunchNotebookRequestServerOptions": {
+ "properties": {
+ "cpu_request": {
+ "default": 0
+ },
+ "defaultUrl": {
+ "default": "/lab",
+ "type": "string"
+ },
+ "disk_request": {
+ "default": "1G"
+ },
+ "gpu_request": {
+ "default": 0
+ },
+ "lfs_auto_fetch": {
+ "default": false,
+ "type": "boolean"
+ },
+ "mem_request": {
+ "default": "0G"
+ }
+ },
+ "type": "object"
+ },
+ "LaunchNotebookResponseCloudStorage": {
+ "properties": {
+ "mount_folder": {},
+ "remote": {},
+ "type": {}
+ },
+ "type": "object"
+ },
+ "NotebookResponse": {
+ "properties": {
+ "annotations": {
+ "$ref": "#/components/schemas/_UserPodAnnotations"
+ },
+ "cloudstorage": {
+ "items": {
+ "$ref": "#/components/schemas/LaunchNotebookResponseCloudStorage"
+ },
+ "type": "array"
+ },
+ "image": {
+ "type": "string"
+ },
+ "name": {
+ "$ref": "#/components/schemas/ServerName"
+ },
+ "resources": {
+ "$ref": "#/components/schemas/UserPodResources"
+ },
+ "started": {
+ "format": "date-time",
+ "nullable": true,
+ "type": "string"
+ },
+ "state": {
+ "type": "object"
+ },
+ "status": {
+ "$ref": "#/components/schemas/ServerStatus"
+ },
+ "url": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "NotebooksServiceInfo": {
+ "properties": {
+ "anonymousSessionsEnabled": {
+ "type": "boolean"
+ },
+ "cloudstorageEnabled": {
+ "type": "boolean"
+ },
+ "defaultCullingThresholds": {
+ "$ref": "#/components/schemas/DefaultCullingThresholds"
+ },
+ "sshEnabled": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "anonymousSessionsEnabled",
+ "cloudstorageEnabled",
+ "defaultCullingThresholds",
+ "sshEnabled"
+ ],
+ "type": "object"
+ },
+ "NotebooksServiceVersions": {
+ "properties": {
+ "data": {
+ "$ref": "#/components/schemas/NotebooksServiceInfo"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": ["data", "version"],
+ "type": "object"
+ },
+ "PatchServerRequest": {
+ "properties": {
+ "resource_class_id": {
+ "type": "integer"
+ },
+ "state": {
+ "enum": ["running", "hibernated"],
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "RCloneStorageRequest": {
+ "properties": {
+ "configuration": {
+ "additionalProperties": {},
+ "default": null,
+ "nullable": true,
+ "type": "object"
+ },
+ "readonly": {
+ "default": true,
+ "type": "boolean"
+ },
+ "source_path": {
+ "type": "string"
+ },
+ "storage_id": {
+ "default": null,
+ "nullable": true,
+ "type": "string"
+ },
+ "target_path": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ResourceRequests": {
+ "properties": {
+ "cpu": {},
+ "gpu": {},
+ "memory": {},
+ "storage": {}
+ },
+ "required": ["cpu", "memory"],
+ "type": "object"
+ },
+ "ResourceUsage": {
+ "properties": {
+ "cpu": {},
+ "memory": {},
+ "storage": {}
+ },
+ "type": "object"
+ },
+ "ServerLogs": {
+ "additionalProperties": true,
+ "properties": {
+ "jupyter-server": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ServerOptionsEndpointResponse": {
+ "properties": {
+ "cloudstorage": {
+ "$ref": "#/components/schemas/Generated"
+ },
+ "defaultUrl": {
+ "$ref": "#/components/schemas/StringServerOptionsChoice"
+ },
+ "lfs_auto_fetch": {
+ "$ref": "#/components/schemas/BoolServerOptionsChoice"
+ }
+ },
+ "required": ["cloudstorage"],
+ "type": "object"
+ },
+ "ServerStatus": {
+ "properties": {
+ "details": {
+ "items": {
+ "$ref": "#/components/schemas/ServerStatusDetail"
+ },
+ "type": "array"
+ },
+ "message": {
+ "type": "string"
+ },
+ "readyNumContainers": {
+ "minimum": 0,
+ "type": "integer"
+ },
+ "state": {
+ "enum": ["running", "starting", "stopping", "failed", "hibernated"],
+ "type": "string"
+ },
+ "totalNumContainers": {
+ "minimum": 0,
+ "type": "integer"
+ },
+ "warnings": {
+ "items": {
+ "$ref": "#/components/schemas/ServerStatusWarning"
+ },
+ "type": "array"
+ }
+ },
+ "required": [
+ "details",
+ "readyNumContainers",
+ "state",
+ "totalNumContainers"
+ ],
+ "type": "object"
+ },
+ "ServerStatusDetail": {
+ "properties": {
+ "status": {
+ "enum": ["ready", "waiting", "executing", "failed"],
+ "type": "string"
+ },
+ "step": {
+ "type": "string"
+ }
+ },
+ "required": ["status", "step"],
+ "type": "object"
+ },
+ "ServerStatusWarning": {
+ "properties": {
+ "critical": {
+ "default": false,
+ "type": "boolean"
+ },
+ "message": {
+ "type": "string"
+ }
+ },
+ "required": ["message"],
+ "type": "object"
+ },
+ "ServersGetResponse": {
+ "properties": {
+ "servers": {
+ "additionalProperties": {
+ "$ref": "#/components/schemas/NotebookResponse"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "StringServerOptionsChoice": {
+ "properties": {
+ "default": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "options": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "order": {
+ "type": "integer"
+ },
+ "type": {
+ "enum": ["enum", "boolean"],
+ "type": "string"
+ }
+ },
+ "required": ["default", "displayName", "order", "type"],
+ "type": "object"
+ },
+ "UserPodResources": {
+ "properties": {
+ "requests": {
+ "$ref": "#/components/schemas/ResourceRequests"
+ },
+ "usage": {
+ "$ref": "#/components/schemas/ResourceUsage"
+ }
+ },
+ "type": "object"
+ },
+ "UserSecrets": {
+ "properties": {
+ "mount_path": {},
+ "user_secret_ids": {
+ "items": {},
+ "type": "array"
+ }
+ },
+ "required": ["mount_path", "user_secret_ids"],
+ "type": "object"
+ },
+ "_UserPodAnnotations": {
+ "additionalProperties": true,
+ "properties": {
+ "jupyter.org/servername": {
+ "type": "string"
+ },
+ "jupyter.org/username": {
+ "type": "string"
+ },
+ "renku.io/branch": {
+ "type": "string"
+ },
+ "renku.io/commit-sha": {
+ "type": "string"
+ },
+ "renku.io/default_image_used": {
+ "type": "string"
+ },
+ "renku.io/git-host": {
+ "type": "string"
+ },
+ "renku.io/gitlabProjectId": {
+ "type": "string"
+ },
+ "renku.io/hibernatedSecondsThreshold": {
+ "type": "string"
+ },
+ "renku.io/hibernation": {
+ "type": "string"
+ },
+ "renku.io/hibernationBranch": {
+ "type": "string"
+ },
+ "renku.io/hibernationCommitSha": {
+ "type": "string"
+ },
+ "renku.io/hibernationDate": {
+ "type": "string"
+ },
+ "renku.io/hibernationDirty": {
+ "type": "string"
+ },
+ "renku.io/hibernationSynchronized": {
+ "type": "string"
+ },
+ "renku.io/idleSecondsThreshold": {
+ "type": "string"
+ },
+ "renku.io/lastActivityDate": {
+ "type": "string"
+ },
+ "renku.io/launcherId": {
+ "type": "string"
+ },
+ "renku.io/namespace": {
+ "type": "string"
+ },
+ "renku.io/projectId": {
+ "type": "string"
+ },
+ "renku.io/projectName": {
+ "type": "string"
+ },
+ "renku.io/renkuVersion": {
+ "type": "string"
+ },
+ "renku.io/repository": {
+ "type": "string"
+ },
+ "renku.io/resourceClassId": {
+ "type": "string"
+ },
+ "renku.io/servername": {
+ "type": "string"
+ },
+ "renku.io/username": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "renku.io/branch",
+ "renku.io/commit-sha",
+ "renku.io/default_image_used",
+ "renku.io/namespace",
+ "renku.io/projectName",
+ "renku.io/repository"
+ ],
+ "type": "object"
+ },
+ "SessionPostRequest": {
+ "properties": {
+ "launcher_id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "disk_storage": {
+ "default": 1,
+ "type": "integer",
+ "description": "The size of disk storage for the session, in gigabytes"
+ },
+ "resource_class_id": {
+ "default": null,
+ "nullable": true,
+ "type": "integer"
+ },
+ "cloudstorage": {
+ "$ref": "#/components/schemas/SessionCloudStoragePostList"
+ }
+ },
+ "required": ["launcher_id"],
+ "type": "object"
+ },
+ "SessionResponse": {
+ "properties": {
+ "image": {
+ "type": "string"
+ },
+ "name": {
+ "$ref": "#/components/schemas/ServerName"
+ },
+ "resources": {
+ "$ref": "#/components/schemas/SessionResources"
+ },
+ "started": {
+ "format": "date-time",
+ "nullable": true,
+ "type": "string"
+ },
+ "status": {
+ "$ref": "#/components/schemas/SessionStatus"
+ },
+ "url": {
+ "type": "string"
+ },
+ "project_id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "launcher_id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "resource_class_id": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "image",
+ "name",
+ "resources",
+ "started",
+ "status",
+ "url",
+ "project_id",
+ "launcher_id",
+ "resource_class_id"
+ ],
+ "type": "object"
+ },
+ "SessionListResponse": {
+ "items": {
+ "$ref": "#/components/schemas/SessionResponse"
+ },
+ "type": "array"
+ },
+ "SessionPatchRequest": {
+ "properties": {
+ "resource_class_id": {
+ "type": "integer"
+ },
+ "state": {
+ "enum": ["running", "hibernated"],
+ "type": "string"
+ }
+ }
+ },
+ "SessionStatus": {
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "state": {
+ "enum": ["running", "starting", "stopping", "failed", "hibernated"],
+ "type": "string"
+ },
+ "will_hibernate_at": {
+ "format": "date-time",
+ "nullable": true,
+ "type": "string"
+ },
+ "will_delete_at": {
+ "format": "date-time",
+ "nullable": true,
+ "type": "string"
+ },
+ "ready_containers": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "total_containers": {
+ "type": "integer",
+ "minimum": 0
+ }
+ },
+ "required": ["state", "ready_containers", "total_containers"],
+ "type": "object"
+ },
+ "SessionResources": {
+ "properties": {
+ "requests": {
+ "$ref": "#/components/schemas/SessionResourcesRequests"
+ }
+ },
+ "type": "object"
+ },
+ "SessionResourcesRequests": {
+ "properties": {
+ "cpu": {
+ "type": "number",
+ "description": "Fractional CPUs"
+ },
+ "gpu": {
+ "type": "integer",
+ "description": "Number of GPUs used"
+ },
+ "memory": {
+ "type": "integer",
+ "description": "Ammount of RAM for the session, in gigabytes"
+ },
+ "storage": {
+ "type": "integer",
+ "description": "The size of disk storage for the session, in gigabytes"
+ }
+ },
+ "example": {
+ "cpu": 1.5,
+ "memory": 1,
+ "storage": 40,
+ "gpu": 0
+ },
+ "type": "object"
+ },
+ "SessionLogsResponse": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "container-A": "Log line 1\nLog line 2",
+ "container-B": "Log line 1\nLog line 2"
+ }
+ },
+ "Ulid": {
+ "description": "ULID identifier",
+ "type": "string",
+ "minLength": 26,
+ "maxLength": 26,
+ "pattern": "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
+ },
+ "SessionCloudStoragePostList": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SessionCloudStoragePost"
+ }
+ },
+ "SessionCloudStoragePost": {
+ "type": "object",
+ "properties": {
+ "configuration": {
+ "type": "object",
+ "additionalProperties": true
+ },
+ "readonly": {
+ "type": "boolean"
+ },
+ "source_path": {
+ "type": "string"
+ },
+ "target_path": {
+ "type": "string"
+ },
+ "storage_id": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ {
+ "description": "If the storage_id is provided then this config must replace an existing storage config in the session"
+ }
+ ]
+ }
+ },
+ "required": ["storage_id"]
+ },
+ "ServerName": {
+ "type": "string",
+ "minLength": 5,
+ "maxLength": 50,
+ "pattern": "^[a-z]([-a-z0-9]*[a-z0-9])?$",
+ "example": "d185e68d-d43-renku-2-b9ac279a4e8a85ac28d08"
+ }
+ },
+ "responses": {
+ "Error": {
+ "description": "The schema for all 4xx and 5xx responses",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
index a57bc65d8f..cf0b066f42 100644
--- a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
+++ b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
@@ -476,7 +476,7 @@ interface ModifySessionModalProps {
resources: SessionResources;
status: SessionStatus;
toggleModal: () => void;
- resource_class_id: string;
+ resource_class_id: number;
}
function ModifySessionModal({
@@ -512,7 +512,7 @@ interface ModifySessionModalContentProps {
resources: SessionResources;
status: SessionStatus;
toggleModal: () => void;
- resource_class_id: string;
+ resource_class_id: number;
}
function ModifySessionModalContent({
@@ -556,7 +556,7 @@ function ModifySessionModalContent({
useEffect(() => {
const currentSessionClass = resourcePools
?.flatMap((pool) => pool.classes)
- .find((c) => `${c.id}` == resource_class_id);
+ .find((c) => c.id == resource_class_id);
setCurrentSessionClass(currentSessionClass);
}, [resource_class_id, resourcePools]);
@@ -614,7 +614,7 @@ function ModifySessionModalContent({
resourcePools.length == 0 ||
isError ||
currentSessionClass == null ||
- resource_class_id === `${currentSessionClass?.id}`
+ resource_class_id === currentSessionClass?.id
}
onClick={onClick({ resumeSession: true })}
type="submit"
@@ -632,7 +632,7 @@ function ModifySessionModalContent({
isError ||
currentSessionClass == null ||
(resource_class_id != null &&
- resource_class_id === `${currentSessionClass?.id}`)
+ resource_class_id === currentSessionClass?.id)
}
onClick={onClick({ resumeSession: false })}
type="submit"
diff --git a/client/src/features/sessionsV2/components/SessionStatus/SessionStatus.tsx b/client/src/features/sessionsV2/components/SessionStatus/SessionStatus.tsx
index bc03c427fd..f3bf50b914 100644
--- a/client/src/features/sessionsV2/components/SessionStatus/SessionStatus.tsx
+++ b/client/src/features/sessionsV2/components/SessionStatus/SessionStatus.tsx
@@ -134,7 +134,9 @@ export function SessionStatusV2Description({
"align-items-center"
)}
>
-
+ {started && (
+
+ )}
{showInfoDetails && (
)}
diff --git a/client/src/features/sessionsV2/sessionsV2.api.ts b/client/src/features/sessionsV2/sessionsV2.api.ts
index 003793113c..1a64cb46e5 100644
--- a/client/src/features/sessionsV2/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/sessionsV2.api.ts
@@ -216,7 +216,7 @@ const sessionsV2Api = createApi({
export default sessionsV2Api;
export const {
- useGetSessionsQuery,
+ // useGetSessionsQuery,
useGetSessionEnvironmentsQuery,
useGetSessionLaunchersQuery,
useGetProjectSessionLauncherQuery,
diff --git a/client/src/features/sessionsV2/sessionsV2.types.ts b/client/src/features/sessionsV2/sessionsV2.types.ts
index d111671ae0..84f8990489 100644
--- a/client/src/features/sessionsV2/sessionsV2.types.ts
+++ b/client/src/features/sessionsV2/sessionsV2.types.ts
@@ -135,19 +135,19 @@ export interface SessionLauncherForm {
}
export interface SessionResources {
- requests: {
- cpu: number;
- gpu: number;
- memory: number;
- storage: number;
+ requests?: {
+ cpu?: number;
+ gpu?: number;
+ memory?: number;
+ storage?: number;
};
}
export interface SessionStatus {
message?: string;
state: "running" | "starting" | "stopping" | "failed" | "hibernated";
- will_hibernate_at?: string;
- will_delete_at?: string;
+ will_hibernate_at?: string | null;
+ will_delete_at?: string | null;
ready_containers: number;
total_containers: number;
}
@@ -157,12 +157,12 @@ export interface SessionV2 {
image: string;
name: string;
resources: SessionResources;
- started: string;
+ started: string | null;
status: SessionStatus;
url: string;
project_id: string;
launcher_id: string;
- resource_class_id: string;
+ resource_class_id: number;
}
export interface SessionCloudStorageV2 {
From 59f10413cda23db32dd151cc90744773aba71224 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 15:36:42 +0100
Subject: [PATCH 03/11] more API updates
---
client/.eslintignore | 1 +
.../sessionsV2/PauseOrDeleteSessionModal.tsx | 15 ++++----
.../SessionShowPage/SessionPaused.tsx | 8 +++--
.../features/sessionsV2/SessionStartPage.tsx | 7 ++--
.../features/sessionsV2/api/sessionsV2.api.ts | 36 +++++++++++++++++--
.../SessionButton/ActiveSessionButton.tsx | 22 +++++++-----
.../src/features/sessionsV2/sessionsV2.api.ts | 6 ++--
7 files changed, 72 insertions(+), 23 deletions(-)
diff --git a/client/.eslintignore b/client/.eslintignore
index e8891d7569..6eb2d9a87f 100644
--- a/client/.eslintignore
+++ b/client/.eslintignore
@@ -5,3 +5,4 @@ src/features/projectsV2/api/projectV2.api.ts
src/features/projectsV2/api/storagesV2.api.ts
src/features/dataConnectorsV2/api/data-connectors.api.ts
src/features/usersV2/api/users.generated-api.ts
+src/features/sessionsV2/api/sessionsV2.generated-api.ts
diff --git a/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx b/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
index debd472ab6..99f6add6ea 100644
--- a/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
+++ b/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
@@ -35,9 +35,9 @@ import useLegacySelector from "../../utils/customHooks/useLegacySelector.hook";
import styles from "../session/components/SessionModals.module.scss";
import { useWaitForSessionStatusV2 } from "../session/useWaitForSessionStatus.hook";
import {
- usePatchSessionMutation,
- useStopSessionMutation,
-} from "../sessionsV2/sessionsV2.api";
+ usePatchSessionsBySessionIdMutation as usePatchSessionMutation,
+ useDeleteSessionsBySessionIdMutation as useStopSessionMutation,
+} from "./api/sessionsV2.api";
import { SessionV2 } from "./sessionsV2.types";
import { Loader } from "../../components/Loader";
@@ -107,7 +107,7 @@ function AnonymousDeleteSessionModal({
const [isStopping, setIsStopping] = useState(false);
const onStopSession = useCallback(async () => {
- stopSession({ session_id: sessionName });
+ stopSession({ sessionId: sessionName });
setIsStopping(true);
}, [sessionName, stopSession]);
@@ -226,7 +226,10 @@ function PauseSessionModalContent({
const [isStopping, setIsStopping] = useState(false);
const onHibernateSession = useCallback(async () => {
- patchSession({ session_id: sessionName, state: "hibernated" });
+ patchSession({
+ sessionId: sessionName,
+ sessionPatchRequest: { state: "hibernated" },
+ });
setIsStopping(true);
}, [patchSession, sessionName]);
@@ -335,7 +338,7 @@ function DeleteSessionModalContent({
const [isStopping, setIsStopping] = useState(false);
const onStopSession = useCallback(async () => {
- stopSession({ session_id: sessionName });
+ stopSession({ sessionId: sessionName });
setIsStopping(true);
}, [sessionName, stopSession]);
diff --git a/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx b/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
index b1ff102cb9..4b21c73872 100644
--- a/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
+++ b/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
@@ -29,7 +29,8 @@ import { NOTIFICATION_TOPICS } from "../../../notifications/Notifications.consta
import type { NotificationsManager } from "../../../notifications/notifications.types";
import { ABSOLUTE_ROUTES } from "../../../routing/routes.constants";
import AppContext from "../../../utils/context/appContext";
-import { usePatchSessionMutation } from "../sessionsV2.api";
+// import { usePatchSessionMutation } from "../sessionsV2.api";
+import { usePatchSessionsBySessionIdMutation as usePatchSessionMutation } from "../api/sessionsV2.api";
import type { SessionV2 } from "../sessionsV2.types";
interface SessionPausedProps {
@@ -46,7 +47,10 @@ export default function SessionPaused({ session }: SessionPausedProps) {
const [isResuming, setIsResuming] = useState(false);
const onResumeSession = useCallback(() => {
- patchSession({ session_id: sessionName, state: "running" });
+ patchSession({
+ sessionId: sessionName,
+ sessionPatchRequest: { state: "running" },
+ });
setIsResuming(true);
}, [patchSession, sessionName]);
diff --git a/client/src/features/sessionsV2/SessionStartPage.tsx b/client/src/features/sessionsV2/SessionStartPage.tsx
index 3658fafc71..78cb602d4f 100644
--- a/client/src/features/sessionsV2/SessionStartPage.tsx
+++ b/client/src/features/sessionsV2/SessionStartPage.tsx
@@ -61,8 +61,9 @@ import { SelectResourceClassModal } from "./components/SessionModals/SelectResou
import {
useGetDockerImageQuery,
useGetProjectSessionLaunchersQuery,
- useLaunchSessionMutation,
+ // useLaunchSessionMutation,
} from "./sessionsV2.api";
+import { usePostSessionsMutation as useLaunchSessionMutation } from "./api/sessionsV2.api";
import { SessionLauncher } from "./sessionsV2.types";
import startSessionOptionsV2Slice from "./startSessionOptionsV2.slice";
import {
@@ -224,7 +225,9 @@ function SessionStarting({ launcher, project }: StartSessionFromLauncherProps) {
// Request session
useEffect(() => {
if (isLoadingStartSession || session != null || isError) return;
- startSessionV2(launcherToStart);
+ startSessionV2({
+ sessionPostRequest: launcherToStart,
+ });
dispatch(setFavicon("waiting"));
}, [
isLoadingStartSession,
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api.ts b/client/src/features/sessionsV2/api/sessionsV2.api.ts
index 8d15731888..b3cb527ed2 100644
--- a/client/src/features/sessionsV2/api/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/api/sessionsV2.api.ts
@@ -19,8 +19,37 @@
import { sessionsV2GeneratedApi } from "./sessionsV2.generated-api";
export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
- addTagTypes: [],
- endpoints: {},
+ addTagTypes: ["Session"],
+ endpoints: {
+ getSessions: {
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map(({ name }) => ({
+ id: name,
+ type: "Session" as const,
+ })),
+ "Session",
+ ]
+ : ["Session"],
+ },
+ getSessionsBySessionId: {
+ providesTags: (result) =>
+ result
+ ? [{ id: result.name, type: "Session" }, "Session"]
+ : ["Session"],
+ },
+ postSessions: {
+ invalidatesTags: ["Session"],
+ },
+ patchSessionsBySessionId: {
+ invalidatesTags: (result) =>
+ result ? [{ id: result.name, type: "Session" }] : ["Session"],
+ },
+ deleteSessionsBySessionId: {
+ invalidatesTags: ["Session"],
+ },
+ },
});
// useGetNotebooksImagesQuery,
@@ -43,6 +72,9 @@ export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
export const {
// "sessions" hooks
useGetSessionsQuery,
+ usePostSessionsMutation,
+ usePatchSessionsBySessionIdMutation,
+ useDeleteSessionsBySessionIdMutation,
} = sessionsV2Api;
export type * from "./sessionsV2.generated-api";
diff --git a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
index cf0b066f42..cf16483595 100644
--- a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
+++ b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
@@ -63,9 +63,9 @@ import { SessionClassSelectorV2 } from "../../../session/components/options/Sess
import { SessionStatusState } from "../../../session/sessions.types";
import { useWaitForSessionStatusV2 } from "../../../session/useWaitForSessionStatus.hook";
import {
- usePatchSessionMutation,
- useStopSessionMutation,
-} from "../../sessionsV2.api";
+ usePatchSessionsBySessionIdMutation as usePatchSessionMutation,
+ useDeleteSessionsBySessionIdMutation as useStopSessionMutation,
+} from "../../api/sessionsV2.api";
import {
SessionResources,
SessionStatus,
@@ -111,7 +111,10 @@ export default function ActiveSessionButton({
{ isSuccess: isSuccessResumeSession, error: errorResumeSession },
] = usePatchSessionMutation();
const onResumeSession = useCallback(() => {
- resumeSession({ session_id: session.name, state: "running" });
+ resumeSession({
+ sessionId: session.name,
+ sessionPatchRequest: { state: "running" },
+ });
setIsResuming(true);
}, [resumeSession, session.name]);
const { isWaiting: isWaitingForResumedSession } = useWaitForSessionStatusV2({
@@ -147,7 +150,10 @@ export default function ActiveSessionButton({
{ isSuccess: isSuccessHibernateSession, error: errorHibernateSession },
] = usePatchSessionMutation();
const onHibernateSession = useCallback(() => {
- hibernateSession({ session_id: session.name, state: "hibernated" });
+ hibernateSession({
+ sessionId: session.name,
+ sessionPatchRequest: { state: "hibernated" },
+ });
setIsHibernating(true);
}, [hibernateSession, session.name]);
const { isWaiting: isWaitingForHibernatedSession } =
@@ -177,7 +183,7 @@ export default function ActiveSessionButton({
// Optimistically show a session as "stopping" when triggered from the UI
const [isStopping, setIsStopping] = useState(false);
const onStopSession = useCallback(() => {
- stopSession({ session_id: session.name });
+ stopSession({ sessionId: session.name });
setIsStopping(true);
}, [session.name, stopSession]);
useEffect(() => {
@@ -204,8 +210,8 @@ export default function ActiveSessionButton({
(sessionClass: number, resumeSession: boolean) => {
const status = session.status.state;
const request = modifySession({
- session_id: session.name,
- resource_class_id: sessionClass,
+ sessionId: session.name,
+ sessionPatchRequest: { resource_class_id: sessionClass },
});
if (resumeSession && status === "hibernated") {
request.then(() => {
diff --git a/client/src/features/sessionsV2/sessionsV2.api.ts b/client/src/features/sessionsV2/sessionsV2.api.ts
index 1a64cb46e5..38dd53f676 100644
--- a/client/src/features/sessionsV2/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/sessionsV2.api.ts
@@ -224,9 +224,9 @@ export const {
useAddSessionLauncherMutation,
useUpdateSessionLauncherMutation,
useDeleteSessionLauncherMutation,
- useLaunchSessionMutation,
- usePatchSessionMutation,
- useStopSessionMutation,
+ // useLaunchSessionMutation,
+ // usePatchSessionMutation,
+ // useStopSessionMutation,
useGetLogsQuery,
useGetDockerImageQuery,
} = sessionsV2Api;
From 99423c88771404a0d2cb4da20497392b3c0cdb0b Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 15:49:49 +0100
Subject: [PATCH 04/11] more API updates
---
client/src/features/sessionsV2/SessionStartPage.tsx | 9 ++++++---
client/src/features/sessionsV2/api/sessionsV2.api.ts | 10 ++++++++++
client/src/features/sessionsV2/sessionsV2.api.ts | 4 ++--
client/src/utils/customHooks/UseGetSessionLogs.ts | 8 ++++----
4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/client/src/features/sessionsV2/SessionStartPage.tsx b/client/src/features/sessionsV2/SessionStartPage.tsx
index 78cb602d4f..f148691076 100644
--- a/client/src/features/sessionsV2/SessionStartPage.tsx
+++ b/client/src/features/sessionsV2/SessionStartPage.tsx
@@ -59,11 +59,14 @@ import DataConnectorSecretsModal from "./DataConnectorSecretsModal";
import SessionSecretsModal from "./SessionSecretsModal";
import { SelectResourceClassModal } from "./components/SessionModals/SelectResourceClass";
import {
- useGetDockerImageQuery,
+ // useGetDockerImageQuery,
useGetProjectSessionLaunchersQuery,
// useLaunchSessionMutation,
} from "./sessionsV2.api";
-import { usePostSessionsMutation as useLaunchSessionMutation } from "./api/sessionsV2.api";
+import {
+ usePostSessionsMutation as useLaunchSessionMutation,
+ useGetSessionsImagesQuery as useGetDockerImageQuery,
+} from "./api/sessionsV2.api";
import { SessionLauncher } from "./sessionsV2.types";
import startSessionOptionsV2Slice from "./startSessionOptionsV2.slice";
import {
@@ -456,7 +459,7 @@ function StartSessionFromLauncher({
isError: isErrorDockerImageStatus,
error: errorDockerImageStatus,
} = useGetDockerImageQuery(
- containerImage ? { image_url: containerImage } : skipToken
+ containerImage ? { imageUrl: containerImage } : skipToken
);
const needsCredentials = startSessionOptionsV2.cloudStorage?.some(
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api.ts b/client/src/features/sessionsV2/api/sessionsV2.api.ts
index b3cb527ed2..11d7bb3867 100644
--- a/client/src/features/sessionsV2/api/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/api/sessionsV2.api.ts
@@ -49,6 +49,14 @@ export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
deleteSessionsBySessionId: {
invalidatesTags: ["Session"],
},
+ getSessionsBySessionIdLogs: {
+ transformResponse: (result: unknown) => {
+ return result && typeof result == "string"
+ ? JSON.parse(result)
+ : result;
+ },
+ keepUnusedDataFor: 0,
+ },
},
});
@@ -75,6 +83,8 @@ export const {
usePostSessionsMutation,
usePatchSessionsBySessionIdMutation,
useDeleteSessionsBySessionIdMutation,
+ useGetSessionsBySessionIdLogsQuery,
+ useGetSessionsImagesQuery,
} = sessionsV2Api;
export type * from "./sessionsV2.generated-api";
diff --git a/client/src/features/sessionsV2/sessionsV2.api.ts b/client/src/features/sessionsV2/sessionsV2.api.ts
index 38dd53f676..b0357404a5 100644
--- a/client/src/features/sessionsV2/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/sessionsV2.api.ts
@@ -227,6 +227,6 @@ export const {
// useLaunchSessionMutation,
// usePatchSessionMutation,
// useStopSessionMutation,
- useGetLogsQuery,
- useGetDockerImageQuery,
+ // useGetLogsQuery,
+ // useGetDockerImageQuery,
} = sessionsV2Api;
diff --git a/client/src/utils/customHooks/UseGetSessionLogs.ts b/client/src/utils/customHooks/UseGetSessionLogs.ts
index f303d99b83..a55930aee0 100644
--- a/client/src/utils/customHooks/UseGetSessionLogs.ts
+++ b/client/src/utils/customHooks/UseGetSessionLogs.ts
@@ -17,7 +17,7 @@
*/
import { useEffect, useState } from "react";
import { useGetLogsQuery } from "../../features/session/sessions.api";
-import { useGetLogsQuery as useGetLogsQueryV2 } from "../../features/sessionsV2/sessionsV2.api";
+import { useGetSessionsBySessionIdLogsQuery as useGetLogsQueryV2 } from "../../features/sessionsV2/api/sessionsV2.api";
import { ILogs } from "../../components/Logs";
/**
@@ -57,7 +57,7 @@ export function useGetSessionLogsV2(
show: boolean | string
) {
const { data, isFetching, isLoading, error, refetch } = useGetLogsQueryV2(
- { session_id: serverName, max_lines: 250 },
+ { sessionId: serverName, maxLines: 250 },
{ skip: !serverName }
);
const [logs, setLogs] = useState(undefined);
@@ -71,8 +71,8 @@ export function useGetSessionLogsV2(
useEffect(() => {
setLogs({
- data,
- fetched: !isLoading && !error && data,
+ data: data ?? {},
+ fetched: !isLoading && !error && !!data,
fetching: isFetching,
show: show ? serverName : false,
});
From 027c571c885e8663d9af2cd80a24658e9a2133b4 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 16:06:26 +0100
Subject: [PATCH 05/11] wip: env/launchers API
---
.../api/sessionLaunchersV2.openapi.json | 946 ++++++++++++++++++
.../features/sessionsV2/api/sessionsV2.api.ts | 17 -
2 files changed, 946 insertions(+), 17 deletions(-)
create mode 100644 client/src/features/sessionsV2/api/sessionLaunchersV2.openapi.json
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.openapi.json b/client/src/features/sessionsV2/api/sessionLaunchersV2.openapi.json
new file mode 100644
index 0000000000..92a5728277
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.openapi.json
@@ -0,0 +1,946 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "title": "Renku Data Services API",
+ "description": "This service is the main backend for Renku. It provides information about users, projects,\ncloud storage, access to compute resources and many other things.\n",
+ "version": "v1"
+ },
+ "servers": [
+ {
+ "url": "/api/data"
+ }
+ ],
+ "paths": {
+ "/environments": {
+ "get": {
+ "summary": "Get all global environments",
+ "parameters": [
+ {
+ "in": "query",
+ "style": "form",
+ "explode": true,
+ "name": "get_environment_params",
+ "schema": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include_archived": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to return archived environments or not"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "List of global environments",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EnvironmentList"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["environments"]
+ },
+ "post": {
+ "summary": "Create a new global session environment",
+ "description": "Requires admin permissions",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EnvironmentPost"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The session environment was created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Environment"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["environments"]
+ }
+ },
+ "/environments/{environment_id}": {
+ "get": {
+ "summary": "Get a global session environment",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "environment_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The session environment",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Environment"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The session environment does not exist",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["environments"]
+ },
+ "patch": {
+ "summary": "Update specific fields of an existing global session environment",
+ "description": "Requires admin permissions",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "environment_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EnvironmentPatch"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The patched session environment",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Environment"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The session environment does not exist",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["environments"]
+ },
+ "delete": {
+ "summary": "Remove a global session environment",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "environment_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "The session environment was removed or did not exist in the first place"
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["environments"]
+ }
+ },
+ "/session_launchers": {
+ "get": {
+ "summary": "Get all user's session launchers",
+ "responses": {
+ "200": {
+ "description": "List of sessions launchers",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLaunchersList"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ },
+ "post": {
+ "summary": "Create a new session launcher",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLauncherPost"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The session launcher was created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLauncher"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ }
+ },
+ "/session_launchers/{launcher_id}": {
+ "get": {
+ "summary": "Get a session launcher",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "launcher_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The session launcher",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLauncher"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The session launcher does not exist",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ },
+ "patch": {
+ "summary": "Update specific fields of an existing session launcher",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "launcher_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLauncherPatch"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The patched session launcher",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLauncher"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The session launcher does not exist",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ },
+ "delete": {
+ "summary": "Remove a session launcher",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "launcher_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "The session was removed or did not exist in the first place"
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ }
+ },
+ "/projects/{project_id}/session_launchers": {
+ "get": {
+ "summary": "Get a project's session launchers",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "project_id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/Ulid"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "List of sessions launchers",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SessionLaunchersList"
+ }
+ }
+ }
+ },
+ "default": {
+ "$ref": "#/components/responses/Error"
+ }
+ },
+ "tags": ["session_launchers"]
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "EnvironmentList": {
+ "description": "A list of session environments",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Environment"
+ }
+ },
+ "Environment": {
+ "description": "A Renku 2.0 session environment",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "creation_date": {
+ "$ref": "#/components/schemas/CreationDate"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "container_image": {
+ "$ref": "#/components/schemas/ContainerImage"
+ },
+ "default_url": {
+ "$ref": "#/components/schemas/DefaultUrl"
+ },
+ "uid": {
+ "$ref": "#/components/schemas/EnvironmentUid"
+ },
+ "gid": {
+ "$ref": "#/components/schemas/EnvironmentGid"
+ },
+ "working_directory": {
+ "$ref": "#/components/schemas/EnvironmentWorkingDirectory"
+ },
+ "mount_directory": {
+ "$ref": "#/components/schemas/EnvironmentMountDirectory"
+ },
+ "port": {
+ "$ref": "#/components/schemas/EnvironmentPort"
+ },
+ "command": {
+ "$ref": "#/components/schemas/EnvironmentCommand"
+ },
+ "args": {
+ "$ref": "#/components/schemas/EnvironmentArgs"
+ },
+ "is_archived": {
+ "$ref": "#/components/schemas/IsArchived"
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "creation_date",
+ "container_image",
+ "port",
+ "uid",
+ "gid",
+ "default_url"
+ ],
+ "example": {
+ "id": "01AN4Z79ZS6XX96588FDX0H099",
+ "name": "JupyterLab environment",
+ "creation_date": "2023-11-01T17:32:28Z",
+ "description": "JupyterLab session environment",
+ "container_image": "renku-jupyter:latest",
+ "default_url": "/lab",
+ "port": 8080,
+ "working_directory": "/home/jovyan/work",
+ "mount_directory": "/home/jovyan/work",
+ "uid": 1000,
+ "gid": 1000,
+ "is_archive": false
+ }
+ },
+ "EnvironmentGetInLauncher": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Environment"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "environment_kind": {
+ "$ref": "#/components/schemas/EnvironmentKind"
+ }
+ },
+ "required": ["environment_kind"],
+ "example": {
+ "environment_kind": "global_environment"
+ }
+ }
+ ]
+ },
+ "EnvironmentPostInLauncher": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentPost"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "environment_kind": {
+ "$ref": "#/components/schemas/EnvironmentKind"
+ }
+ },
+ "required": ["environment_kind"],
+ "example": {
+ "environment_kind": "global_environment"
+ }
+ }
+ ]
+ },
+ "EnvironmentPost": {
+ "description": "Data required to create a session environment",
+ "type": "object",
+ "properties": {
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "container_image": {
+ "$ref": "#/components/schemas/ContainerImage"
+ },
+ "default_url": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/DefaultUrl"
+ },
+ {
+ "default": "/lab"
+ }
+ ],
+ "default": "/lab"
+ },
+ "uid": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentUid"
+ },
+ {
+ "default": 1000
+ }
+ ],
+ "default": 1000
+ },
+ "gid": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentGid"
+ },
+ {
+ "default": 1000
+ }
+ ],
+ "default": 1000
+ },
+ "working_directory": {
+ "$ref": "#/components/schemas/EnvironmentWorkingDirectory"
+ },
+ "mount_directory": {
+ "$ref": "#/components/schemas/EnvironmentMountDirectory"
+ },
+ "port": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentPort"
+ },
+ {
+ "default": 8080
+ }
+ ],
+ "default": 8080
+ },
+ "command": {
+ "$ref": "#/components/schemas/EnvironmentCommand"
+ },
+ "args": {
+ "$ref": "#/components/schemas/EnvironmentArgs"
+ },
+ "is_archived": {
+ "$ref": "#/components/schemas/IsArchived",
+ "default": false
+ }
+ },
+ "required": ["name", "container_image"]
+ },
+ "EnvironmentPatchInLauncher": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentPatch"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "environment_kind": {
+ "$ref": "#/components/schemas/EnvironmentKind"
+ }
+ }
+ }
+ ]
+ },
+ "EnvironmentPatch": {
+ "type": "object",
+ "description": "Update a session environment",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "container_image": {
+ "$ref": "#/components/schemas/ContainerImage"
+ },
+ "default_url": {
+ "$ref": "#/components/schemas/DefaultUrl"
+ },
+ "uid": {
+ "$ref": "#/components/schemas/EnvironmentUid"
+ },
+ "gid": {
+ "$ref": "#/components/schemas/EnvironmentGid"
+ },
+ "working_directory": {
+ "$ref": "#/components/schemas/EnvironmentWorkingDirectoryPatch"
+ },
+ "mount_directory": {
+ "$ref": "#/components/schemas/EnvironmentMountDirectoryPatch"
+ },
+ "port": {
+ "$ref": "#/components/schemas/EnvironmentPort"
+ },
+ "command": {
+ "$ref": "#/components/schemas/EnvironmentCommand"
+ },
+ "args": {
+ "$ref": "#/components/schemas/EnvironmentArgs"
+ },
+ "is_archived": {
+ "$ref": "#/components/schemas/IsArchived"
+ }
+ }
+ },
+ "SessionLaunchersList": {
+ "description": "A list of Renku session launchers",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SessionLauncher"
+ },
+ "minItems": 0
+ },
+ "SessionLauncher": {
+ "description": "A Renku 2.0 session definition and metadata",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "project_id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "creation_date": {
+ "$ref": "#/components/schemas/CreationDate"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "environment": {
+ "$ref": "#/components/schemas/EnvironmentGetInLauncher"
+ },
+ "resource_class_id": {
+ "$ref": "#/components/schemas/ResourceClassId"
+ },
+ "disk_storage": {
+ "$ref": "#/components/schemas/DiskStorage"
+ }
+ },
+ "required": [
+ "id",
+ "project_id",
+ "name",
+ "creation_date",
+ "environment",
+ "resource_class_id"
+ ]
+ },
+ "SessionLauncherPost": {
+ "description": "Data required to create a session launcher",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "project_id": {
+ "$ref": "#/components/schemas/Ulid"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "resource_class_id": {
+ "$ref": "#/components/schemas/ResourceClassId"
+ },
+ "disk_storage": {
+ "$ref": "#/components/schemas/DiskStorage"
+ },
+ "environment": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentPostInLauncher"
+ },
+ {
+ "$ref": "#/components/schemas/EnvironmentIdOnlyPost"
+ }
+ ]
+ }
+ },
+ "required": ["name", "project_id", "environment"],
+ "example": {
+ "project_id": "01AN4Z79ZS5XN0F25N3DB94T4R",
+ "name": "Renku R Session",
+ "environment": {
+ "id": "01AN4Z79ZS6XX96588FDX0H099"
+ }
+ }
+ },
+ "SessionLauncherPatch": {
+ "type": "object",
+ "description": "Update a session launcher",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "$ref": "#/components/schemas/SessionName"
+ },
+ "description": {
+ "$ref": "#/components/schemas/Description"
+ },
+ "resource_class_id": {
+ "$ref": "#/components/schemas/ResourceClassId"
+ },
+ "disk_storage": {
+ "$ref": "#/components/schemas/DiskStoragePatch"
+ },
+ "environment": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentPatchInLauncher"
+ },
+ {
+ "$ref": "#/components/schemas/EnvironmentIdOnlyPatch"
+ }
+ ]
+ }
+ }
+ },
+ "Ulid": {
+ "description": "ULID identifier",
+ "type": "string",
+ "minLength": 26,
+ "maxLength": 26,
+ "pattern": "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
+ },
+ "SessionName": {
+ "description": "Renku session name",
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 99,
+ "example": "My Renku Session :)"
+ },
+ "EnvironmentIdOnlyPatch": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "#/components/schemas/EnvironmentId"
+ }
+ }
+ },
+ "EnvironmentIdOnlyPost": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "#/components/schemas/EnvironmentId"
+ }
+ },
+ "required": ["id"]
+ },
+ "EnvironmentKind": {
+ "description": "Kind of environment to use",
+ "type": "string",
+ "enum": ["GLOBAL", "CUSTOM"],
+ "example": "CUSTOM"
+ },
+ "EnvironmentId": {
+ "description": "Id of the environment to use",
+ "type": "string",
+ "minLength": 1,
+ "example": "01AN4Z79ZS6XX96588FDX0H099"
+ },
+ "CreationDate": {
+ "description": "The date and time the resource was created (in UTC and ISO-8601 format)",
+ "type": "string",
+ "format": "date-time",
+ "example": "2023-11-01T17:32:28Z"
+ },
+ "Description": {
+ "description": "A description for the resource",
+ "type": "string",
+ "maxLength": 500
+ },
+ "ContainerImage": {
+ "description": "A container image",
+ "type": "string",
+ "maxLength": 500,
+ "pattern": "^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$",
+ "example": "renku/renkulab-py:3.10-0.18.1"
+ },
+ "DefaultUrl": {
+ "description": "The default path to open in a session",
+ "type": "string",
+ "maxLength": 200,
+ "example": "/lab"
+ },
+ "ResourceClassId": {
+ "description": "The identifier of a resource class",
+ "type": "integer",
+ "default": null,
+ "nullable": true
+ },
+ "DiskStorage": {
+ "description": "The size of disk storage for the session, in gigabytes",
+ "type": "integer",
+ "minimum": 1,
+ "example": 8
+ },
+ "DiskStoragePatch": {
+ "type": "integer",
+ "minimum": 1,
+ "nullable": true
+ },
+ "EnvironmentPort": {
+ "type": "integer",
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "exclusiveMaximum": true,
+ "maximum": 65400,
+ "description": "The TCP port (on any container in the session) where user requests will be routed to from the ingress"
+ },
+ "EnvironmentUid": {
+ "type": "integer",
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "maximum": 65535,
+ "description": "The user ID used to run the session"
+ },
+ "EnvironmentGid": {
+ "type": "integer",
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "maximum": 65535,
+ "description": "The group ID used to run the session"
+ },
+ "EnvironmentWorkingDirectory": {
+ "type": "string",
+ "description": "The location where the session will start, if left unset it will default to the session image working directory.",
+ "minLength": 1,
+ "example": "/home/jovyan/work"
+ },
+ "EnvironmentWorkingDirectoryPatch": {
+ "type": "string",
+ "example": "/home/jovyan/work"
+ },
+ "EnvironmentMountDirectory": {
+ "type": "string",
+ "description": "The location where the persistent storage for the session will be mounted, usually it should be identical to or a parent of the working directory, if left unset will default to the working directory.",
+ "minLength": 1,
+ "example": "/home/jovyan/work"
+ },
+ "EnvironmentMountDirectoryPatch": {
+ "type": "string",
+ "example": "/home/jovyan/work"
+ },
+ "EnvironmentCommand": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The command that will be run i.e. will overwrite the image Dockerfile ENTRYPOINT, equivalent to command in Kubernetes",
+ "minLength": 1
+ },
+ "EnvironmentArgs": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The arguments that will follow the command, i.e. will overwrite the image Dockerfile CMD, equivalent to args in Kubernetes",
+ "minLength": 1
+ },
+ "IsArchived": {
+ "type": "boolean",
+ "description": "Whether this environment is archived and not for use in new projects or not",
+ "default": false
+ },
+ "ErrorResponse": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "integer",
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "example": 1404
+ },
+ "detail": {
+ "type": "string",
+ "example": "A more detailed optional message showing what the problem was"
+ },
+ "message": {
+ "type": "string",
+ "example": "Something went wrong - please try again later"
+ }
+ },
+ "required": ["code", "message"]
+ }
+ },
+ "required": ["error"]
+ }
+ },
+ "responses": {
+ "Error": {
+ "description": "The schema for all 4xx and 5xx responses",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api.ts b/client/src/features/sessionsV2/api/sessionsV2.api.ts
index 11d7bb3867..f128f14848 100644
--- a/client/src/features/sessionsV2/api/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/api/sessionsV2.api.ts
@@ -60,23 +60,6 @@ export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
},
});
-// useGetNotebooksImagesQuery,
-// useGetNotebooksLogsByServerNameQuery,
-// useGetNotebooksServerOptionsQuery,
-// usePostNotebooksServersMutation,
-// useGetNotebooksServersQuery,
-// useDeleteNotebooksServersByServerNameMutation,
-// useGetNotebooksServersByServerNameQuery,
-// usePatchNotebooksServersByServerNameMutation,
-// "sessions"
-// usePostSessionsMutation,
-// useGetSessionsQuery,
-// useGetSessionsBySessionIdQuery,
-// useDeleteSessionsBySessionIdMutation,
-// usePatchSessionsBySessionIdMutation,
-// useGetSessionsBySessionIdLogsQuery,
-// useGetSessionsImagesQuery,
-
export const {
// "sessions" hooks
useGetSessionsQuery,
From b3511067a79f86fb6245b52001ff92aeae08468e Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Tue, 28 Jan 2025 16:12:05 +0100
Subject: [PATCH 06/11] wip: launchers api
---
client/package.json | 3 +-
.../api/sessionLaunchersV2.api-config.ts | 32 ++
.../api/sessionLaunchersV2.empty-api.ts | 26 ++
.../api/sessionLaunchersV2.generated-api.ts | 287 ++++++++++++++++++
4 files changed, 347 insertions(+), 1 deletion(-)
create mode 100644 client/src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts
create mode 100644 client/src/features/sessionsV2/api/sessionLaunchersV2.empty-api.ts
create mode 100644 client/src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts
diff --git a/client/package.json b/client/package.json
index 36cc7a736a..7e5a6a6a70 100644
--- a/client/package.json
+++ b/client/package.json
@@ -30,7 +30,8 @@
"generate-api:platform": "rtk-query-codegen-openapi src/features/platform/api/platform.api-config.ts",
"generate-api:searchV2": "rtk-query-codegen-openapi src/features/searchV2/api/searchV2.api-config.ts",
"generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts",
- "generate-api:sessionsV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionsV2.api-config.ts"
+ "generate-api:sessionsV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionsV2.api-config.ts",
+ "generate-api:sessionLaunchersV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts"
},
"type": "module",
"dependencies": {
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts b/client/src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts
new file mode 100644
index 0000000000..d765cec7fb
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts
@@ -0,0 +1,32 @@
+/*!
+ * Copyright 2025 - Swiss Data Science Center (SDSC)
+ * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
+ * Eidgenössische Technische Hochschule Zürich (ETHZ).
+ *
+ * Licensed 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.
+ */
+
+// Run `npm run generate-api:sessionLaunchersV2` to generate the API
+import type { ConfigFile } from "@rtk-query/codegen-openapi";
+import path from "path";
+
+const config: ConfigFile = {
+ apiFile: "./sessionLaunchersV2.empty-api.ts",
+ apiImport: "sessionLaunchersV2EmptyApi",
+ outputFile: "./sessionLaunchersV2.generated-api.ts",
+ exportName: "sessionLaunchersV2GeneratedApi",
+ hooks: true,
+ schemaFile: path.join(__dirname, "sessionLaunchersV2.openapi.json"),
+};
+
+export default config;
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.empty-api.ts b/client/src/features/sessionsV2/api/sessionLaunchersV2.empty-api.ts
new file mode 100644
index 0000000000..fe7921893e
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.empty-api.ts
@@ -0,0 +1,26 @@
+/*!
+ * Copyright 2025 - Swiss Data Science Center (SDSC)
+ * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
+ * Eidgenössische Technische Hochschule Zürich (ETHZ).
+ *
+ * Licensed 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.
+ */
+
+import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
+
+// initialize an empty api service that we'll inject endpoints into later as needed
+export const sessionLaunchersV2EmptyApi = createApi({
+ baseQuery: fetchBaseQuery({ baseUrl: "/api/data" }),
+ endpoints: () => ({}),
+ reducerPath: "sessionLaunchersV2Api",
+});
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts b/client/src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts
new file mode 100644
index 0000000000..10254532f8
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts
@@ -0,0 +1,287 @@
+import { sessionLaunchersV2EmptyApi as api } from "./sessionLaunchersV2.empty-api";
+const injectedRtkApi = api.injectEndpoints({
+ endpoints: (build) => ({
+ getEnvironments: build.query<
+ GetEnvironmentsApiResponse,
+ GetEnvironmentsApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/environments`,
+ params: { get_environment_params: queryArg.getEnvironmentParams },
+ }),
+ }),
+ postEnvironments: build.mutation<
+ PostEnvironmentsApiResponse,
+ PostEnvironmentsApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/environments`,
+ method: "POST",
+ body: queryArg.environmentPost,
+ }),
+ }),
+ getEnvironmentsByEnvironmentId: build.query<
+ GetEnvironmentsByEnvironmentIdApiResponse,
+ GetEnvironmentsByEnvironmentIdApiArg
+ >({
+ query: (queryArg) => ({ url: `/environments/${queryArg.environmentId}` }),
+ }),
+ patchEnvironmentsByEnvironmentId: build.mutation<
+ PatchEnvironmentsByEnvironmentIdApiResponse,
+ PatchEnvironmentsByEnvironmentIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/environments/${queryArg.environmentId}`,
+ method: "PATCH",
+ body: queryArg.environmentPatch,
+ }),
+ }),
+ deleteEnvironmentsByEnvironmentId: build.mutation<
+ DeleteEnvironmentsByEnvironmentIdApiResponse,
+ DeleteEnvironmentsByEnvironmentIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/environments/${queryArg.environmentId}`,
+ method: "DELETE",
+ }),
+ }),
+ getSessionLaunchers: build.query<
+ GetSessionLaunchersApiResponse,
+ GetSessionLaunchersApiArg
+ >({
+ query: () => ({ url: `/session_launchers` }),
+ }),
+ postSessionLaunchers: build.mutation<
+ PostSessionLaunchersApiResponse,
+ PostSessionLaunchersApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/session_launchers`,
+ method: "POST",
+ body: queryArg.sessionLauncherPost,
+ }),
+ }),
+ getSessionLaunchersByLauncherId: build.query<
+ GetSessionLaunchersByLauncherIdApiResponse,
+ GetSessionLaunchersByLauncherIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/session_launchers/${queryArg.launcherId}`,
+ }),
+ }),
+ patchSessionLaunchersByLauncherId: build.mutation<
+ PatchSessionLaunchersByLauncherIdApiResponse,
+ PatchSessionLaunchersByLauncherIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/session_launchers/${queryArg.launcherId}`,
+ method: "PATCH",
+ body: queryArg.sessionLauncherPatch,
+ }),
+ }),
+ deleteSessionLaunchersByLauncherId: build.mutation<
+ DeleteSessionLaunchersByLauncherIdApiResponse,
+ DeleteSessionLaunchersByLauncherIdApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/session_launchers/${queryArg.launcherId}`,
+ method: "DELETE",
+ }),
+ }),
+ getProjectsByProjectIdSessionLaunchers: build.query<
+ GetProjectsByProjectIdSessionLaunchersApiResponse,
+ GetProjectsByProjectIdSessionLaunchersApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/projects/${queryArg.projectId}/session_launchers`,
+ }),
+ }),
+ }),
+ overrideExisting: false,
+});
+export { injectedRtkApi as sessionLaunchersV2GeneratedApi };
+export type GetEnvironmentsApiResponse =
+ /** status 200 List of global environments */ EnvironmentList;
+export type GetEnvironmentsApiArg = {
+ getEnvironmentParams?: {
+ /** Whether to return archived environments or not */
+ include_archived?: boolean;
+ };
+};
+export type PostEnvironmentsApiResponse =
+ /** status 201 The session environment was created */ Environment;
+export type PostEnvironmentsApiArg = {
+ environmentPost: EnvironmentPost;
+};
+export type GetEnvironmentsByEnvironmentIdApiResponse =
+ /** status 200 The session environment */ Environment;
+export type GetEnvironmentsByEnvironmentIdApiArg = {
+ environmentId: Ulid;
+};
+export type PatchEnvironmentsByEnvironmentIdApiResponse =
+ /** status 200 The patched session environment */ Environment;
+export type PatchEnvironmentsByEnvironmentIdApiArg = {
+ environmentId: Ulid;
+ environmentPatch: EnvironmentPatch;
+};
+export type DeleteEnvironmentsByEnvironmentIdApiResponse =
+ /** status 204 The session environment was removed or did not exist in the first place */ void;
+export type DeleteEnvironmentsByEnvironmentIdApiArg = {
+ environmentId: Ulid;
+};
+export type GetSessionLaunchersApiResponse =
+ /** status 200 List of sessions launchers */ SessionLaunchersList;
+export type GetSessionLaunchersApiArg = void;
+export type PostSessionLaunchersApiResponse =
+ /** status 201 The session launcher was created */ SessionLauncher;
+export type PostSessionLaunchersApiArg = {
+ sessionLauncherPost: SessionLauncherPost;
+};
+export type GetSessionLaunchersByLauncherIdApiResponse =
+ /** status 200 The session launcher */ SessionLauncher;
+export type GetSessionLaunchersByLauncherIdApiArg = {
+ launcherId: Ulid;
+};
+export type PatchSessionLaunchersByLauncherIdApiResponse =
+ /** status 200 The patched session launcher */ SessionLauncher;
+export type PatchSessionLaunchersByLauncherIdApiArg = {
+ launcherId: Ulid;
+ sessionLauncherPatch: SessionLauncherPatch;
+};
+export type DeleteSessionLaunchersByLauncherIdApiResponse =
+ /** status 204 The session was removed or did not exist in the first place */ void;
+export type DeleteSessionLaunchersByLauncherIdApiArg = {
+ launcherId: Ulid;
+};
+export type GetProjectsByProjectIdSessionLaunchersApiResponse =
+ /** status 200 List of sessions launchers */ SessionLaunchersList;
+export type GetProjectsByProjectIdSessionLaunchersApiArg = {
+ projectId: Ulid;
+};
+export type Ulid = string;
+export type SessionName = string;
+export type CreationDate = string;
+export type Description = string;
+export type ContainerImage = string;
+export type DefaultUrl = string;
+export type EnvironmentUid = number;
+export type EnvironmentGid = number;
+export type EnvironmentWorkingDirectory = string;
+export type EnvironmentMountDirectory = string;
+export type EnvironmentPort = number;
+export type EnvironmentCommand = string[];
+export type EnvironmentArgs = string[];
+export type IsArchived = boolean;
+export type Environment = {
+ id: Ulid;
+ name: SessionName;
+ creation_date: CreationDate;
+ description?: Description;
+ container_image: ContainerImage;
+ default_url: DefaultUrl;
+ uid: EnvironmentUid;
+ gid: EnvironmentGid;
+ working_directory?: EnvironmentWorkingDirectory;
+ mount_directory?: EnvironmentMountDirectory;
+ port: EnvironmentPort;
+ command?: EnvironmentCommand;
+ args?: EnvironmentArgs;
+ is_archived?: IsArchived;
+};
+export type EnvironmentList = Environment[];
+export type ErrorResponse = {
+ error: {
+ code: number;
+ detail?: string;
+ message: string;
+ };
+};
+export type EnvironmentPost = {
+ name: SessionName;
+ description?: Description;
+ container_image: ContainerImage;
+ default_url?: DefaultUrl & any;
+ uid?: EnvironmentUid & any;
+ gid?: EnvironmentGid & any;
+ working_directory?: EnvironmentWorkingDirectory;
+ mount_directory?: EnvironmentMountDirectory;
+ port?: EnvironmentPort & any;
+ command?: EnvironmentCommand;
+ args?: EnvironmentArgs;
+ is_archived?: IsArchived;
+};
+export type EnvironmentWorkingDirectoryPatch = string;
+export type EnvironmentMountDirectoryPatch = string;
+export type EnvironmentPatch = {
+ name?: SessionName;
+ description?: Description;
+ container_image?: ContainerImage;
+ default_url?: DefaultUrl;
+ uid?: EnvironmentUid;
+ gid?: EnvironmentGid;
+ working_directory?: EnvironmentWorkingDirectoryPatch;
+ mount_directory?: EnvironmentMountDirectoryPatch;
+ port?: EnvironmentPort;
+ command?: EnvironmentCommand;
+ args?: EnvironmentArgs;
+ is_archived?: IsArchived;
+};
+export type EnvironmentKind = "GLOBAL" | "CUSTOM";
+export type EnvironmentGetInLauncher = Environment & {
+ environment_kind: EnvironmentKind;
+};
+export type ResourceClassId = number | null;
+export type DiskStorage = number;
+export type SessionLauncher = {
+ id: Ulid;
+ project_id: Ulid;
+ name: SessionName;
+ creation_date: CreationDate;
+ description?: Description;
+ environment: EnvironmentGetInLauncher;
+ resource_class_id: ResourceClassId;
+ disk_storage?: DiskStorage;
+};
+export type SessionLaunchersList = SessionLauncher[];
+export type EnvironmentPostInLauncher = EnvironmentPost & {
+ environment_kind: EnvironmentKind;
+};
+export type EnvironmentId = string;
+export type EnvironmentIdOnlyPost = {
+ id: EnvironmentId;
+};
+export type SessionLauncherPost = {
+ name: SessionName;
+ project_id: Ulid;
+ description?: Description;
+ resource_class_id?: ResourceClassId;
+ disk_storage?: DiskStorage;
+ environment: EnvironmentPostInLauncher | EnvironmentIdOnlyPost;
+};
+export type DiskStoragePatch = number | null;
+export type EnvironmentPatchInLauncher = EnvironmentPatch & {
+ environment_kind?: EnvironmentKind;
+};
+export type EnvironmentIdOnlyPatch = {
+ id?: EnvironmentId;
+};
+export type SessionLauncherPatch = {
+ name?: SessionName;
+ description?: Description;
+ resource_class_id?: ResourceClassId;
+ disk_storage?: DiskStoragePatch;
+ environment?: EnvironmentPatchInLauncher | EnvironmentIdOnlyPatch;
+};
+export const {
+ useGetEnvironmentsQuery,
+ usePostEnvironmentsMutation,
+ useGetEnvironmentsByEnvironmentIdQuery,
+ usePatchEnvironmentsByEnvironmentIdMutation,
+ useDeleteEnvironmentsByEnvironmentIdMutation,
+ useGetSessionLaunchersQuery,
+ usePostSessionLaunchersMutation,
+ useGetSessionLaunchersByLauncherIdQuery,
+ usePatchSessionLaunchersByLauncherIdMutation,
+ useDeleteSessionLaunchersByLauncherIdMutation,
+ useGetProjectsByProjectIdSessionLaunchersQuery,
+} = injectedRtkApi;
From b665dbf49cec616f0abb2c8b7031f5af116b55e4 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Wed, 29 Jan 2025 11:08:48 +0100
Subject: [PATCH 07/11] more api refactor
---
client/.eslintignore | 1 +
.../dashboardV2/DashboardV2Sessions.tsx | 4 +-
.../sessionsV2/DeleteSessionLauncherModal.tsx | 2 +-
.../SessionList/SessionItemDisplay.tsx | 1 -
.../SessionShowPage/ShowSessionPage.tsx | 5 +-
.../features/sessionsV2/SessionStartPage.tsx | 6 +-
client/src/features/sessionsV2/SessionsV2.tsx | 5 +-
.../sessionsV2/api/sessionLaunchersV2.api.ts | 77 ++++++
.../features/sessionsV2/api/sessionsV2.api.ts | 13 +-
.../SessionForm/EditLauncherFormContent.tsx | 5 +-
.../SessionForm/GlobalEnvironmentFields.tsx | 5 +-
.../SessionModals/ModifyResourcesLauncher.tsx | 8 +-
.../SessionModals/NewSessionLauncherModal.tsx | 22 +-
.../SessionModals/SelectResourceClass.tsx | 2 +-
.../UpdateSessionLauncherModal.tsx | 18 +-
.../src/features/sessionsV2/sessionsV2.api.ts | 232 ------------------
.../features/sessionsV2/sessionsV2.types.ts | 4 +-
client/src/utils/helpers/EnhancedState.ts | 5 +-
.../handlers/sessionStatusHandlerV2.ts | 2 +-
19 files changed, 139 insertions(+), 278 deletions(-)
create mode 100644 client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
delete mode 100644 client/src/features/sessionsV2/sessionsV2.api.ts
diff --git a/client/.eslintignore b/client/.eslintignore
index 6eb2d9a87f..865ee4b376 100644
--- a/client/.eslintignore
+++ b/client/.eslintignore
@@ -6,3 +6,4 @@ src/features/projectsV2/api/storagesV2.api.ts
src/features/dataConnectorsV2/api/data-connectors.api.ts
src/features/usersV2/api/users.generated-api.ts
src/features/sessionsV2/api/sessionsV2.generated-api.ts
+src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts
diff --git a/client/src/features/dashboardV2/DashboardV2Sessions.tsx b/client/src/features/dashboardV2/DashboardV2Sessions.tsx
index 53d1dc48f7..7a948d7572 100644
--- a/client/src/features/dashboardV2/DashboardV2Sessions.tsx
+++ b/client/src/features/dashboardV2/DashboardV2Sessions.tsx
@@ -25,7 +25,7 @@ import { Col, ListGroup, Row } from "reactstrap";
import { Loader } from "../../components/Loader";
import EnvironmentLogsV2 from "../../components/LogsV2";
import { RtkErrorAlert } from "../../components/errors/RtkErrorAlert";
-import { useGetProjectSessionLauncherQuery } from "../../features/sessionsV2/sessionsV2.api";
+import { useGetSessionLaunchersByLauncherIdQuery as useGetProjectSessionLauncherQuery } from "../sessionsV2/api/sessionLaunchersV2.generated-api";
import { ABSOLUTE_ROUTES } from "../../routing/routes.constants";
import useAppSelector from "../../utils/customHooks/useAppSelector.hook";
import { useGetProjectsByProjectIdQuery } from "../projectsV2/api/projectV2.enhanced-api";
@@ -122,7 +122,7 @@ function DashboardSession({ session }: DashboardSessionProps) {
projectId ? { projectId } : skipToken
);
const { data: launcher } = useGetProjectSessionLauncherQuery(
- launcherId ? { id: launcherId } : skipToken
+ launcherId ? { launcherId } : skipToken
);
const projectUrl = project
diff --git a/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx b/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
index 544dc206c5..79fd2b774f 100644
--- a/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
@@ -22,7 +22,7 @@ import { Trash, XLg } from "react-bootstrap-icons";
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "reactstrap";
import { RtkErrorAlert } from "../../components/errors/RtkErrorAlert";
-import { useDeleteSessionLauncherMutation } from "./sessionsV2.api";
+import { useDeleteSessionLaunchersByLauncherIdMutation as useDeleteSessionLauncherMutation } from "./api/sessionLaunchersV2.api";
import { SessionLauncher } from "./sessionsV2.types";
import { WarnAlert } from "../../components/Alert";
diff --git a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
index 31a8a4282d..9cc167469c 100644
--- a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
+++ b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
@@ -20,7 +20,6 @@ import { useCallback, useMemo } from "react";
import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
import { Project } from "../../projectsV2/api/projectV2.api";
-// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../api/sessionsV2.api";
import { SessionView } from "../SessionView/SessionView";
import { SessionLauncher } from "../sessionsV2.types";
diff --git a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
index 29b9d2a822..3247d703ee 100644
--- a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
+++ b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
@@ -61,10 +61,7 @@ import styles from "../../session/components/ShowSession.module.scss";
import { StartSessionProgressBarV2 } from "../../session/components/StartSessionProgressBar";
import PauseOrDeleteSessionModal from "../PauseOrDeleteSessionModal";
import { getSessionFavicon } from "../session.utils";
-import {
- useGetProjectSessionLaunchersQuery,
- // useGetSessionsQuery,
-} from "../sessionsV2.api";
+import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "../api/sessionLaunchersV2.api";
import { useGetSessionsQuery } from "../api/sessionsV2.api";
import { SessionV2 } from "../sessionsV2.types";
import SessionIframe from "./SessionIframe";
diff --git a/client/src/features/sessionsV2/SessionStartPage.tsx b/client/src/features/sessionsV2/SessionStartPage.tsx
index f148691076..cf1875915d 100644
--- a/client/src/features/sessionsV2/SessionStartPage.tsx
+++ b/client/src/features/sessionsV2/SessionStartPage.tsx
@@ -58,11 +58,7 @@ import { storageSecretNameToFieldName } from "../secretsV2/secrets.utils";
import DataConnectorSecretsModal from "./DataConnectorSecretsModal";
import SessionSecretsModal from "./SessionSecretsModal";
import { SelectResourceClassModal } from "./components/SessionModals/SelectResourceClass";
-import {
- // useGetDockerImageQuery,
- useGetProjectSessionLaunchersQuery,
- // useLaunchSessionMutation,
-} from "./sessionsV2.api";
+import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "./api/sessionLaunchersV2.api";
import {
usePostSessionsMutation as useLaunchSessionMutation,
useGetSessionsImagesQuery as useGetDockerImageQuery,
diff --git a/client/src/features/sessionsV2/SessionsV2.tsx b/client/src/features/sessionsV2/SessionsV2.tsx
index 200df402f7..bea45492e9 100644
--- a/client/src/features/sessionsV2/SessionsV2.tsx
+++ b/client/src/features/sessionsV2/SessionsV2.tsx
@@ -44,10 +44,7 @@ import SessionItem from "./SessionList/SessionItem";
import { SessionItemDisplay } from "./SessionList/SessionItemDisplay";
import { SessionView } from "./SessionView/SessionView";
import UpdateSessionLauncherModal from "./components/SessionModals/UpdateSessionLauncherModal";
-import {
- useGetProjectSessionLaunchersQuery,
- // useGetSessionsQuery as useGetSessionsQueryV2,
-} from "./sessionsV2.api";
+import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "./api/sessionLaunchersV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "./api/sessionsV2.api";
import { SessionLauncher, SessionV2 } from "./sessionsV2.types";
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts b/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
new file mode 100644
index 0000000000..ab4f1240fc
--- /dev/null
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
@@ -0,0 +1,77 @@
+/*!
+ * Copyright 2025 - Swiss Data Science Center (SDSC)
+ * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
+ * Eidgenössische Technische Hochschule Zürich (ETHZ).
+ *
+ * Licensed 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.
+ */
+
+import { sessionLaunchersV2GeneratedApi } from "./sessionLaunchersV2.generated-api";
+
+// Adds tag handling for cache management
+export const sessionLaunchersV2Api =
+ sessionLaunchersV2GeneratedApi.enhanceEndpoints({
+ addTagTypes: ["Environment", "Launcher"],
+ endpoints: {
+ getEnvironments: {
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map(({ id }) => ({
+ id,
+ type: "Environment" as const,
+ })),
+ "Environment",
+ ]
+ : ["Environment"],
+ },
+ getSessionLaunchersByLauncherId: {
+ providesTags: (result) =>
+ result
+ ? [{ id: result.id, type: "Launcher" }, "Launcher"]
+ : ["Launcher"],
+ },
+ postSessionLaunchers: {
+ invalidatesTags: ["Launcher"],
+ },
+ patchSessionLaunchersByLauncherId: {
+ invalidatesTags: (result) =>
+ result ? [{ id: result.id, type: "Launcher" }] : ["Launcher"],
+ },
+ deleteSessionLaunchersByLauncherId: {
+ invalidatesTags: ["Launcher"],
+ },
+ getProjectsByProjectIdSessionLaunchers: {
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map(({ id }) => ({ id, type: "Launcher" as const })),
+ "Launcher",
+ ]
+ : ["Launcher"],
+ },
+ },
+ });
+
+export const {
+ // "environments" hooks
+ useGetEnvironmentsQuery,
+ // "launchers" hooks
+ useGetSessionLaunchersByLauncherIdQuery,
+ usePostSessionLaunchersMutation,
+ usePatchSessionLaunchersByLauncherIdMutation,
+ useDeleteSessionLaunchersByLauncherIdMutation,
+ useGetProjectsByProjectIdSessionLaunchersQuery,
+} = sessionLaunchersV2Api;
+
+export type * from "./sessionLaunchersV2.generated-api";
diff --git a/client/src/features/sessionsV2/api/sessionsV2.api.ts b/client/src/features/sessionsV2/api/sessionsV2.api.ts
index f128f14848..bdcfd99f65 100644
--- a/client/src/features/sessionsV2/api/sessionsV2.api.ts
+++ b/client/src/features/sessionsV2/api/sessionsV2.api.ts
@@ -18,7 +18,8 @@
import { sessionsV2GeneratedApi } from "./sessionsV2.generated-api";
-export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
+// Adds tag handling for cache management
+const withTagHandling = sessionsV2GeneratedApi.enhanceEndpoints({
addTagTypes: ["Session"],
endpoints: {
getSessions: {
@@ -60,6 +61,16 @@ export const sessionsV2Api = sessionsV2GeneratedApi.enhanceEndpoints({
},
});
+// Adds tag invalidation endpoints
+export const sessionsV2Api = withTagHandling.injectEndpoints({
+ endpoints: (build) => ({
+ invalidateSessions: build.mutation({
+ queryFn: () => ({ data: null }),
+ invalidatesTags: ["Session"],
+ }),
+ }),
+});
+
export const {
// "sessions" hooks
useGetSessionsQuery,
diff --git a/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx b/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
index e7a1529689..8c6ff9eafc 100644
--- a/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
+++ b/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
@@ -33,7 +33,8 @@ import ChevronFlippedIcon from "../../../../components/icons/ChevronFlippedIcon"
import { Loader } from "../../../../components/Loader";
import { CONTAINER_IMAGE_PATTERN } from "../../session.constants";
import { prioritizeSelectedEnvironment } from "../../session.utils";
-import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
+// import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
+import { useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery } from "../../api/sessionLaunchersV2.api";
import { SessionLauncherForm } from "../../sessionsV2.types";
import { AdvancedSettingsFields } from "./AdvancedSettingsFields";
import { EnvironmentKindField } from "./EnvironmentKindField";
@@ -64,7 +65,7 @@ export default function EditLauncherFormContent({
data: environments,
error,
isLoading,
- } = useGetSessionEnvironmentsQuery();
+ } = useGetSessionEnvironmentsQuery({});
const environmentKind = watch("environment_kind");
const [isAdvanceSettingOpen, setIsAdvanceSettingsOpen] = useState(false);
const toggleIsOpen = useCallback(
diff --git a/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx b/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
index 864e312640..f7c6804e29 100644
--- a/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
+++ b/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
@@ -21,7 +21,8 @@ import { Input, ListGroup } from "reactstrap";
import { WarnAlert } from "../../../../components/Alert";
import { RtkErrorAlert } from "../../../../components/errors/RtkErrorAlert";
import { Loader } from "../../../../components/Loader";
-import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
+// import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
+import { useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery } from "../../api/sessionLaunchersV2.api";
import { EnvironmentFieldsProps } from "./EnvironmentField";
import { SessionEnvironmentItem } from "./SessionEnvironmentItem";
@@ -35,7 +36,7 @@ export function GlobalEnvironmentFields({
data: environments,
error,
isLoading,
- } = useGetSessionEnvironmentsQuery();
+ } = useGetSessionEnvironmentsQuery({});
const watchEnvironmentKind = watch("environment_kind");
return (
diff --git a/client/src/features/sessionsV2/components/SessionModals/ModifyResourcesLauncher.tsx b/client/src/features/sessionsV2/components/SessionModals/ModifyResourcesLauncher.tsx
index d897d56035..9eccb7c9d0 100644
--- a/client/src/features/sessionsV2/components/SessionModals/ModifyResourcesLauncher.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/ModifyResourcesLauncher.tsx
@@ -24,7 +24,7 @@ import {
MIN_SESSION_STORAGE_GB,
STEP_SESSION_STORAGE_GB,
} from "../../../session/startSessionOptions.constants";
-import { useUpdateSessionLauncherMutation } from "../../sessionsV2.api";
+import { usePatchSessionLaunchersByLauncherIdMutation as useUpdateSessionLauncherMutation } from "../../api/sessionLaunchersV2.api";
import {
ErrorOrNotAvailableResourcePools,
FetchingResourcePools,
@@ -74,8 +74,10 @@ export function ModifyResourcesLauncherModal({
: null;
updateSessionLauncher({
launcherId: sessionLauncherId,
- resource_class_id: data.resourceClass.id,
- disk_storage: diskStorage,
+ sessionLauncherPatch: {
+ resource_class_id: data.resourceClass.id,
+ disk_storage: diskStorage,
+ },
});
}
},
diff --git a/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx b/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
index 27a49f4bd3..c9fc57092f 100644
--- a/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
@@ -37,9 +37,9 @@ import { useGetNamespacesByNamespaceProjectsAndSlugQuery } from "../../../projec
import { DEFAULT_PORT, DEFAULT_URL } from "../../session.constants";
import { getFormattedEnvironmentValues } from "../../session.utils";
import {
- useAddSessionLauncherMutation,
- useGetSessionEnvironmentsQuery,
-} from "../../sessionsV2.api";
+ useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery,
+ usePostSessionLaunchersMutation as useAddSessionLauncherMutation,
+} from "../../api/sessionLaunchersV2.api";
import { SessionLauncherForm } from "../../sessionsV2.types";
import { EnvironmentFields } from "../SessionForm/EnvironmentField";
import { LauncherDetailsFields } from "../SessionForm/LauncherDetailsFields";
@@ -59,7 +59,7 @@ export default function NewSessionLauncherModal({
}: NewSessionLauncherModalProps) {
const [step, setStep] = useState(LauncherType.Environment);
const { namespace, slug } = useParams<{ namespace: string; slug: string }>();
- const { data: environments } = useGetSessionEnvironmentsQuery();
+ const { data: environments } = useGetSessionEnvironmentsQuery({});
const [addSessionLauncher, result] = useAddSessionLauncherMutation();
const { data: project } = useGetNamespacesByNamespaceProjectsAndSlugQuery(
namespace && slug ? { namespace, slug } : skipToken
@@ -120,11 +120,15 @@ export default function NewSessionLauncherModal({
: undefined;
if (environment.success && environment.data)
addSessionLauncher({
- project_id: projectId ?? "",
- resource_class_id: resourceClass.id,
- disk_storage: diskStorage,
- name,
- environment: environment.data,
+ sessionLauncherPost: {
+ project_id: projectId ?? "",
+ resource_class_id: resourceClass.id,
+ disk_storage: diskStorage,
+ name,
+ // TODO: fix types for this session environment
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ environment: environment.data as any,
+ },
});
},
[projectId, addSessionLauncher]
diff --git a/client/src/features/sessionsV2/components/SessionModals/SelectResourceClass.tsx b/client/src/features/sessionsV2/components/SessionModals/SelectResourceClass.tsx
index 6abed19b13..86560aaa01 100644
--- a/client/src/features/sessionsV2/components/SessionModals/SelectResourceClass.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/SelectResourceClass.tsx
@@ -55,7 +55,7 @@ interface SelectResourceClassModalProps {
isOpen: boolean;
onContinue: (env: ResourceClass, diskStorage: number | undefined) => void;
projectUrl: string;
- resourceClassId?: number;
+ resourceClassId?: number | null;
isCustom: boolean;
}
export function SelectResourceClassModal({
diff --git a/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx b/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
index c6a337f5d9..de52c949b7 100644
--- a/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
@@ -36,9 +36,9 @@ import {
getLauncherDefaultValues,
} from "../../session.utils";
import {
- useGetSessionEnvironmentsQuery,
- useUpdateSessionLauncherMutation,
-} from "../../sessionsV2.api";
+ useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery,
+ usePatchSessionLaunchersByLauncherIdMutation as useUpdateSessionLauncherMutation,
+} from "../../api/sessionLaunchersV2.api";
import { SessionLauncher, SessionLauncherForm } from "../../sessionsV2.types";
import EditLauncherFormContent from "../SessionForm/EditLauncherFormContent";
@@ -53,7 +53,7 @@ export default function UpdateSessionLauncherModal({
launcher,
toggle,
}: UpdateSessionLauncherModalProps) {
- const { data: environments } = useGetSessionEnvironmentsQuery();
+ const { data: environments } = useGetSessionEnvironmentsQuery({});
const [updateSessionLauncher, result] = useUpdateSessionLauncherMutation();
const defaultValues = useMemo(
() => getLauncherDefaultValues(launcher),
@@ -77,9 +77,13 @@ export default function UpdateSessionLauncherModal({
if (environment.success && environment.data)
updateSessionLauncher({
launcherId: launcher.id,
- name,
- description: description?.trim() || undefined,
- environment: environment.data,
+ sessionLauncherPatch: {
+ name,
+ description: description?.trim() || undefined,
+ // TODO: fix types for this session environment
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ environment: environment.data as any,
+ },
});
},
[launcher.id, updateSessionLauncher]
diff --git a/client/src/features/sessionsV2/sessionsV2.api.ts b/client/src/features/sessionsV2/sessionsV2.api.ts
deleted file mode 100644
index b0357404a5..0000000000
--- a/client/src/features/sessionsV2/sessionsV2.api.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-/*!
- * Copyright 2024 - Swiss Data Science Center (SDSC)
- * A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
- * Eidgenössische Technische Hochschule Zürich (ETHZ).
- *
- * Licensed 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.
- */
-
-import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
-
-import {
- AddSessionLauncherParams,
- DeleteSessionLauncherParams,
- DockerImage,
- GetLogsParams,
- GetProjectSessionLauncherParams,
- GetProjectSessionLaunchersParams,
- LaunchSessionParams,
- PatchSessionParams,
- SessionEnvironmentList,
- SessionImageParams,
- SessionLauncher,
- SessionLauncherList,
- SessionList,
- SessionV2,
- StopSessionParams,
- UpdateSessionLauncherParams,
-} from "./sessionsV2.types";
-
-const sessionsV2Api = createApi({
- reducerPath: "sessionsV2Api",
- baseQuery: fetchBaseQuery({
- baseUrl: "/api/data",
- }),
- tagTypes: ["Environment", "Launcher", "SessionsV2"],
- endpoints: (builder) => ({
- getSessionEnvironments: builder.query({
- query: () => {
- return {
- url: "environments",
- };
- },
- }),
- getSessionLaunchers: builder.query({
- query: () => {
- return {
- url: "session_launchers",
- };
- },
- providesTags: (result) =>
- result
- ? [
- ...result.map(({ id }) => ({ type: "Launcher" as const, id })),
- "Launcher",
- ]
- : ["Launcher"],
- }),
- getProjectSessionLaunchers: builder.query<
- SessionLauncherList,
- GetProjectSessionLaunchersParams
- >({
- query: ({ projectId }) => {
- return {
- url: `/projects/${projectId}/session_launchers`,
- };
- },
- providesTags: (result) =>
- result
- ? [
- ...result.map(({ id }) => ({ type: "Launcher" as const, id })),
- "Launcher",
- ]
- : ["Launcher"],
- }),
- getProjectSessionLauncher: builder.query<
- SessionLauncher,
- GetProjectSessionLauncherParams
- >({
- query: ({ id }) => {
- return {
- url: `/session_launchers/${id}`,
- };
- },
- providesTags: (result) =>
- result ? [{ type: "Launcher" as const, id: result.id }] : ["Launcher"],
- }),
- addSessionLauncher: builder.mutation<
- SessionLauncher,
- AddSessionLauncherParams
- >({
- query: ({ ...params }) => {
- return {
- url: "session_launchers",
- method: "POST",
- body: params,
- };
- },
- invalidatesTags: ["Launcher"],
- }),
- updateSessionLauncher: builder.mutation<
- SessionLauncher,
- UpdateSessionLauncherParams
- >({
- query: ({ launcherId, ...params }) => {
- return {
- url: `session_launchers/${launcherId}`,
- method: "PATCH",
- body: params,
- };
- },
- invalidatesTags: (_result, _error, { launcherId }) => [
- { id: launcherId, type: "Launcher" },
- ],
- }),
- deleteSessionLauncher: builder.mutation({
- query: ({ launcherId }) => {
- return {
- url: `session_launchers/${launcherId}`,
- method: "DELETE",
- };
- },
- invalidatesTags: ["Launcher"],
- }),
- getSessions: builder.query({
- query: () => ({ url: "sessions" }),
- providesTags: (result) =>
- result
- ? [
- ...result.map(({ name }) => ({
- type: "SessionsV2" as const,
- name,
- })),
- "SessionsV2",
- ]
- : ["SessionsV2"],
- }),
- launchSession: builder.mutation({
- query: ({
- launcher_id,
- disk_storage,
- resource_class_id,
- cloudstorage,
- }) => {
- const body = {
- launcher_id,
- disk_storage,
- resource_class_id,
- cloudstorage,
- };
- return {
- body,
- method: "POST",
- url: "/sessions",
- };
- },
- }),
- patchSession: builder.mutation({
- query: ({ session_id, state, resource_class_id }) => ({
- method: "PATCH",
- url: `sessions/${session_id}`,
- body: {
- ...(state ? { state } : {}),
- ...(resource_class_id ? { resource_class_id } : {}),
- },
- }),
- transformResponse: () => null,
- invalidatesTags: (_result, _error, { session_id }) => [
- { id: session_id, type: "SessionsV2" },
- ],
- }),
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- getLogs: builder.query({
- query: ({ session_id, max_lines }) => {
- return {
- url: `sessions/${session_id}/logs`,
- params: { max_lines },
- };
- },
- transformResponse: (result: unknown) => {
- return result && typeof result == "string"
- ? JSON.parse(result)
- : result;
- },
- keepUnusedDataFor: 0,
- }),
- stopSession: builder.mutation({
- query: ({ session_id }) => ({
- method: "DELETE",
- url: `sessions/${session_id}`,
- }),
- invalidatesTags: ["SessionsV2"],
- }),
- invalidateSessions: builder.mutation({
- queryFn: () => ({ data: null }),
- invalidatesTags: ["SessionsV2"],
- }),
- getDockerImage: builder.query({
- query: ({ image_url }) => ({
- method: "GET",
- url: "sessions/images",
- params: { image_url },
- }),
- }),
- }),
-});
-
-export default sessionsV2Api;
-export const {
- // useGetSessionsQuery,
- useGetSessionEnvironmentsQuery,
- useGetSessionLaunchersQuery,
- useGetProjectSessionLauncherQuery,
- useGetProjectSessionLaunchersQuery,
- useAddSessionLauncherMutation,
- useUpdateSessionLauncherMutation,
- useDeleteSessionLauncherMutation,
- // useLaunchSessionMutation,
- // usePatchSessionMutation,
- // useStopSessionMutation,
- // useGetLogsQuery,
- // useGetDockerImageQuery,
-} = sessionsV2Api;
diff --git a/client/src/features/sessionsV2/sessionsV2.types.ts b/client/src/features/sessionsV2/sessionsV2.types.ts
index 84f8990489..efcc4a11ac 100644
--- a/client/src/features/sessionsV2/sessionsV2.types.ts
+++ b/client/src/features/sessionsV2/sessionsV2.types.ts
@@ -31,7 +31,7 @@ export interface SessionEnvironment {
working_directory?: string;
mount_directory?: string;
port?: number;
- environment_kind: EnvironmentKind;
+ environment_kind?: EnvironmentKind;
command?: string[];
args?: string[];
}
@@ -44,7 +44,7 @@ export type SessionLauncher = {
name: string;
creation_date: string;
description?: string;
- resource_class_id?: number;
+ resource_class_id?: number | null;
disk_storage?: number;
environment: SessionLauncherEnvironment;
};
diff --git a/client/src/utils/helpers/EnhancedState.ts b/client/src/utils/helpers/EnhancedState.ts
index a11a6ef715..b726f6abf6 100644
--- a/client/src/utils/helpers/EnhancedState.ts
+++ b/client/src/utils/helpers/EnhancedState.ts
@@ -57,7 +57,8 @@ import sessionsApi from "../../features/session/sessions.api";
import sessionSidecarApi from "../../features/session/sidecar.api";
import startSessionSlice from "../../features/session/startSession.slice";
import { startSessionOptionsSlice } from "../../features/session/startSessionOptionsSlice";
-import sessionsV2Api from "../../features/sessionsV2/sessionsV2.api";
+import { sessionLaunchersV2EmptyApi as sessionLaunchersV2Api } from "../../features/sessionsV2/api/sessionLaunchersV2.empty-api";
+import { sessionsV2EmptyApi as sessionsV2Api } from "../../features/sessionsV2/api/sessionsV2.empty-api";
import startSessionOptionsV2Slice from "../../features/sessionsV2/startSessionOptionsV2.slice";
import termsApi from "../../features/terms/terms.api";
import { usersEmptyApi as usersApi } from "../../features/usersV2/api/users.empty-api";
@@ -107,6 +108,7 @@ export const createStore = (
[sessionsApi.reducerPath]: sessionsApi.reducer,
[sessionSidecarApi.reducerPath]: sessionSidecarApi.reducer,
[sessionsV2Api.reducerPath]: sessionsV2Api.reducer,
+ [sessionLaunchersV2Api.reducerPath]: sessionLaunchersV2Api.reducer,
[statuspageApi.reducerPath]: statuspageApi.reducer,
[termsApi.reducerPath]: termsApi.reducer,
[usersApi.reducerPath]: usersApi.reducer,
@@ -145,6 +147,7 @@ export const createStore = (
.concat(sessionSidecarApi.middleware)
.concat(sessionSidecarApi.middleware)
.concat(sessionsV2Api.middleware)
+ .concat(sessionLaunchersV2Api.middleware)
.concat(statuspageApi.middleware)
.concat(termsApi.middleware)
.concat(usersApi.middleware)
diff --git a/client/src/websocket/handlers/sessionStatusHandlerV2.ts b/client/src/websocket/handlers/sessionStatusHandlerV2.ts
index 5462accf3c..724ee64b9e 100644
--- a/client/src/websocket/handlers/sessionStatusHandlerV2.ts
+++ b/client/src/websocket/handlers/sessionStatusHandlerV2.ts
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-import sessionsV2Api from "../../features/sessionsV2/sessionsV2.api";
+import { sessionsV2Api } from "../../features/sessionsV2/api/sessionsV2.api";
import { StateModel } from "../../model";
function handleSessionsStatusV2(
From e01d84555e46e4e6220b2e9d4eb442306ae4d5e3 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Wed, 29 Jan 2025 11:49:10 +0100
Subject: [PATCH 08/11] update e2e fixture
---
tests/cypress/support/renkulab-fixtures/newSession.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/cypress/support/renkulab-fixtures/newSession.ts b/tests/cypress/support/renkulab-fixtures/newSession.ts
index 072a24a125..92fda5d718 100644
--- a/tests/cypress/support/renkulab-fixtures/newSession.ts
+++ b/tests/cypress/support/renkulab-fixtures/newSession.ts
@@ -128,7 +128,7 @@ export function NewSession(Parent: T) {
name = "getEnvironments",
} = args ?? {};
const response = { fixture };
- cy.intercept("GET", `/api/data/environments`, response).as(name);
+ cy.intercept("GET", `/api/data/environments*`, response).as(name);
return this;
}
};
From 646afcaf0dcb1dec0a893ceff387bcfc0bb7993d Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Wed, 29 Jan 2025 13:14:55 +0100
Subject: [PATCH 09/11] sorting
---
client/package.json | 8 ++++----
client/src/utils/helpers/EnhancedState.ts | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/client/package.json b/client/package.json
index 7e5a6a6a70..9397af42d4 100644
--- a/client/package.json
+++ b/client/package.json
@@ -22,16 +22,16 @@
"storybook-wait-server": "wait-on http://127.0.0.1:6006",
"storybook-test": "test-storybook",
"storybook-compile-and-test": "concurrently -k -s first -n 'BUILD,TEST' -c 'magenta,blue' 'npm run storybook-build && npm run storybook-start-server' 'npm run storybook-wait-server && npm run storybook-test'",
- "generate-api": "npm run generate-api:connectedServices && npm run generate-api:data-connectors && npm run generate-api:namespaceV2 && npm run generate-api:projectV2 && npm run generate-api:platform && npm run generate-api:searchV2 && npm run generate-api:users",
+ "generate-api": "npm run generate-api:connectedServices && npm run generate-api:data-connectors && npm run generate-api:namespaceV2 && npm run generate-api:platform && npm run generate-api:projectV2 && npm run generate-api:searchV2 && npm run generate-api:sessionLaunchersV2 && npm run generate-api:sessionsV2 && npm run generate-api:users",
"generate-api:connectedServices": "rtk-query-codegen-openapi src/features/connectedServices/api/connectedServices.api-config.ts",
"generate-api:data-connectors": "rtk-query-codegen-openapi src/features/dataConnectorsV2/api/data-connectors.api-config.ts",
"generate-api:namespaceV2": "rtk-query-codegen-openapi src/features/projectsV2/api/namespace.api-config.ts",
- "generate-api:projectV2": "rtk-query-codegen-openapi src/features/projectsV2/api/projectV2.api-config.ts",
"generate-api:platform": "rtk-query-codegen-openapi src/features/platform/api/platform.api-config.ts",
+ "generate-api:projectV2": "rtk-query-codegen-openapi src/features/projectsV2/api/projectV2.api-config.ts",
"generate-api:searchV2": "rtk-query-codegen-openapi src/features/searchV2/api/searchV2.api-config.ts",
- "generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts",
+ "generate-api:sessionLaunchersV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts",
"generate-api:sessionsV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionsV2.api-config.ts",
- "generate-api:sessionLaunchersV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionLaunchersV2.api-config.ts"
+ "generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts"
},
"type": "module",
"dependencies": {
diff --git a/client/src/utils/helpers/EnhancedState.ts b/client/src/utils/helpers/EnhancedState.ts
index b726f6abf6..deaf457f8a 100644
--- a/client/src/utils/helpers/EnhancedState.ts
+++ b/client/src/utils/helpers/EnhancedState.ts
@@ -105,10 +105,10 @@ export const createStore = (
[recentUserActivityApi.reducerPath]: recentUserActivityApi.reducer,
[repositoriesApi.reducerPath]: repositoriesApi.reducer,
[searchV2Api.reducerPath]: searchV2Api.reducer,
+ [sessionLaunchersV2Api.reducerPath]: sessionLaunchersV2Api.reducer,
[sessionsApi.reducerPath]: sessionsApi.reducer,
[sessionSidecarApi.reducerPath]: sessionSidecarApi.reducer,
[sessionsV2Api.reducerPath]: sessionsV2Api.reducer,
- [sessionLaunchersV2Api.reducerPath]: sessionLaunchersV2Api.reducer,
[statuspageApi.reducerPath]: statuspageApi.reducer,
[termsApi.reducerPath]: termsApi.reducer,
[usersApi.reducerPath]: usersApi.reducer,
@@ -143,11 +143,11 @@ export const createStore = (
.concat(recentUserActivityApi.middleware)
.concat(repositoriesApi.middleware)
.concat(searchV2Api.middleware)
+ .concat(sessionLaunchersV2Api.middleware)
.concat(sessionsApi.middleware)
.concat(sessionSidecarApi.middleware)
.concat(sessionSidecarApi.middleware)
.concat(sessionsV2Api.middleware)
- .concat(sessionLaunchersV2Api.middleware)
.concat(statuspageApi.middleware)
.concat(termsApi.middleware)
.concat(usersApi.middleware)
From 44e8126527100c5320fdf95d7e81870db819fce7 Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Wed, 29 Jan 2025 13:23:51 +0100
Subject: [PATCH 10/11] cleanup
---
client/.eslintignore | 6 +++---
client/src/features/dashboardV2/DashboardV2.tsx | 1 -
client/src/features/dashboardV2/DashboardV2Sessions.tsx | 2 +-
.../src/features/session/useWaitForSessionStatus.hook.ts | 3 +--
.../features/sessionsV2/DeleteSessionLauncherModal.tsx | 2 +-
.../features/sessionsV2/PauseOrDeleteSessionModal.tsx | 6 ++++--
.../sessionsV2/SessionList/SessionItemDisplay.tsx | 2 +-
.../sessionsV2/SessionShowPage/SessionPaused.tsx | 1 -
.../sessionsV2/SessionShowPage/ShowSessionPage.tsx | 6 ++++--
client/src/features/sessionsV2/SessionStartPage.tsx | 5 +++--
client/src/features/sessionsV2/SessionsV2.tsx | 2 +-
.../components/SessionForm/EditLauncherFormContent.tsx | 3 +--
.../components/SessionForm/GlobalEnvironmentFields.tsx | 3 ++-
.../components/SessionModals/NewSessionLauncherModal.tsx | 7 ++++---
.../SessionModals/UpdateSessionLauncherModal.tsx | 9 +++++----
client/src/utils/customHooks/UseGetSessionLogs.ts | 4 +++-
16 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/client/.eslintignore b/client/.eslintignore
index 865ee4b376..19e7e5d6d8 100644
--- a/client/.eslintignore
+++ b/client/.eslintignore
@@ -1,9 +1,9 @@
*.css
*.svg
# Generated files should not be linted
+src/features/dataConnectorsV2/api/data-connectors.api.ts
src/features/projectsV2/api/projectV2.api.ts
src/features/projectsV2/api/storagesV2.api.ts
-src/features/dataConnectorsV2/api/data-connectors.api.ts
-src/features/usersV2/api/users.generated-api.ts
-src/features/sessionsV2/api/sessionsV2.generated-api.ts
src/features/sessionsV2/api/sessionLaunchersV2.generated-api.ts
+src/features/sessionsV2/api/sessionsV2.generated-api.ts
+src/features/usersV2/api/users.generated-api.ts
diff --git a/client/src/features/dashboardV2/DashboardV2.tsx b/client/src/features/dashboardV2/DashboardV2.tsx
index 72e60cec78..e1d3cee551 100644
--- a/client/src/features/dashboardV2/DashboardV2.tsx
+++ b/client/src/features/dashboardV2/DashboardV2.tsx
@@ -61,7 +61,6 @@ import CreateProjectV2Button from "../projectsV2/new/CreateProjectV2Button";
import GroupShortHandDisplay from "../projectsV2/show/GroupShortHandDisplay";
import ProjectShortHandDisplay from "../projectsV2/show/ProjectShortHandDisplay";
import SearchV2Bar from "../searchV2/components/SearchV2Bar";
-// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/api/sessionsV2.api";
import { useGetUserQuery } from "../usersV2/api/users.api";
import UserAvatar from "../usersV2/show/UserAvatar";
diff --git a/client/src/features/dashboardV2/DashboardV2Sessions.tsx b/client/src/features/dashboardV2/DashboardV2Sessions.tsx
index 7a948d7572..1d8d22a5ef 100644
--- a/client/src/features/dashboardV2/DashboardV2Sessions.tsx
+++ b/client/src/features/dashboardV2/DashboardV2Sessions.tsx
@@ -25,10 +25,10 @@ import { Col, ListGroup, Row } from "reactstrap";
import { Loader } from "../../components/Loader";
import EnvironmentLogsV2 from "../../components/LogsV2";
import { RtkErrorAlert } from "../../components/errors/RtkErrorAlert";
-import { useGetSessionLaunchersByLauncherIdQuery as useGetProjectSessionLauncherQuery } from "../sessionsV2/api/sessionLaunchersV2.generated-api";
import { ABSOLUTE_ROUTES } from "../../routing/routes.constants";
import useAppSelector from "../../utils/customHooks/useAppSelector.hook";
import { useGetProjectsByProjectIdQuery } from "../projectsV2/api/projectV2.enhanced-api";
+import { useGetSessionLaunchersByLauncherIdQuery as useGetProjectSessionLauncherQuery } from "../sessionsV2/api/sessionLaunchersV2.api";
import ActiveSessionButton from "../sessionsV2/components/SessionButton/ActiveSessionButton";
import {
SessionStatusV2Description,
diff --git a/client/src/features/session/useWaitForSessionStatus.hook.ts b/client/src/features/session/useWaitForSessionStatus.hook.ts
index c88a267a44..4679a13044 100644
--- a/client/src/features/session/useWaitForSessionStatus.hook.ts
+++ b/client/src/features/session/useWaitForSessionStatus.hook.ts
@@ -17,9 +17,8 @@
*/
import { useEffect, useMemo, useState } from "react";
-import { useGetSessionsQuery } from "./sessions.api";
-// import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/sessionsV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../sessionsV2/api/sessionsV2.api";
+import { useGetSessionsQuery } from "./sessions.api";
import { SessionStatusState } from "./sessions.types";
const DEFAULT_POLLING_INTERVAL_MS = 5_000;
diff --git a/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx b/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
index 79fd2b774f..7a0ca31de9 100644
--- a/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/DeleteSessionLauncherModal.tsx
@@ -21,10 +21,10 @@ import { useCallback, useEffect } from "react";
import { Trash, XLg } from "react-bootstrap-icons";
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "reactstrap";
+import { WarnAlert } from "../../components/Alert";
import { RtkErrorAlert } from "../../components/errors/RtkErrorAlert";
import { useDeleteSessionLaunchersByLauncherIdMutation as useDeleteSessionLauncherMutation } from "./api/sessionLaunchersV2.api";
import { SessionLauncher } from "./sessionsV2.types";
-import { WarnAlert } from "../../components/Alert";
interface DeleteSessionLauncherModalProps {
isOpen: boolean;
diff --git a/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx b/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
index 99f6add6ea..6267782fd0 100644
--- a/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
+++ b/client/src/features/sessionsV2/PauseOrDeleteSessionModal.tsx
@@ -26,20 +26,22 @@ import {
useParams,
} from "react-router-dom-v5-compat";
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "reactstrap";
+
+import { Loader } from "../../components/Loader";
import { User } from "../../model/renkuModels.types";
import { NOTIFICATION_TOPICS } from "../../notifications/Notifications.constants";
import { NotificationsManager } from "../../notifications/notifications.types";
import { ABSOLUTE_ROUTES } from "../../routing/routes.constants";
import AppContext from "../../utils/context/appContext";
import useLegacySelector from "../../utils/customHooks/useLegacySelector.hook";
-import styles from "../session/components/SessionModals.module.scss";
import { useWaitForSessionStatusV2 } from "../session/useWaitForSessionStatus.hook";
import {
usePatchSessionsBySessionIdMutation as usePatchSessionMutation,
useDeleteSessionsBySessionIdMutation as useStopSessionMutation,
} from "./api/sessionsV2.api";
import { SessionV2 } from "./sessionsV2.types";
-import { Loader } from "../../components/Loader";
+
+import styles from "../session/components/SessionModals.module.scss";
interface PauseOrDeleteSessionModalProps {
action?: "pause" | "delete";
diff --git a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
index 9cc167469c..e7c53740e9 100644
--- a/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
+++ b/client/src/features/sessionsV2/SessionList/SessionItemDisplay.tsx
@@ -21,8 +21,8 @@ import { useCallback, useMemo } from "react";
import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
import { Project } from "../../projectsV2/api/projectV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../api/sessionsV2.api";
-import { SessionView } from "../SessionView/SessionView";
import { SessionLauncher } from "../sessionsV2.types";
+import { SessionView } from "../SessionView/SessionView";
import SessionItem from "./SessionItem";
interface SessionLauncherDisplayProps {
diff --git a/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx b/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
index 4b21c73872..c595047817 100644
--- a/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
+++ b/client/src/features/sessionsV2/SessionShowPage/SessionPaused.tsx
@@ -29,7 +29,6 @@ import { NOTIFICATION_TOPICS } from "../../../notifications/Notifications.consta
import type { NotificationsManager } from "../../../notifications/notifications.types";
import { ABSOLUTE_ROUTES } from "../../../routing/routes.constants";
import AppContext from "../../../utils/context/appContext";
-// import { usePatchSessionMutation } from "../sessionsV2.api";
import { usePatchSessionsBySessionIdMutation as usePatchSessionMutation } from "../api/sessionsV2.api";
import type { SessionV2 } from "../sessionsV2.types";
diff --git a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
index 3247d703ee..ac34bee6cf 100644
--- a/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
+++ b/client/src/features/sessionsV2/SessionShowPage/ShowSessionPage.tsx
@@ -43,6 +43,7 @@ import {
ModalHeader,
UncontrolledTooltip,
} from "reactstrap";
+
import { Loader } from "../../../components/Loader";
import EnvironmentLogsV2 from "../../../components/LogsV2";
import { TimeCaption } from "../../../components/TimeCaption";
@@ -57,16 +58,17 @@ import { displaySlice, resetFavicon, setFavicon } from "../../display";
import { useGetNamespacesByNamespaceProjectsAndSlugQuery } from "../../projectsV2/api/projectV2.enhanced-api";
import SessionUnavailable from "../../session/components/SessionUnavailable";
import { SessionRowResourceRequests } from "../../session/components/SessionsList";
-import styles from "../../session/components/ShowSession.module.scss";
import { StartSessionProgressBarV2 } from "../../session/components/StartSessionProgressBar";
import PauseOrDeleteSessionModal from "../PauseOrDeleteSessionModal";
-import { getSessionFavicon } from "../session.utils";
import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "../api/sessionLaunchersV2.api";
import { useGetSessionsQuery } from "../api/sessionsV2.api";
+import { getSessionFavicon } from "../session.utils";
import { SessionV2 } from "../sessionsV2.types";
import SessionIframe from "./SessionIframe";
import SessionPaused from "./SessionPaused";
+import styles from "../../session/components/ShowSession.module.scss";
+
export default function ShowSessionPage() {
const dispatch = useAppDispatch();
const {
diff --git a/client/src/features/sessionsV2/SessionStartPage.tsx b/client/src/features/sessionsV2/SessionStartPage.tsx
index cf1875915d..94604a38f3 100644
--- a/client/src/features/sessionsV2/SessionStartPage.tsx
+++ b/client/src/features/sessionsV2/SessionStartPage.tsx
@@ -28,6 +28,7 @@ import {
useParams,
useSearchParams,
} from "react-router-dom-v5-compat";
+
import { ErrorAlert } from "../../components/Alert";
import PageLoader from "../../components/PageLoader";
import {
@@ -57,12 +58,12 @@ import { useGetNamespacesByNamespaceProjectsAndSlugQuery } from "../projectsV2/a
import { storageSecretNameToFieldName } from "../secretsV2/secrets.utils";
import DataConnectorSecretsModal from "./DataConnectorSecretsModal";
import SessionSecretsModal from "./SessionSecretsModal";
-import { SelectResourceClassModal } from "./components/SessionModals/SelectResourceClass";
import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "./api/sessionLaunchersV2.api";
import {
- usePostSessionsMutation as useLaunchSessionMutation,
useGetSessionsImagesQuery as useGetDockerImageQuery,
+ usePostSessionsMutation as useLaunchSessionMutation,
} from "./api/sessionsV2.api";
+import { SelectResourceClassModal } from "./components/SessionModals/SelectResourceClass";
import { SessionLauncher } from "./sessionsV2.types";
import startSessionOptionsV2Slice from "./startSessionOptionsV2.slice";
import {
diff --git a/client/src/features/sessionsV2/SessionsV2.tsx b/client/src/features/sessionsV2/SessionsV2.tsx
index bea45492e9..589ba4f2a2 100644
--- a/client/src/features/sessionsV2/SessionsV2.tsx
+++ b/client/src/features/sessionsV2/SessionsV2.tsx
@@ -43,9 +43,9 @@ import DeleteSessionV2Modal from "./DeleteSessionLauncherModal";
import SessionItem from "./SessionList/SessionItem";
import { SessionItemDisplay } from "./SessionList/SessionItemDisplay";
import { SessionView } from "./SessionView/SessionView";
-import UpdateSessionLauncherModal from "./components/SessionModals/UpdateSessionLauncherModal";
import { useGetProjectsByProjectIdSessionLaunchersQuery as useGetProjectSessionLaunchersQuery } from "./api/sessionLaunchersV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "./api/sessionsV2.api";
+import UpdateSessionLauncherModal from "./components/SessionModals/UpdateSessionLauncherModal";
import { SessionLauncher, SessionV2 } from "./sessionsV2.types";
// Required for logs formatting
diff --git a/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx b/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
index 8c6ff9eafc..3444e1ebe7 100644
--- a/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
+++ b/client/src/features/sessionsV2/components/SessionForm/EditLauncherFormContent.tsx
@@ -31,10 +31,9 @@ import { Collapse, Input, Label, ListGroup } from "reactstrap";
import { RtkErrorAlert } from "../../../../components/errors/RtkErrorAlert";
import ChevronFlippedIcon from "../../../../components/icons/ChevronFlippedIcon";
import { Loader } from "../../../../components/Loader";
+import { useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery } from "../../api/sessionLaunchersV2.api";
import { CONTAINER_IMAGE_PATTERN } from "../../session.constants";
import { prioritizeSelectedEnvironment } from "../../session.utils";
-// import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
-import { useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery } from "../../api/sessionLaunchersV2.api";
import { SessionLauncherForm } from "../../sessionsV2.types";
import { AdvancedSettingsFields } from "./AdvancedSettingsFields";
import { EnvironmentKindField } from "./EnvironmentKindField";
diff --git a/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx b/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
index f7c6804e29..fe45f45d0b 100644
--- a/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
+++ b/client/src/features/sessionsV2/components/SessionForm/GlobalEnvironmentFields.tsx
@@ -15,13 +15,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import cx from "classnames";
import { Controller } from "react-hook-form";
import { Input, ListGroup } from "reactstrap";
+
import { WarnAlert } from "../../../../components/Alert";
import { RtkErrorAlert } from "../../../../components/errors/RtkErrorAlert";
import { Loader } from "../../../../components/Loader";
-// import { useGetSessionEnvironmentsQuery } from "../../sessionsV2.api";
import { useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery } from "../../api/sessionLaunchersV2.api";
import { EnvironmentFieldsProps } from "./EnvironmentField";
import { SessionEnvironmentItem } from "./SessionEnvironmentItem";
diff --git a/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx b/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
index c9fc57092f..4443be3d28 100644
--- a/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/NewSessionLauncherModal.tsx
@@ -30,16 +30,17 @@ import {
ModalFooter,
ModalHeader,
} from "reactstrap";
+
import { SuccessAlert } from "../../../../components/Alert";
import { RtkErrorAlert } from "../../../../components/errors/RtkErrorAlert";
import { Loader } from "../../../../components/Loader";
import { useGetNamespacesByNamespaceProjectsAndSlugQuery } from "../../../projectsV2/api/projectV2.enhanced-api";
-import { DEFAULT_PORT, DEFAULT_URL } from "../../session.constants";
-import { getFormattedEnvironmentValues } from "../../session.utils";
import {
- useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery,
usePostSessionLaunchersMutation as useAddSessionLauncherMutation,
+ useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery,
} from "../../api/sessionLaunchersV2.api";
+import { DEFAULT_PORT, DEFAULT_URL } from "../../session.constants";
+import { getFormattedEnvironmentValues } from "../../session.utils";
import { SessionLauncherForm } from "../../sessionsV2.types";
import { EnvironmentFields } from "../SessionForm/EnvironmentField";
import { LauncherDetailsFields } from "../SessionForm/LauncherDetailsFields";
diff --git a/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx b/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
index de52c949b7..c1411f2f59 100644
--- a/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
+++ b/client/src/features/sessionsV2/components/SessionModals/UpdateSessionLauncherModal.tsx
@@ -28,17 +28,18 @@ import {
ModalFooter,
ModalHeader,
} from "reactstrap";
+
import { SuccessAlert } from "../../../../components/Alert";
import { Loader } from "../../../../components/Loader";
import { RtkErrorAlert } from "../../../../components/errors/RtkErrorAlert";
-import {
- getFormattedEnvironmentValues,
- getLauncherDefaultValues,
-} from "../../session.utils";
import {
useGetEnvironmentsQuery as useGetSessionEnvironmentsQuery,
usePatchSessionLaunchersByLauncherIdMutation as useUpdateSessionLauncherMutation,
} from "../../api/sessionLaunchersV2.api";
+import {
+ getFormattedEnvironmentValues,
+ getLauncherDefaultValues,
+} from "../../session.utils";
import { SessionLauncher, SessionLauncherForm } from "../../sessionsV2.types";
import EditLauncherFormContent from "../SessionForm/EditLauncherFormContent";
diff --git a/client/src/utils/customHooks/UseGetSessionLogs.ts b/client/src/utils/customHooks/UseGetSessionLogs.ts
index a55930aee0..8d095cdb6f 100644
--- a/client/src/utils/customHooks/UseGetSessionLogs.ts
+++ b/client/src/utils/customHooks/UseGetSessionLogs.ts
@@ -15,10 +15,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import { useEffect, useState } from "react";
+
+import { ILogs } from "../../components/Logs";
import { useGetLogsQuery } from "../../features/session/sessions.api";
import { useGetSessionsBySessionIdLogsQuery as useGetLogsQueryV2 } from "../../features/sessionsV2/api/sessionsV2.api";
-import { ILogs } from "../../components/Logs";
/**
* useGetSessionLogs custom hook
From 102b81e848380a30bc2ea3f4d222b80d02e9174a Mon Sep 17 00:00:00 2001
From: Flora Thiebaut
Date: Wed, 29 Jan 2025 13:30:58 +0100
Subject: [PATCH 11/11] fix explode query args
---
.../sessionsV2/api/sessionLaunchersV2.api.ts | 105 +++++++++++-------
.../support/renkulab-fixtures/newSession.ts | 2 +-
2 files changed, 63 insertions(+), 44 deletions(-)
diff --git a/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts b/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
index ab4f1240fc..94b18943f6 100644
--- a/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
+++ b/client/src/features/sessionsV2/api/sessionLaunchersV2.api.ts
@@ -16,52 +16,71 @@
* limitations under the License.
*/
-import { sessionLaunchersV2GeneratedApi } from "./sessionLaunchersV2.generated-api";
+import {
+ type GetEnvironmentsApiArg,
+ type GetEnvironmentsApiResponse,
+ sessionLaunchersV2GeneratedApi,
+} from "./sessionLaunchersV2.generated-api";
+
+// Fixes some API endpoints
+const withFixedEndpoints = sessionLaunchersV2GeneratedApi.injectEndpoints({
+ overrideExisting: true,
+ endpoints: (build) => ({
+ getEnvironments: build.query<
+ GetEnvironmentsApiResponse,
+ GetEnvironmentsApiArg
+ >({
+ query: ({ getEnvironmentParams }) => ({
+ url: `/environments`,
+ params: getEnvironmentParams,
+ }),
+ }),
+ }),
+});
// Adds tag handling for cache management
-export const sessionLaunchersV2Api =
- sessionLaunchersV2GeneratedApi.enhanceEndpoints({
- addTagTypes: ["Environment", "Launcher"],
- endpoints: {
- getEnvironments: {
- providesTags: (result) =>
- result
- ? [
- ...result.map(({ id }) => ({
- id,
- type: "Environment" as const,
- })),
- "Environment",
- ]
- : ["Environment"],
- },
- getSessionLaunchersByLauncherId: {
- providesTags: (result) =>
- result
- ? [{ id: result.id, type: "Launcher" }, "Launcher"]
- : ["Launcher"],
- },
- postSessionLaunchers: {
- invalidatesTags: ["Launcher"],
- },
- patchSessionLaunchersByLauncherId: {
- invalidatesTags: (result) =>
- result ? [{ id: result.id, type: "Launcher" }] : ["Launcher"],
- },
- deleteSessionLaunchersByLauncherId: {
- invalidatesTags: ["Launcher"],
- },
- getProjectsByProjectIdSessionLaunchers: {
- providesTags: (result) =>
- result
- ? [
- ...result.map(({ id }) => ({ id, type: "Launcher" as const })),
- "Launcher",
- ]
- : ["Launcher"],
- },
+export const sessionLaunchersV2Api = withFixedEndpoints.enhanceEndpoints({
+ addTagTypes: ["Environment", "Launcher"],
+ endpoints: {
+ getEnvironments: {
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map(({ id }) => ({
+ id,
+ type: "Environment" as const,
+ })),
+ "Environment",
+ ]
+ : ["Environment"],
+ },
+ getSessionLaunchersByLauncherId: {
+ providesTags: (result) =>
+ result
+ ? [{ id: result.id, type: "Launcher" }, "Launcher"]
+ : ["Launcher"],
+ },
+ postSessionLaunchers: {
+ invalidatesTags: ["Launcher"],
+ },
+ patchSessionLaunchersByLauncherId: {
+ invalidatesTags: (result) =>
+ result ? [{ id: result.id, type: "Launcher" }] : ["Launcher"],
+ },
+ deleteSessionLaunchersByLauncherId: {
+ invalidatesTags: ["Launcher"],
+ },
+ getProjectsByProjectIdSessionLaunchers: {
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map(({ id }) => ({ id, type: "Launcher" as const })),
+ "Launcher",
+ ]
+ : ["Launcher"],
},
- });
+ },
+});
export const {
// "environments" hooks
diff --git a/tests/cypress/support/renkulab-fixtures/newSession.ts b/tests/cypress/support/renkulab-fixtures/newSession.ts
index 92fda5d718..072a24a125 100644
--- a/tests/cypress/support/renkulab-fixtures/newSession.ts
+++ b/tests/cypress/support/renkulab-fixtures/newSession.ts
@@ -128,7 +128,7 @@ export function NewSession(Parent: T) {
name = "getEnvironments",
} = args ?? {};
const response = { fixture };
- cy.intercept("GET", `/api/data/environments*`, response).as(name);
+ cy.intercept("GET", `/api/data/environments`, response).as(name);
return this;
}
};