Commit Graph
199 Commits
Author SHA1 Message Date
Yuxing Dengandjialin f62e0ba372 feat(cluster): add default container registry field to advanced config
Surface the top-level system_default_container_registry as a dedicated
input (both Docker and K8s), coerce blank to null, and drop its
redundant worker_config YAML hint.
2026-05-29 23:11:46 +08:00
Yuxing Deng fcd1d01e83 feat(cluster): update K8s cluster form for new k8s_options API
Align the Kubernetes cluster create/edit page with the backend's
promotion of operator/K8s knobs out of worker_config and the removal
of gpuVendorOverrides.

- k8s_options: drop gpuVendorOverrides; add operatorImage, namespace,
  and gpuInstanceOptions (presence = GPU instances enabled, carrying an
  optional gpuInstancesAccessStaticAddress).
- Add a top-level system_default_container_registry to the cluster type
  (promoted out of worker_config on the backend).
- Group all k8s_options fields into a new top-level "K8s Deployment
  Options" collapsible section (sibling of Advanced, rendered above it),
  with namespace first followed by volume mounts, image credentials,
  node selector, operator image, and GPU instances.
- Drive the GPU instances toggle from local state instead of
  Form.useWatch (an unregistered nested path never re-rendered, leaving
  the switch unresponsive); use antd's borderless Switch and keep the
  label/switch grouped together. Namespace gains a gpustack-system
  placeholder.
- Remove the gpuVendorOverrides validation from the form and the stale
  operator_image / namespace / gpu_instances_access_static_address hints
  from the worker_config YAML template and JSON schema.
- Add-worker GPU picker: always allow multi-select for K8s clusters
  (runtime node selectors are now auto-derived), dropping the
  override-gating, cluster fetch, and single-only hint.
- Update locales (en/zh/ja/ru/tr) for the removed and added keys.
2026-05-29 17:56:01 +08:00
gitlawrandjialin 5cff1298fc feat(management): show only own rows on Clusters / Storage Types lists
The two management pages now pass ``mine=true`` to their list APIs.
With multi-tenant cluster_access in place an Org Owner would
otherwise see rows that came in via cross-Org grants — usable but
read-only — and editing/deleting them would 403 from the backend.
Restricting the management lists to rows the caller's scope owns
keeps the UX honest. PV-create / GPU-instance-create pickers still
query without ``mine`` so usable cross-Org clusters and types are
selectable there.
2026-05-28 18:16:15 +08:00
jialinandjialin e47a9304f4 fix: cluster worker_config refill 2026-05-28 15:51:51 +08:00
jialinandjialin b590aa746b fix: update onceMaxRequest field 2026-05-28 15:51:51 +08:00
jialinandjialin a4c48c1981 fix: remove description json format 2026-05-27 17:10:15 +08:00
jialinandjialin 3497590d2e fix: using select handler for provider hint 2026-05-27 17:10:15 +08:00
gitlawrandjialin f15d0ab243 fix(cluster-create): hide ProviderCatalog when entering via providerHint
The catalog was gated on ``currentStep === startStep`` so it would
re-appear at step 1 whenever ``providerHint`` skipped the catalog (e.g.
GPU Service's "Add a Kubernetes Cluster" empty-state CTA). Result: the
configure step rendered the catalog *plus* the Name/Description/Advanced
form together, with Kubernetes shown as already selected — confusing
and ugly.

Pin the catalog to step 0 explicitly. ``startStep`` was only used to
seed ``currentStep``, so it's inlined into the ``useState`` initializer
to keep the "skip the catalog when providerHint is set" intent in one
place. Pre-selecting a provider now correctly lands the user straight
on the configure form alone.
2026-05-27 15:53:39 +08:00
gitlawrandjialin 96e6ddfe8a fix: collapse GPU Service menu in Personal Org; add K8s-direct CTA
Two follow-ups to the GPU Service gating:

- In Personal-Org view the access extension was stripping
  canSeeAdmin/canSeeOrgAdmin but leaving canSeeGpuService at its
  admin-shortcut value, so platform admins switched into Personal
  still saw the menu even though Personal scope can't host a K8s
  cluster. Mirror the probe result through sessionStorage so the
  extension can fall back to the strict cluster-availability signal
  in that branch.

- The empty-state CTA now reads 'Add a Kubernetes Cluster' and, on
  click, opens the cluster-create flow with Kubernetes preselected
  via clusterSession.providerHint. ClusterCreate consumes the hint
  on mount: it seeds extraData.provider and starts at the configure
  step instead of the provider catalog, so the user lands one click
  closer to the form they actually need.
2026-05-27 13:41:32 +08:00
Yuxing Deng acb90531b2 feat: extend cluster k8s_options with multi-vendor manifest support
- New k8s_pod_spec form sections (image credentials, node selector,
  gpu vendor overrides) under k8s_options, replacing the legacy flat
  k8s_volume_mounts list. UI keys aligned to the backend wire shape
  (snake_case k8s_options + camelCase inside).
- System default container registry is pre-filled into the first image
  credential when creating a new cluster; empty username/password are
  coerced to null on submit to match the Optional[str] backend schema.
- Register cluster flow supports multi-runtime selection gated by the
  cluster's gpuVendorOverrides: non-override vendors stay single-select
  with an inline hint; multi-add only opens once an override vendor is
  picked, and non-override cards become disabled in that state.
- Manifest URL emits multiple ?runtime= params; check-env step combines
  per-vendor commands; downstream steps are disabled when no vendor is
  selected.
- Pre-validate gpuVendorOverrides at save time (non-empty selector, no
  duplicates across vendors, no key clash with base nodeSelector) so
  the user sees the error before hitting the manifest endpoint.
- Misc: dark-mode background of the k8s_pod_spec / volume mount titles
  no longer clashes with the drawer; cluster Steps no longer leaks the
  internal showModules/showForms props to the DOM.
2026-05-26 16:54:14 +08:00
jialinandjialin 921a2a0d81 fix: instance form ux 2026-05-25 22:42:02 +08:00
jialinandjialin 6f896b4f94 fix(style): use --app-banner-height in scroller container 2026-05-21 19:58:16 +08:00
gitlawrandjialin e7a376db70 refactor: adapt org-namespace lookup to principal name rename
Tracks the gpustack identity-consolidation effort: the unified
``principals`` table's URL-safe identifier column was renamed
``slug`` → ``name`` (with the legacy display ``name`` → ``display_name``).
The enterprise plugin's persisted org caches (``organizationList``,
``allOrganizations`` in localStorage) now write ``name`` instead of
``slug`` on each Organization row.

``getCurrentOrgNamespace`` reads those caches to compose the k8s
namespace (``gpustack-{name}``) for GPU-instance / storage CRDs.
Updated to read ``item.name`` so namespace resolution stays in sync
with what the enterprise plugin writes — otherwise every gpu-service
write would fall through to ``gpustack-default`` even when the user
has an Org context.

Stale ``slug`` references in surrounding comments also retitled to
``name`` to avoid divergence between code and prose. The namespace
format itself (``gpustack-{...}``) is unchanged — only the column it
sources is.
2026-05-21 12:15:39 +08:00
gitlawrandjialin 2dae886fd1 fix(gpu-service): use gpustack-{slug} namespace for org resources
The legacy ``getCurrentOrganizationId`` helper returned the raw numeric
org id from localStorage, which the GPU-service / storage call sites
then used as the K8s namespace path segment — producing requests like
``/v2/clusters/1/proxy/.../namespaces/5/instances``. The backend
creates a namespace named ``gpustack-{slug}`` (matching
``get_namespace_name``), so the request hit a namespace that doesn't
exist.

Replace the helper with ``getCurrentOrgNamespace`` that:

- prefers the Org the caller is acting under (numeric
  ``currentOrganizationId`` from localStorage, slug looked up in the
  persisted ``organizationList`` or ``allOrganizations`` cache);
- falls back to the selected cluster's owner Org slug for the admin
  "All" view, where there is no explicit Org context but the resource
  still has to land in some Org's namespace — call sites pass
  ``currentCluster?.owner_principal_id`` through;
- falls back to ``gpustack-default`` only if neither path resolves a
  slug (first load before any cache hydrates, etc.).

``ClusterListItem`` is widened with the optional ``owner_principal_id``
field so TypeScript accepts the fallback argument; the backend has
been returning it via ``ClusterPublic`` all along.
2026-05-13 12:29:09 +08:00
gitlawrandjialin 125a5be91f feat: restore cluster detail surface, gate cluster-list name link via plugin
The "chore: hide cluster detail" change had commented out both the
cluster-detail route and the cluster name link in the list. The
detail page component still ships in the OSS tree, so reach is
restored but the link is plugin-gated rather than unconditional:
plain OSS renders the name as a span; with a registered
`clusterDetail.linkableName` flag the name turns into a
`Typography.Link` that fires the parent's existing `onCellClick`
(which navigates to the detail route).

Detail tabs adjustments for the in-cluster context:
- Drop the Deployments tab (deployments are managed from the
  top-level Models page; the detail view is scoped to a single
  cluster's hardware).
- `WorkerList` and `GPUList` accept an optional `clusterId`. When
  set, the list pins `cluster_id` in its query and hides the
  cluster-filter dropdown so the user can't scope away from the
  cluster they're inside.

`clusterDetail.extraTabs(clusterId, intl)` exposes a plugin slot
that appends additional tab items — used by the enterprise plugin
to inject per-cluster Access / Quotas surfaces. No-op without a
plugin.
2026-05-11 20:28:29 +08:00
gitlawrandjialin 2889ba7c78 feat: plugin extension slots for access, request interceptors, Users actions, and form fields
Four purely-additive seams that let build-time tooling extend host
behaviour without forking files:

* `src/access.extensions.ts` — identity `applyAccessExtensions`
  (mirrors `config/routes.extensions.ts`). `src/access.ts` runs the
  resolved predicate object through it. Adds two new predicates,
  `canSeeOrgAdmin` and `canManageCurrentOrg`, alongside the existing
  `canSeeAdmin`. Resources, Models children, Cluster Management, and
  Resources/Backends are retagged from `canSeeAdmin` to
  `canSeeOrgAdmin`. Users and Dashboard stay strict.
* `src/request.extensions.ts` — identity-empty
  `extraRequestInterceptors`. `src/request-config.tsx` spreads it
  into the existing `requestInterceptors` list so extensions can
  inject context-aware headers without forking the request config.
* Users page action column — renders
  `getGPUStackPlugin()?.components?.UserRowActions` next to the
  existing DropdownButtons inside a Space when a plugin component
  is registered. If absent, the cell renders exactly as before.
* `src/components/plugin-extra-fields.tsx` — generic component-slot
  helper. Renders `pluginManager.components.<name>` if registered,
  forwarding a `context` payload. Used by create/edit forms to let
  plugins inject extra `Form.Item` fields. Mounted in the relevant
  create forms — API Keys, Cloud Credentials, Clusters, Model
  Routes, Model Providers, and Inference Backends — under the slot
  name `CreateOrgScopeField`. Resources whose org is implicit from a
  parent (Models / Workers / Benchmarks / Worker Pools / Model Files
  inherit from the chosen Cluster) deliberately don't mount the slot.
2026-05-08 18:29:52 +08:00
jialinandjialin 217285223c fix: list-input, labels-selector form 2026-04-29 18:09:55 +08:00
jialinandjialin 6fccee3711 fix: impoer external components 2026-04-24 14:28:30 +08:00
jialinandjialin 597a86562a fix: rebase main 2026-04-24 14:28:30 +08:00
jialinandjialin 6c161c6ae7 build: sync config 2026-04-24 14:28:30 +08:00
jialinandjialin 48b357b1c6 chore: update hooks import 2026-04-24 14:28:30 +08:00
jialinandjialin 8711c27b78 chore: replace components with core-ui, upgrade eslint 2026-04-24 14:28:30 +08:00
jialinandjialin 3ac2720ba8 chore: remove experimental from metax 2026-04-16 15:03:59 +08:00
jialinandjialin 41c9b86fd9 fix: k8s volume config 2026-04-14 20:42:01 +08:00
jialinandjialin cf13e3bed0 fix: volume mounts default empty 2026-04-10 15:33:59 +08:00
jialinandjialin 0956538b79 fix: volume name update while typing 2026-04-10 15:17:58 +08:00
jialinandjialin f2a4ab2654 feat: k8s volume mounts 2026-04-10 15:17:58 +08:00
jialinandjialin c73609d155 fix: adjust border raduis 2026-04-08 18:54:06 +08:00
jialinandjialin adde7fba37 feat: add instance view 2026-03-26 18:20:55 +08:00
jialinandjialin f0e19c8934 fix: spin size 2026-03-19 12:28:18 +08:00
jialinandjialin a6af51dc32 fix: delay querying backends 2026-03-19 12:28:18 +08:00
jialinandjialin 9840a48301 fix: depercated props 2026-03-19 12:28:18 +08:00
jialinandjialin a86bfe7fd3 chore: upgrade antd 6.3.3 2026-03-17 16:35:55 +08:00
jialinandjialin 4f02bcd40c feat: paste multiple lines in parameters input 2026-03-17 16:35:55 +08:00
jialinandjialin 68519223fa fix: pagination cache for table list 2026-03-17 16:35:55 +08:00
jialin 511297ed11 fix: do not cache while watching during manual updates 2026-02-13 19:32:59 +08:00
jialin 88aafbaf7b refactor: list watch trigger 2026-02-13 16:12:56 +08:00
jialin 59c19f3fae fix: update add worker command 2026-02-11 17:54:34 +08:00
jialin 1b8c17ce92 fix: tts params filter 2026-02-11 15:30:35 +08:00
jialin 15d635322b fix: target model text overflow 2026-02-10 17:29:57 +08:00
jialin 198a52e230 chore: add runtime in register k8s command 2026-02-09 15:58:29 +08:00
jialin f35ba8f8e5 fix: success message in creation cluster 2026-02-08 10:27:49 +08:00
jialin 21ffd2a564 fix: env params incorrect after switching between vendors 2026-02-07 16:51:09 +08:00
jialin 4ff5b3e05a chore: grafana entry 2026-02-06 14:27:05 +08:00
jialin 7f3d6bb55f fix: ui issues 2026-02-06 11:13:49 +08:00
jialin a1a7979fb3 fix: update open playground btn 2026-02-05 11:55:05 +08:00
jialin 4e8b5e26ae feat: monitor button 2026-02-04 20:14:25 +08:00
jialin 8f2eea70f6 chore: detail api 2026-01-30 18:48:55 +08:00
jialin ec9a4b2607 fix: duplicate watch created 2026-01-20 14:51:45 +08:00
jialin d5f3158638 fix: recreate watch request after cluster changed 2026-01-20 13:40:15 +08:00