161 lines
5.0 KiB
Go
161 lines
5.0 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
func Open(path string) (*sql.DB, error) {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
database, err := sql.Open("sqlite", path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
database.SetMaxOpenConns(1)
|
|
database.SetConnMaxLifetime(30 * time.Minute)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
if err := database.PingContext(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := migrate(ctx, database); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return database, nil
|
|
}
|
|
|
|
func migrate(ctx context.Context, database *sql.DB) error {
|
|
statements := []string{
|
|
`PRAGMA foreign_keys = ON;`,
|
|
`CREATE TABLE IF NOT EXISTS organizations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
theme TEXT NOT NULL DEFAULT 'emerald',
|
|
theme_mode TEXT NOT NULL DEFAULT 'dark',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);`,
|
|
`CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
organization_id INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
email TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
role TEXT NOT NULL,
|
|
otp_secret TEXT NOT NULL,
|
|
otp_enabled BOOLEAN NOT NULL DEFAULT 0,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (organization_id) REFERENCES organizations(id)
|
|
);`,
|
|
`CREATE TABLE IF NOT EXISTS vm_groups (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
organization_id INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
color_token TEXT NOT NULL DEFAULT 'primary',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (organization_id) REFERENCES organizations(id)
|
|
);`,
|
|
`CREATE TABLE IF NOT EXISTS nodes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
organization_id INTEGER NOT NULL,
|
|
group_id INTEGER,
|
|
tag TEXT NOT NULL DEFAULT '',
|
|
name TEXT NOT NULL,
|
|
distro TEXT NOT NULL,
|
|
hostname TEXT NOT NULL,
|
|
ip_address TEXT NOT NULL,
|
|
mac_address TEXT NOT NULL DEFAULT '',
|
|
ssh_port INTEGER NOT NULL DEFAULT 22,
|
|
ssh_username TEXT NOT NULL DEFAULT '',
|
|
ssh_password TEXT NOT NULL DEFAULT '',
|
|
package_manager TEXT NOT NULL DEFAULT '',
|
|
architecture TEXT NOT NULL DEFAULT '',
|
|
kernel_version TEXT NOT NULL DEFAULT '',
|
|
cpu_model TEXT NOT NULL DEFAULT '',
|
|
memory_total_mb INTEGER NOT NULL DEFAULT 0,
|
|
disk_total_gb INTEGER NOT NULL DEFAULT 0,
|
|
cpu_usage REAL NOT NULL DEFAULT 0,
|
|
ram_usage REAL NOT NULL DEFAULT 0,
|
|
disk_usage REAL NOT NULL DEFAULT 0,
|
|
uptime_seconds INTEGER NOT NULL DEFAULT 0,
|
|
last_seen_at DATETIME,
|
|
auto_updates_enabled BOOLEAN NOT NULL DEFAULT 0,
|
|
notes TEXT NOT NULL DEFAULT '',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (organization_id) REFERENCES organizations(id),
|
|
FOREIGN KEY (group_id) REFERENCES vm_groups(id)
|
|
);`,
|
|
`CREATE TABLE IF NOT EXISTS automation_jobs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
organization_id INTEGER NOT NULL,
|
|
node_id INTEGER,
|
|
group_id INTEGER,
|
|
tag TEXT NOT NULL DEFAULT '',
|
|
name TEXT NOT NULL,
|
|
trigger_type TEXT NOT NULL,
|
|
schedule TEXT NOT NULL DEFAULT '',
|
|
command TEXT NOT NULL,
|
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
|
last_run_at DATETIME,
|
|
next_run_at DATETIME,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (organization_id) REFERENCES organizations(id),
|
|
FOREIGN KEY (node_id) REFERENCES nodes(id),
|
|
FOREIGN KEY (group_id) REFERENCES vm_groups(id)
|
|
);`,
|
|
`CREATE TABLE IF NOT EXISTS command_runs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
job_id INTEGER,
|
|
node_id INTEGER NOT NULL,
|
|
action TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
output TEXT NOT NULL DEFAULT '',
|
|
triggered_by INTEGER,
|
|
started_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
finished_at DATETIME,
|
|
FOREIGN KEY (job_id) REFERENCES automation_jobs(id),
|
|
FOREIGN KEY (node_id) REFERENCES nodes(id),
|
|
FOREIGN KEY (triggered_by) REFERENCES users(id)
|
|
);`,
|
|
}
|
|
|
|
for _, statement := range statements {
|
|
if _, err := database.ExecContext(ctx, statement); err != nil {
|
|
return fmt.Errorf("migrate: %w", err)
|
|
}
|
|
}
|
|
|
|
alterStatements := []string{
|
|
`ALTER TABLE organizations ADD COLUMN theme_mode TEXT NOT NULL DEFAULT 'dark';`,
|
|
`ALTER TABLE nodes ADD COLUMN tag TEXT NOT NULL DEFAULT '';`,
|
|
`ALTER TABLE nodes ADD COLUMN package_manager TEXT NOT NULL DEFAULT '';`,
|
|
`ALTER TABLE nodes ADD COLUMN architecture TEXT NOT NULL DEFAULT '';`,
|
|
`ALTER TABLE nodes ADD COLUMN kernel_version TEXT NOT NULL DEFAULT '';`,
|
|
`ALTER TABLE nodes ADD COLUMN cpu_model TEXT NOT NULL DEFAULT '';`,
|
|
`ALTER TABLE nodes ADD COLUMN memory_total_mb INTEGER NOT NULL DEFAULT 0;`,
|
|
`ALTER TABLE nodes ADD COLUMN disk_total_gb INTEGER NOT NULL DEFAULT 0;`,
|
|
`ALTER TABLE automation_jobs ADD COLUMN tag TEXT NOT NULL DEFAULT '';`,
|
|
}
|
|
|
|
for _, statement := range alterStatements {
|
|
_, _ = database.ExecContext(ctx, statement)
|
|
}
|
|
|
|
return nil
|
|
}
|