9bb4b09a04
CI / Lint + build + test (push) Has been cancelled
Post-repair hardware validation pipeline for Proxmox cluster hosts. Go orchestrator + in-image agent + mkosi live image + bundled dnsmasq PXE + SQLite + HTMX/SSE UI + notify registry + janitor + full docs.
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"vetting/internal/model"
|
|
)
|
|
|
|
type Hosts struct {
|
|
DB *sql.DB
|
|
}
|
|
|
|
var ErrNotFound = errors.New("not found")
|
|
|
|
func (h *Hosts) Create(ctx context.Context, in model.Host) (int64, error) {
|
|
in.MAC = normalizeMAC(in.MAC)
|
|
res, err := h.DB.ExecContext(ctx, `
|
|
INSERT INTO hosts(name, mac, wol_broadcast_ip, wol_port, expected_spec_yaml, pdu_config_json, ipmi_config_json, notes)
|
|
VALUES(?,?,?,?,?,?,?,?)
|
|
`, in.Name, in.MAC, in.WoLBroadcastIP, in.WoLPort, in.ExpectedSpecYAML, nullIfEmpty(in.PDUConfigJSON), nullIfEmpty(in.IPMIConfigJSON), in.Notes)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("insert host: %w", err)
|
|
}
|
|
return res.LastInsertId()
|
|
}
|
|
|
|
func (h *Hosts) List(ctx context.Context) ([]model.Host, error) {
|
|
rows, err := h.DB.QueryContext(ctx, `
|
|
SELECT id, name, mac, wol_broadcast_ip, wol_port, expected_spec_yaml,
|
|
COALESCE(pdu_config_json,''), COALESCE(ipmi_config_json,''),
|
|
notes, created_at, updated_at
|
|
FROM hosts
|
|
ORDER BY name COLLATE NOCASE
|
|
`)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list hosts: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var out []model.Host
|
|
for rows.Next() {
|
|
var host model.Host
|
|
if err := rows.Scan(&host.ID, &host.Name, &host.MAC, &host.WoLBroadcastIP, &host.WoLPort,
|
|
&host.ExpectedSpecYAML, &host.PDUConfigJSON, &host.IPMIConfigJSON,
|
|
&host.Notes, &host.CreatedAt, &host.UpdatedAt); err != nil {
|
|
return nil, fmt.Errorf("scan host: %w", err)
|
|
}
|
|
out = append(out, host)
|
|
}
|
|
return out, rows.Err()
|
|
}
|
|
|
|
func (h *Hosts) Get(ctx context.Context, id int64) (*model.Host, error) {
|
|
row := h.DB.QueryRowContext(ctx, `
|
|
SELECT id, name, mac, wol_broadcast_ip, wol_port, expected_spec_yaml,
|
|
COALESCE(pdu_config_json,''), COALESCE(ipmi_config_json,''),
|
|
notes, created_at, updated_at
|
|
FROM hosts WHERE id = ?
|
|
`, id)
|
|
var host model.Host
|
|
err := row.Scan(&host.ID, &host.Name, &host.MAC, &host.WoLBroadcastIP, &host.WoLPort,
|
|
&host.ExpectedSpecYAML, &host.PDUConfigJSON, &host.IPMIConfigJSON,
|
|
&host.Notes, &host.CreatedAt, &host.UpdatedAt)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrNotFound
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get host: %w", err)
|
|
}
|
|
return &host, nil
|
|
}
|
|
|
|
func (h *Hosts) Delete(ctx context.Context, id int64) error {
|
|
res, err := h.DB.ExecContext(ctx, `DELETE FROM hosts WHERE id = ?`, id)
|
|
if err != nil {
|
|
return fmt.Errorf("delete host: %w", err)
|
|
}
|
|
n, _ := res.RowsAffected()
|
|
if n == 0 {
|
|
return ErrNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func normalizeMAC(m string) string {
|
|
return strings.ToLower(strings.TrimSpace(m))
|
|
}
|
|
|
|
func nullIfEmpty(s string) any {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
return s
|
|
}
|