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:
190
backend/scripts/migration_multi_tenant.sql
Normal file
190
backend/scripts/migration_multi_tenant.sql
Normal 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;
|
||||
Reference in New Issue
Block a user