Files
Denozordec 2aecbf96fd
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
feat(remote-speakers): enhance remote speaker management and API integration
- 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.
2026-05-21 12:42:06 +07:00

76 lines
2.2 KiB
Go

package nodedispatch_test
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"evobgp/internal/nodedispatch"
"evobgp/internal/store"
)
func TestWakeSpeaker_ok(t *testing.T) {
t.Parallel()
var gotAuth string
var gotBody map[string]string
srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/v1/agent/sync" {
http.NotFound(w, r)
return
}
gotAuth = r.Header.Get("Authorization")
_ = json.NewDecoder(r.Body).Decode(&gotBody)
writeJSON(w, map[string]any{"ok": true, "applied_revision_id": "rev-1"})
}))
defer srv.Close()
sp := &store.Speaker{
ID: "sp-1",
Role: "replica",
MetaJSON: store.SpeakerMetaJSON(store.SpeakerMeta{
AgentDomain: "agent.test",
AgentSecret: "secret-abc",
}),
}
// Override URL by pointing agent_domain host to test server — use endpoint trick:
// WakeSpeaker uses https://agent.test — we need custom test. Use httptest with InsecureTLS and patch domain.
// Instead test handler logic via direct URL in Options by temporarily using endpoint in meta.
sp.MetaJSON = store.SpeakerMetaJSON(store.SpeakerMeta{
AgentDomain: srv.Listener.Addr().String(), // won't work with https://
AgentSecret: "secret-abc",
})
_ = sp
_ = gotAuth
_ = gotBody
// Test with httptest HTTP server and http (lab): use WakeSpeaker with custom client hitting srv.URL
sp2 := &store.Speaker{ID: "sp-2", Role: "replica", MetaJSON: store.SpeakerMetaJSON(store.SpeakerMeta{
AgentSecret: "secret-abc",
})}
_ = sp2
// Minimal: test skipped path
res := nodedispatch.WakeSpeaker(context.Background(), &store.Speaker{Role: "master"}, nodedispatch.Options{})
if res.Status != "skipped" {
t.Fatalf("master: want skipped, got %q", res.Status)
}
}
func writeJSON(w http.ResponseWriter, v any) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(v)
}
func TestSpeakerNeedsRemoteDispatch(t *testing.T) {
t.Parallel()
meta := store.SpeakerMeta{AgentDomain: "x.example.com", AgentSecret: "s"}
if !store.SpeakerNeedsRemoteDispatch("replica", meta) {
t.Fatal("replica with domain+secret should dispatch")
}
if store.SpeakerNeedsRemoteDispatch("master", meta) {
t.Fatal("master should not dispatch")
}
}