feat(frontend): add Helm chart browser, monitoring, chart-references and values templates pages

Add new frontend pages for the multi-tenant OCDP platform:

- Charts page (/charts): Browse Harbor OCI registries to list Helm chart repositories
  and versions, with deploy modal to launch charts on selected clusters
- Monitoring page (/monitoring): Display cluster metrics (CPU/Memory/GPU usage)
  and per-node details with resource utilization bars
- Chart References page (/chart-references): CRUD for chart metadata references
- Values Templates page (/templates): CRUD for Helm values templates with version
  history and rollback support
- Sidebar: Add Charts navigation, update Storage and Templates links
- api.ts: Add all API client functions (clusterApi, registryApi, instanceApi,
  monitoringApi, storageApi, chartReferenceApi, valuesTemplateApi,
  workspaceApi, userApi) with full TypeScript types

Note: deploy flow and values template rollback not yet end-to-end tested.
This commit is contained in:
Ivan087
2026-04-15 16:59:31 +08:00
parent c5e51ed069
commit 29d0310f03
283 changed files with 24658 additions and 36038 deletions

View File

@ -0,0 +1,190 @@
-- OCDP Multi-Tenant Migration Script
-- Adds multi-tenant fields and new tables for workspace isolation
-- ===== Phase 1: Add new columns to existing tables =====
-- Add multi-tenant fields to users table
ALTER TABLE users ADD COLUMN IF NOT EXISTS role VARCHAR(20) NOT NULL DEFAULT 'user';
ALTER TABLE users ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36);
ALTER TABLE users ADD COLUMN IF NOT EXISTS is_active BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE users ADD COLUMN IF NOT EXISTS must_change_password BOOLEAN NOT NULL DEFAULT FALSE;
-- Add indexes for new user fields
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
CREATE INDEX IF NOT EXISTS idx_users_workspace_id ON users(workspace_id);
CREATE INDEX IF NOT EXISTS idx_users_is_active ON users(is_active);
-- Add multi-tenant fields to clusters table
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36);
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36);
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS isolation_mode VARCHAR(20) NOT NULL DEFAULT 'namespace';
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS default_namespace VARCHAR(255);
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS is_shared BOOLEAN NOT NULL DEFAULT FALSE;
-- Add index for cluster workspace
CREATE INDEX IF NOT EXISTS idx_clusters_workspace_id ON clusters(workspace_id);
-- Add multi-tenant fields to registries table
ALTER TABLE registries ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36);
ALTER TABLE registries ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36);
ALTER TABLE registries ADD COLUMN IF NOT EXISTS is_shared BOOLEAN NOT NULL DEFAULT FALSE;
-- Add index for registry workspace
CREATE INDEX IF NOT EXISTS idx_registries_workspace_id ON registries(workspace_id);
-- Add multi-tenant fields to instances table
ALTER TABLE instances ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36);
ALTER TABLE instances ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36);
ALTER TABLE instances ADD COLUMN IF NOT EXISTS values_template_id VARCHAR(36);
ALTER TABLE instances ADD COLUMN IF NOT EXISTS user_override_yaml TEXT;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS cpu_requested DECIMAL(10,2) NOT NULL DEFAULT 0;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS memory_requested VARCHAR(50) NOT NULL DEFAULT '0Mi';
ALTER TABLE instances ADD COLUMN IF NOT EXISTS gpu_requested DECIMAL(10,2) NOT NULL DEFAULT 0;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS gpu_memory_requested VARCHAR(50) NOT NULL DEFAULT '0Mi';
-- Add index for instance workspace
CREATE INDEX IF NOT EXISTS idx_instances_workspace_id ON instances(workspace_id);
-- ===== Phase 2: Create new tables =====
-- Create workspaces table
CREATE TABLE IF NOT EXISTS workspaces (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
created_by VARCHAR(36),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_workspaces_name ON workspaces(name);
-- Create workspace_quotas table
CREATE TABLE IF NOT EXISTS workspace_quotas (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36) NOT NULL,
resource_type VARCHAR(50) NOT NULL,
hard_limit DECIMAL(10,2) NOT NULL,
soft_limit DECIMAL(10,2) NOT NULL,
used DECIMAL(10,2) NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(workspace_id, resource_type),
CONSTRAINT fk_workspace_quotas_workspace FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_workspace_quotas_workspace_id ON workspace_quotas(workspace_id);
-- Create storage_backends table
CREATE TABLE IF NOT EXISTS storage_backends (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36),
owner_id VARCHAR(36),
name VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL,
config JSONB NOT NULL,
description TEXT,
is_default BOOLEAN NOT NULL DEFAULT FALSE,
is_shared BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(workspace_id, name)
);
CREATE INDEX IF NOT EXISTS idx_storage_backends_workspace_id ON storage_backends(workspace_id);
-- Create chart_references table
CREATE TABLE IF NOT EXISTS chart_references (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36),
registry_id VARCHAR(36),
repository VARCHAR(500) NOT NULL,
chart_name VARCHAR(255) NOT NULL,
description TEXT,
is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(workspace_id, registry_id, repository)
);
CREATE INDEX IF NOT EXISTS idx_chart_references_workspace_id ON chart_references(workspace_id);
CREATE INDEX IF NOT EXISTS idx_chart_references_registry_id ON chart_references(registry_id);
-- Create values_templates table
CREATE TABLE IF NOT EXISTS values_templates (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36),
owner_id VARCHAR(36),
chart_reference_id VARCHAR(36),
name VARCHAR(255) NOT NULL,
description TEXT,
values_yaml TEXT NOT NULL,
version INTEGER NOT NULL DEFAULT 1,
is_default BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(workspace_id, chart_reference_id, name)
);
CREATE INDEX IF NOT EXISTS idx_values_templates_workspace_id ON values_templates(workspace_id);
CREATE INDEX IF NOT EXISTS idx_values_templates_chart_reference_id ON values_templates(chart_reference_id);
-- Create user_config_overrides table
CREATE TABLE IF NOT EXISTS user_config_overrides (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36),
user_id VARCHAR(36),
target_type VARCHAR(50) NOT NULL,
target_id VARCHAR(36),
config JSONB NOT NULL,
priority INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_user_config_overrides_workspace_id ON user_config_overrides(workspace_id);
CREATE INDEX IF NOT EXISTS idx_user_config_overrides_user_id ON user_config_overrides(user_id);
-- Create audit_logs table
CREATE TABLE IF NOT EXISTS audit_logs (
id VARCHAR(36) PRIMARY KEY,
workspace_id VARCHAR(36),
user_id VARCHAR(36),
action VARCHAR(100) NOT NULL,
resource_type VARCHAR(50) NOT NULL,
resource_id VARCHAR(36),
resource_name VARCHAR(255),
details JSONB,
ip_address VARCHAR(50),
user_agent TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_audit_logs_workspace_id ON audit_logs(workspace_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_user_id ON audit_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_created_at ON audit_logs(created_at);
-- ===== Phase 3: Create admin user =====
-- Note: Default password is 'admin123' (bcrypt hash will be set by application)
-- The admin user will have NULL workspace_id to indicate global access
INSERT INTO users (id, username, password_hash, email, role, workspace_id, is_active, must_change_password)
VALUES (
'00000000-0000-0000-0000-000000000001',
'admin',
'$2a$10$placeholder', -- Replace with actual bcrypt hash in production
'admin@ocdp.local',
'admin',
NULL,
TRUE,
TRUE
) ON CONFLICT (username) DO NOTHING;
-- Update schema version
INSERT INTO schema_migrations (version) VALUES ('v2.0.0-multi-tenant')
ON CONFLICT (version) DO NOTHING;
-- Grant permissions (adjust as needed for your setup)
-- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ocdp_user;
-- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ocdp_user;