diff --git a/.env.development b/.env.development index 61de4d2ff721795f2a01a4cbbedf8268c6794a44..419ea4b88290f568e51a96f8e2e2f9b150bb6bd2 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,3 @@ NEXT_PUBLIC_GL_CLIENT_ID=76df8d6ead161d6eb9b04d0bfeaca80ac4ad21b7d7bb69cf07b3ab17e17d5514 NEXT_PUBLIC_GL_REDIRECT_URI=http://localhost:3211 NEXT_PUBLIC_GL_URL=https://gitlab.inria.fr -NEXT_PUBLIC_API_ROOT=https://public-api.grid5000.fr/stable diff --git a/.env.production b/.env.production index e0127bdb4e8ad421b03e21f8b210a3242d7b9ea5..f244e768e7d576b1dc392eeec70ee0aeade6868f 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,3 @@ NEXT_PUBLIC_GL_CLIENT_ID=76df8d6ead161d6eb9b04d0bfeaca80ac4ad21b7d7bb69cf07b3ab17e17d5514 NEXT_PUBLIC_GL_REDIRECT_URI=https://grid5000.gitlabpages.inria.fr/pipeline-creation-assistant NEXT_PUBLIC_GL_URL=https://gitlab.inria.fr -NEXT_PUBLIC_API_ROOT=https://public-api.grid5000.fr/stable diff --git a/package-lock.json b/package-lock.json index 50a445c29472357b7283433758e73a60f3d311a0..083518c78b012ba0f0a14ad3a2547b2e48592a28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@fontsource/roboto": "^5.1.0", + "@grid5000/refrepo-ts": "^1.0.0", "@mui/icons-material": "^6.1.2", "@mui/material": "^6.1.2", "@mui/material-nextjs": "^6.1.2", @@ -520,6 +521,11 @@ "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, + "node_modules/@grid5000/refrepo-ts": { + "version": "1.0.0", + "resolved": "https://gitlab.inria.fr/api/v4/projects/55430/packages/npm/@grid5000/refrepo-ts/-/@grid5000/refrepo-ts-1.0.0.tgz", + "integrity": "sha1-wsaCp781PnvO00mwjxYNLuNgm9s=" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", diff --git a/package.json b/package.json index 20c5926d3e597b7be3e4a65b9c38312ce28e4d2f..cef2d21c33119ccbe1826cab46143003c13ab1a6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@fontsource/roboto": "^5.1.0", + "@grid5000/refrepo-ts": "^1.0.0", "@mui/icons-material": "^6.1.2", "@mui/material": "^6.1.2", "@mui/material-nextjs": "^6.1.2", diff --git a/src/components/TestImagesTabContent.tsx b/src/components/TestImagesTabContent.tsx index f957d4ffda0dd6295aa34d7771188b5133562ced..db335a5d7daa9a4e8e5b86be51556db01d3d25ab 100644 --- a/src/components/TestImagesTabContent.tsx +++ b/src/components/TestImagesTabContent.tsx @@ -19,7 +19,7 @@ import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import ListSubheader from '@mui/material/ListSubheader'; import LoadingRefApi from './LoadingRefApi'; -import { ObjectMap } from '@/lib/refrepo'; +import { ObjectMap } from '@grid5000/refrepo-ts'; import RemoteBranchSelector from './RemoteBranchSelector'; import Stack from '@mui/material/Stack'; import Tooltip from '@mui/material/Tooltip'; diff --git a/src/hooks/useRefApi.ts b/src/hooks/useRefApi.ts index 7560f0bca13143c0dd8ed8102c3bb24fc4427d14..34c8086d3ceb72c947f51c05280090d4a508f758 100644 --- a/src/hooks/useRefApi.ts +++ b/src/hooks/useRefApi.ts @@ -1,7 +1,6 @@ -import { APIResponse, ClusterNode, ClustersAPI, GPUDevice, Network, ObjectMap, OtherDevice, SitesAPI } from "@/lib/refrepo"; +import { APIResponse, ClusterNode, ClustersAPIResponse, GPUDevice, Network, ObjectMap, OtherDevice, SitesAPIResponse, clustersUrl, nodesUrl, sitesUrl } from "@grid5000/refrepo-ts"; import { Architecture, platformTypeToOurArch } from "@/lib/config"; import { Key, SWRHook } from "swr"; -import { clustersUrl, nodesUrl, sitesUrl } from "@/lib/routes"; import { defaultFetch, fetchItems } from "@/lib/requests"; import { isFirstOne } from "@/lib/generation"; import { useMemo } from "react"; @@ -51,7 +50,7 @@ export type RefApiData = { function computeKeyFromClusters( getUrl: (e: string) => string, - response: APIResponse<ClustersAPI> | undefined + response: ClustersAPIResponse | undefined ) { if (response === undefined) { return undefined; @@ -149,8 +148,8 @@ function nodesByIdMiddleware(useSWRNext: SWRHook) { } function computeClustersBySite( - sites: APIResponse<SitesAPI>, - clustersResponse: APIResponse<ClustersAPI>[], + sites: SitesAPIResponse, + clustersResponse: ClustersAPIResponse[], ): ClustersBySite { const clusters = clustersResponse.map(({ items }) => items.map(({ uid }) => uid)); @@ -167,8 +166,8 @@ export function useRefapi(branch: string = 'master'): RefApiData { data: sites, isLoading: sitesLoading, error: sitesError, } = useSWRImmutable(sitesUrl(branch), defaultFetch); - const branchClustersUrl = useMemo(() => clustersUrl.bind(null, branch), [branch]); - const branchNodesUrl = useMemo(() => nodesUrl.bind(null, branch), [branch]); + const branchClustersUrl = useMemo(() => (s: string) => clustersUrl(s, branch), [branch]); + const branchNodesUrl = useMemo(() => (s: string, c: string) => nodesUrl(s, c, branch), [branch]); const { data: clusters, isLoading: clustersLoading, error: clustersError, diff --git a/src/lib/refrepo.ts b/src/lib/refrepo.ts deleted file mode 100644 index 2cbc7dde979f6ec34bf4947de2e4cb1cb1c709d8..0000000000000000000000000000000000000000 --- a/src/lib/refrepo.ts +++ /dev/null @@ -1,190 +0,0 @@ - -// FIXME: taken from accesses, we should definitely make a small ts lib - -export type ObjectMap<T> = { - [id: string]: T, -}; - -export type GPUDevice = { - model: string, - vendor: string, -}; - -export type OtherDevice = { - count: number, - memory: number, - model: string, - type: string, - vendor: string, -}; - -export type Processor = { - other_description: string, - model: string, - vendor: string, - microarchitecture: string, - version: string, - clock_speed: number, -}; - -export function getFamily({ model, vendor }: Processor): string { - return model.replace(`${vendor} `, ''); -} - -export type Architecture = { - nb_procs: number, - nb_cores: number, - nb_threads: number, - // NOTE: this doesn't seem future-proof. - platform_type: 'x86_64' | 'ppc64le' | 'aarch64', -}; - -export type RamSlot = { - size: number, - technology: 'dram' | 'pmem', -}; - -export type Storage = { - id: string, - interface: string, - storage: 'HDD' | 'SSD', - reservation?: boolean, - model: string, - vendor: string, - size: number, -}; - -export type Performance = { - node_flops: number, - core_flops: number, -}; - -export type Network = { - device: string, - driver: string, - interface: string, - kavlan: boolean, - enabled: boolean, - management: boolean, - model?: string, - mountable: boolean, - mounted: boolean, - rate?: number, - sriov: boolean, - sriov_totalvfs: number, - name: string, - vendor?: string, -}; - -export interface Identifiable { - uid: string, -} - -export type ClusterNode = { - uid: string, - exotic: boolean, - chassis: { - name: string, - manufacturer: string, - }, - gpu_devices?: ObjectMap<GPUDevice>, - other_devices?: ObjectMap<OtherDevice>, - memory_devices: RamSlot[], - storage_devices: Storage[], - network_adapters: Network[], - performance: Performance, - processor: Processor, - architecture: Architecture, - nodeset: string, -}; - -export type ClusterCommon = { - uid: string, - exotic: boolean, - model: string, - created_at: string, - manufactured_at: string, - queues: Array<string>, -}; - -export type Cluster = ClusterCommon & { - nodes: ObjectMap<ClusterNode>, -}; - -export type Site = { - uid: string, - clusters: ObjectMap<Cluster>, -}; - -export type RefRepoData = { - sites: ObjectMap<Site>, -}; - -export type SitesAPI = { - uid: string, -}; - -export type ClustersAPI = ClusterCommon; - -export type APIResponse<T> = { - items: T[]; -}; - -export function getSitesUids(refrepo: RefRepoData): string[] { - return Object.values(refrepo.sites).map(({ uid }) => uid); -} - -// This could also be name "make it sortable", and fixes the fact that numbers -// in cluster names are not padded. -export function normalizeClusterName(uid: string): string { - const asArray = Array.from(uid); - const firstNumber = asArray.findIndex(char => char >= '0' && char <= '9'); - if (firstNumber === -1) { - return uid; - } - const name = uid.slice(0, firstNumber); - const number = uid.slice(firstNumber); - return `${name}${number.padStart(4, '0')}`; -} - -//export async function buildCluster(site: string, cluster: ClustersAPI) { -//const nodes = -//(await defaultFetch(nodesUrl(site, cluster.uid))) as APIResponse<ClusterNode>; -//const ret: Cluster = { -//...cluster, -//nodes: {}, -//}; -//nodes.items.forEach(n => ret.nodes[n.uid] = n); -//return ret; -//} - -//// The full refrepo is too big for nextjs's cache (>2MB), since we generate -//// data at build time anyway, we might as well create a lot of cachable fetches. -//export async function buildSite(s: string) { -//const clusters = (await defaultFetch(clustersUrl(s))) as APIResponse<ClustersAPI>; - -//const site: Site = { -//uid: s, -//clusters: {}, -//}; -//for (const c of clusters.items) { -//site.clusters[c.uid] = await buildCluster(s, c); -//} -//return site; -//} - -//export async function getSites() { -//const sites = (await defaultFetch(sitesUrl())) as APIResponse<SitesAPI>; -//return sites.items.map(({ uid }) => uid); -//} - -//export async function buildFullRefrepo(onlySites: string[]) { -//const sites = onlySites.length > 0 ? onlySites : await getSites(); -//const refrepo: RefRepoData = { -//sites: {}, -//}; -//for (const s of sites) { -//refrepo.sites[s] = await buildSite(s); -//} -//return refrepo; -//} diff --git a/src/lib/routes.ts b/src/lib/routes.ts deleted file mode 100644 index 9a89c92fe3858bfb82ebea375d57b518246019b2..0000000000000000000000000000000000000000 --- a/src/lib/routes.ts +++ /dev/null @@ -1,18 +0,0 @@ - -// TODO: withBranch(branch), adds ?branch=branch; -export function apiUrl(path: string, branch: string | undefined = undefined) { - const appendUrl = branch ? `?branch=${branch}` : ''; - return `${process.env.NEXT_PUBLIC_API_ROOT}${path}${appendUrl}`; -} - -export function sitesUrl(branch: string) { - return apiUrl('/sites', branch); -} - -export function clustersUrl(branch: string, site: string) { - return apiUrl(`/sites/${site}/clusters`, branch); -} - -export function nodesUrl(branch: string, site: string, cluster: string) { - return apiUrl(`/sites/${site}/clusters/${cluster}/nodes`, branch); -}