feat(remote-speakers): enhance remote speaker management and API integration
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Failing after 34s
CI / go (push) Failing after 19s
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped

- Added support for remote speaker configuration in the README and documentation.
- Implemented a new endpoint for retrieving the bundle signing public key.
- Updated the `evobgp-agent` to include a `serve` command for Panel→Node sync API.
- Enhanced CI workflow to validate remote speaker compose files.
- Introduced new fields in the API and UI for managing speaker metadata, including dispatch status and sync status.
- Improved error handling and response formatting in speaker-related API endpoints.
- Updated documentation to reflect changes in remote speaker functionality and usage guidelines.
This commit is contained in:
Denozordec
2026-05-21 12:42:06 +07:00
parent ec65249bf1
commit 2aecbf96fd
29 changed files with 2003 additions and 63 deletions
+53 -9
View File
@@ -6,8 +6,10 @@ import (
"fmt"
"log"
"os"
"sync"
"time"
"evobgp/internal/agentserver"
"evobgp/internal/birdfmt"
)
@@ -17,12 +19,14 @@ func main() {
socket := flag.String("socket", "", "optional birdc control socket (-s)")
timeout := flag.Duration("timeout", 30*time.Second, "timeout for bird/birdc")
watchEvery := flag.Duration("watch-interval", 30*time.Second, "for watch: interval between birdc configure")
listen := flag.String("listen", "", "for serve: listen address (default :8443 or EVOBGP_AGENT_LISTEN)")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [flags] <command>\n", os.Args[0])
fmt.Fprintf(os.Stderr, "Commands:\n")
fmt.Fprintf(os.Stderr, " parse-check <path/to/bird.conf> run bird -c <path> -p (syntax check)\n")
fmt.Fprintf(os.Stderr, " configure run birdc configure (reload running BIRD)\n")
fmt.Fprintf(os.Stderr, " watch periodically run birdc configure (compose sidecar)\n")
fmt.Fprintf(os.Stderr, " serve Panel→Node HTTP API (POST /v1/agent/sync)\n")
flag.PrintDefaults()
}
flag.Parse()
@@ -40,9 +44,21 @@ func main() {
ctl.Birdc = *birdc
}
ctx, cancel := context.WithTimeout(context.Background(), *timeout)
defer cancel()
switch args[0] {
case "serve":
runServe(*listen, *timeout)
case "parse-check", "configure", "watch":
ctx, cancel := context.WithTimeout(context.Background(), *timeout)
defer cancel()
runBirdCommand(ctx, args, ctl, *watchEvery, *timeout)
default:
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
flag.Usage()
os.Exit(2)
}
}
func runBirdCommand(ctx context.Context, args []string, ctl *birdfmt.BirdCtl, watchEvery, timeout time.Duration) {
switch args[0] {
case "parse-check":
if len(args) != 2 {
@@ -63,23 +79,51 @@ func main() {
os.Exit(1)
}
case "watch":
if *watchEvery <= 0 {
if watchEvery <= 0 {
fmt.Fprintln(os.Stderr, "watch-interval must be > 0")
os.Exit(2)
}
log.Printf("evobgp-agent watch: birdc configure every %s (socket=%q)", *watchEvery, *socket)
log.Printf("evobgp-agent watch: birdc configure every %s (socket=%q)", watchEvery, ctl.Socket)
for {
cctx, cancel := context.WithTimeout(context.Background(), *timeout)
cctx, cancel := context.WithTimeout(context.Background(), timeout)
err := ctl.Configure(cctx)
cancel()
if err != nil {
log.Printf("evobgp-agent watch: configure: %v", err)
}
time.Sleep(*watchEvery)
time.Sleep(watchEvery)
}
default:
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
flag.Usage()
}
}
func runServe(listenFlag string, syncTimeout time.Duration) {
cfg, err := agentserver.ConfigFromEnv()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
if listenFlag != "" {
cfg.Listen = listenFlag
}
if syncTimeout > 0 {
cfg.SyncTimeout = syncTimeout
}
var mu sync.Mutex
var lastRev string
var lastAt time.Time
cfg.LastSync = func() (string, time.Time) {
mu.Lock()
defer mu.Unlock()
return lastRev, lastAt
}
cfg.OnSyncSuccess = func(rev string) {
mu.Lock()
lastRev = rev
lastAt = time.Now().UTC()
mu.Unlock()
}
if err := agentserver.ListenAndServe(cfg); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}