software steht so weit.
jetzt build + docker build und testen
This commit is contained in:
1 parent
42f0c0accb
commit
ca6cdcca63
90 files changed
+10298
-480
No files matched your search
@@ -0,0 +1,101 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Lease ist die aktuelle Lease eines Knotens. Document ist das signierte
|
||||
// JSON (license.Lease); die Zeiten liegen zusätzlich als Spalten vor, damit
|
||||
// der Server ohne Parsen entscheiden kann.
|
||||
type Lease struct {
|
||||
NodeID string
|
||||
IssuedAt time.Time
|
||||
RenewAfter time.Time
|
||||
ValidUntil time.Time
|
||||
Document string
|
||||
}
|
||||
|
||||
// PutLease speichert bzw. ersetzt die Lease eines Knotens.
|
||||
func (s *Store) PutLease(ctx context.Context, l Lease) error {
|
||||
_, err := s.db.ExecContext(ctx, `INSERT INTO leases (node_id, issued_at, renew_after, valid_until, document)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT(node_id) DO UPDATE SET issued_at = excluded.issued_at, renew_after = excluded.renew_after,
|
||||
valid_until = excluded.valid_until, document = excluded.document`,
|
||||
l.NodeID, formatTime(l.IssuedAt), formatTime(l.RenewAfter), formatTime(l.ValidUntil), l.Document)
|
||||
if sqliteCode(err) != 0 {
|
||||
return fmt.Errorf("Lease für %s: Knoten: %w", l.NodeID, ErrNotFound)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetLease liest die Lease eines Knotens.
|
||||
func (s *Store) GetLease(ctx context.Context, nodeID string) (Lease, error) {
|
||||
l := Lease{NodeID: nodeID}
|
||||
err := s.db.QueryRowContext(ctx, `SELECT issued_at, renew_after, valid_until, document FROM leases WHERE node_id = ?`, nodeID).
|
||||
Scan(dbTime{&l.IssuedAt}, dbTime{&l.RenewAfter}, dbTime{&l.ValidUntil}, &l.Document)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return Lease{}, fmt.Errorf("Lease für %s: %w", nodeID, ErrNotFound)
|
||||
}
|
||||
return l, err
|
||||
}
|
||||
|
||||
// NodeCommand ist ein Befehl in der Warteschlange für einen Knoten. Die CLI
|
||||
// (eigener Prozess) reiht ein, der Server stellt zu.
|
||||
type NodeCommand struct {
|
||||
ID int64
|
||||
NodeID string
|
||||
Command string
|
||||
Reason string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// EnqueueNodeCommand reiht einen Befehl für nodeID ein.
|
||||
func (s *Store) EnqueueNodeCommand(ctx context.Context, nodeID, command, reason string) error {
|
||||
if blank(command) {
|
||||
return invalid("Befehl fehlt")
|
||||
}
|
||||
_, err := s.db.ExecContext(ctx, `INSERT INTO node_commands (node_id, command, reason, created_at) VALUES (?, ?, ?, ?)`,
|
||||
nodeID, command, reason, formatTime(s.now()))
|
||||
return mapConstraint(err, "Befehl für "+nodeID)
|
||||
}
|
||||
|
||||
// PendingNodeCommands liefert die noch nicht zugestellten Befehle in Reihenfolge.
|
||||
func (s *Store) PendingNodeCommands(ctx context.Context, nodeID string) ([]NodeCommand, error) {
|
||||
rows, err := s.db.QueryContext(ctx, `SELECT id, command, reason, created_at FROM node_commands
|
||||
WHERE node_id = ? AND sent_at IS NULL ORDER BY id`, nodeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []NodeCommand
|
||||
for rows.Next() {
|
||||
c := NodeCommand{NodeID: nodeID}
|
||||
if err := rows.Scan(&c.ID, &c.Command, &c.Reason, dbTime{&c.CreatedAt}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, c)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// MarkNodeCommandSent vermerkt die Zustellung.
|
||||
func (s *Store) MarkNodeCommandSent(ctx context.Context, id int64) error {
|
||||
res, err := s.db.ExecContext(ctx, `UPDATE node_commands SET sent_at = ? WHERE id = ?`, formatTime(s.now()), id)
|
||||
return requireAffected(res, err, fmt.Sprintf("Befehl %d", id))
|
||||
}
|
||||
|
||||
// UpdateNodePublicKey tauscht den Schlüssel eines Knotens (rotate_key).
|
||||
func (s *Store) UpdateNodePublicKey(ctx context.Context, nodeID, publicKey string) error {
|
||||
if blank(publicKey) {
|
||||
return invalid("Public Key fehlt")
|
||||
}
|
||||
res, err := s.db.ExecContext(ctx, `UPDATE nodes SET public_key = ? WHERE id = ?`, publicKey, nodeID)
|
||||
if err != nil {
|
||||
return mapConstraint(err, "Knoten "+nodeID)
|
||||
}
|
||||
return requireAffected(res, nil, "Knoten "+nodeID)
|
||||
}
|
||||
Reference in new issue
Block a user