feat: enhance EvoBGP with new command-line options for the evobgp-agent, including a watch command for periodic configuration updates. Update go.mod with additional dependencies and improve Docker Compose setup for new services, including NATS and various worker components.
CI / changes (push) Successful in 5s
CI / go (push) Successful in 1m40s
CI / openapi (push) Has been skipped
CI / bird2 (push) Successful in 17s

This commit is contained in:
Denozordec
2026-04-05 17:03:21 +07:00
parent bf52b21150
commit 6a55f72ab3
35 changed files with 4609 additions and 193 deletions
+49 -6
View File
@@ -1,6 +1,12 @@
package jobs
import (
"context"
"os"
"strings"
"evobgp/internal/birddeploy"
"evobgp/internal/birdfmt"
"evobgp/internal/observability"
"evobgp/internal/store"
)
@@ -12,9 +18,9 @@ const (
KindBirdReload = "bird_reload"
)
// Worker executes queued jobs against an in-memory store (stub for full render/deploy pipeline).
// Worker executes queued jobs against store.Backend (memory or SQL).
type Worker struct {
Store *store.Memory
Store store.Backend
}
// Process is registered as Registry.workerStart.
@@ -42,6 +48,19 @@ func (w *Worker) Process(j *Job) {
case KindRevisionRollback:
w.runRollback(j)
case KindBirdReload:
sock := strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_SOCKET"))
if sock == "" {
j.Succeed()
return
}
ctl := &birdfmt.BirdCtl{
Socket: sock,
Birdc: strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_BIN")),
}
if err := ctl.Configure(context.Background()); err != nil {
j.Fail(err.Error())
return
}
j.Succeed()
default:
j.Fail("unknown job kind")
@@ -49,18 +68,42 @@ func (w *Worker) Process(j *Job) {
}
func (w *Worker) runDeployApply(j *Job) {
rev, _ := j.Meta["revision_id"].(string)
revID, _ := j.Meta["revision_id"].(string)
spk, hasSpeaker := j.Meta["speaker_id"].(string)
if rev == "" {
if revID == "" {
j.Fail("missing revision_id in job meta")
return
}
activeDir := strings.TrimSpace(os.Getenv("EVOBGP_BIRD_ACTIVE_DIR"))
if activeDir != "" {
revObj, err := w.Store.GetRevision(j.TenantID, revID)
if err != nil {
j.Fail(err.Error())
return
}
staging := strings.TrimSpace(os.Getenv("EVOBGP_BIRD_STAGING_DIR"))
if staging == "" {
staging = os.TempDir() + "/evobgp-bird-staging"
}
cfg := birddeploy.Config{
ActiveDir: activeDir,
StagingDir: staging,
BirdBin: strings.TrimSpace(os.Getenv("EVOBGP_BIRD_BIN")),
BirdcBin: strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_BIN")),
Socket: strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_SOCKET")),
}
ctl := &birdfmt.BirdCtl{Bird: cfg.BirdBin, Birdc: cfg.BirdcBin, Socket: cfg.Socket}
if err := birddeploy.ApplyRevision(context.Background(), ctl, revObj, cfg); err != nil {
j.Fail(err.Error())
return
}
}
applyOne := func(speakerID string) error {
if err := w.Store.SetLastAppliedRevision(j.TenantID, speakerID, rev); err != nil {
if err := w.Store.SetLastAppliedRevision(j.TenantID, speakerID, revID); err != nil {
return err
}
// Replica / node pulls use LatestPublishedRevision; keep pointer in sync with successful deploy.
if err := w.Store.PublishRevisionForSpeaker(speakerID, rev); err != nil {
if err := w.Store.PublishRevisionForSpeaker(speakerID, revID); err != nil {
return err
}
return nil