136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package postgres
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
// DB 数据库连接包装器
|
|
type DB struct {
|
|
conn *sql.DB
|
|
}
|
|
|
|
// NewDB 创建新的数据库连接
|
|
func NewDB(connString string) (*DB, error) {
|
|
if connString == "" {
|
|
return nil, fmt.Errorf("database connection string cannot be empty")
|
|
}
|
|
|
|
conn, err := sql.Open("postgres", connString)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to open database: %w", err)
|
|
}
|
|
|
|
// 配置连接池
|
|
conn.SetMaxOpenConns(25)
|
|
conn.SetMaxIdleConns(5)
|
|
conn.SetConnMaxLifetime(5 * time.Minute)
|
|
|
|
// 测试连接
|
|
if err := conn.Ping(); err != nil {
|
|
return nil, fmt.Errorf("failed to ping database: %w", err)
|
|
}
|
|
|
|
return &DB{conn: conn}, nil
|
|
}
|
|
|
|
// Close 关闭数据库连接
|
|
func (db *DB) Close() error {
|
|
if db.conn != nil {
|
|
return db.conn.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetConn 获取底层连接(用于事务等高级操作)
|
|
func (db *DB) GetConn() *sql.DB {
|
|
return db.conn
|
|
}
|
|
|
|
// InitSchema 初始化数据库 schema
|
|
func (db *DB) InitSchema() error {
|
|
schema := `
|
|
-- Users 表
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
username VARCHAR(255) NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
email VARCHAR(255) NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
|
|
-- Clusters 表
|
|
CREATE TABLE IF NOT EXISTS clusters (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL UNIQUE,
|
|
host TEXT NOT NULL,
|
|
ca_data TEXT,
|
|
cert_data TEXT,
|
|
key_data TEXT,
|
|
token TEXT,
|
|
description TEXT,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_clusters_name ON clusters(name);
|
|
|
|
-- Registries 表
|
|
CREATE TABLE IF NOT EXISTS registries (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL UNIQUE,
|
|
url TEXT NOT NULL,
|
|
description TEXT,
|
|
username VARCHAR(255),
|
|
password TEXT,
|
|
insecure BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_registries_name ON registries(name);
|
|
|
|
-- Instances 表
|
|
CREATE TABLE IF NOT EXISTS instances (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
cluster_id VARCHAR(36) NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
namespace VARCHAR(255) NOT NULL,
|
|
registry_id VARCHAR(36) NOT NULL,
|
|
repository TEXT NOT NULL,
|
|
chart VARCHAR(255) NOT NULL,
|
|
version VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
values JSONB,
|
|
values_yaml TEXT,
|
|
status VARCHAR(50) NOT NULL,
|
|
status_reason TEXT,
|
|
last_operation VARCHAR(50),
|
|
last_error TEXT,
|
|
revision INTEGER NOT NULL DEFAULT 1,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT fk_cluster FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_registry FOREIGN KEY (registry_id) REFERENCES registries(id) ON DELETE CASCADE,
|
|
CONSTRAINT unique_cluster_name UNIQUE (cluster_id, name, namespace)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_instances_cluster ON instances(cluster_id);
|
|
CREATE INDEX IF NOT EXISTS idx_instances_registry ON instances(registry_id);
|
|
CREATE INDEX IF NOT EXISTS idx_instances_name ON instances(name);
|
|
`
|
|
|
|
_, err := db.conn.Exec(schema)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to initialize schema: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|