panel public release
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// InstanceForwardRow is one panel-owned port forward in opnfwd. Composite
|
||||
// key (instance_id, port_name) — the panel allocates one forward per
|
||||
// manifest port per instance.
|
||||
type InstanceForwardRow struct {
|
||||
InstanceID string
|
||||
PortName string
|
||||
NatUUID string
|
||||
FilterUUID string
|
||||
TargetIP string
|
||||
HostPort int32
|
||||
Proto string // "tcp" | "udp" | "tcp/udp"
|
||||
Descr string // "panel-<instance>-<port_name>" — matches the OPNsense rule's <descr>
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// UpsertInstanceForward persists a single forward, replacing any prior row
|
||||
// for the same (instance, port_name). The replace is intentional — if the
|
||||
// panel re-creates a forward for an existing port (e.g. operator clicked
|
||||
// Reconcile and we recreated), the new uuids supersede the old.
|
||||
func (db *DB) UpsertInstanceForward(ctx context.Context, r InstanceForwardRow) error {
|
||||
_, err := db.pool.Exec(ctx, `
|
||||
INSERT INTO instance_forwards (instance_id, port_name, nat_uuid, filter_uuid, target_ip, host_port, proto, descr)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
ON CONFLICT (instance_id, port_name) DO UPDATE SET
|
||||
nat_uuid = EXCLUDED.nat_uuid,
|
||||
filter_uuid = EXCLUDED.filter_uuid,
|
||||
target_ip = EXCLUDED.target_ip,
|
||||
host_port = EXCLUDED.host_port,
|
||||
proto = EXCLUDED.proto,
|
||||
descr = EXCLUDED.descr
|
||||
`, r.InstanceID, r.PortName, r.NatUUID, r.FilterUUID, r.TargetIP, r.HostPort, r.Proto, r.Descr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("upsert instance_forward: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListInstanceForwards returns every forward for the given instance, used
|
||||
// at delete time + by the instance-modal "Forwards" pill.
|
||||
func (db *DB) ListInstanceForwards(ctx context.Context, instanceID string) ([]InstanceForwardRow, error) {
|
||||
rows, err := db.pool.Query(ctx, `
|
||||
SELECT instance_id, port_name, nat_uuid, filter_uuid, target_ip, host_port, proto, descr, created_at
|
||||
FROM instance_forwards
|
||||
WHERE instance_id = $1
|
||||
ORDER BY port_name
|
||||
`, instanceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list instance_forwards: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []InstanceForwardRow
|
||||
for rows.Next() {
|
||||
var r InstanceForwardRow
|
||||
if err := rows.Scan(&r.InstanceID, &r.PortName, &r.NatUUID, &r.FilterUUID,
|
||||
&r.TargetIP, &r.HostPort, &r.Proto, &r.Descr, &r.CreatedAt); err != nil {
|
||||
return nil, fmt.Errorf("scan instance_forward: %w", err)
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// ListAllInstanceForwards is for the reconcile path — compare every
|
||||
// panel-tracked forward against opnfwd's view of the world.
|
||||
func (db *DB) ListAllInstanceForwards(ctx context.Context) ([]InstanceForwardRow, error) {
|
||||
rows, err := db.pool.Query(ctx, `
|
||||
SELECT instance_id, port_name, nat_uuid, filter_uuid, target_ip, host_port, proto, descr, created_at
|
||||
FROM instance_forwards
|
||||
ORDER BY instance_id, port_name
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list all instance_forwards: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []InstanceForwardRow
|
||||
for rows.Next() {
|
||||
var r InstanceForwardRow
|
||||
if err := rows.Scan(&r.InstanceID, &r.PortName, &r.NatUUID, &r.FilterUUID,
|
||||
&r.TargetIP, &r.HostPort, &r.Proto, &r.Descr, &r.CreatedAt); err != nil {
|
||||
return nil, fmt.Errorf("scan instance_forward: %w", err)
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// DeleteInstanceForwards removes every panel-tracked forward for an
|
||||
// instance. Called from the delete path AFTER opnfwd's bulk-delete
|
||||
// returned successfully — this just drops the local mirror.
|
||||
func (db *DB) DeleteInstanceForwards(ctx context.Context, instanceID string) error {
|
||||
_, err := db.pool.Exec(ctx, `DELETE FROM instance_forwards WHERE instance_id = $1`, instanceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete instance_forwards: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user