Accept endpoint health from mesh config
This commit is contained in:
@@ -9,18 +9,19 @@ import (
|
||||
)
|
||||
|
||||
type ScopedSyntheticConfig struct {
|
||||
SchemaVersion string `json:"schema_version"`
|
||||
ClusterID string `json:"cluster_id"`
|
||||
LocalNodeID string `json:"local_node_id"`
|
||||
ConfigVersion string `json:"config_version,omitempty"`
|
||||
PeerDirectoryVersion string `json:"peer_directory_version,omitempty"`
|
||||
PolicyVersion string `json:"policy_version,omitempty"`
|
||||
PeerEndpoints map[string]string `json:"peer_endpoints"`
|
||||
PeerEndpointCandidates map[string][]PeerEndpointCandidate `json:"peer_endpoint_candidates,omitempty"`
|
||||
PeerDirectory []PeerDirectoryEntry `json:"peer_directory,omitempty"`
|
||||
RecoverySeeds []PeerRecoverySeed `json:"recovery_seeds,omitempty"`
|
||||
RendezvousLeases []PeerRendezvousLease `json:"rendezvous_leases,omitempty"`
|
||||
Routes []SyntheticRoute `json:"routes"`
|
||||
SchemaVersion string `json:"schema_version"`
|
||||
ClusterID string `json:"cluster_id"`
|
||||
LocalNodeID string `json:"local_node_id"`
|
||||
ConfigVersion string `json:"config_version,omitempty"`
|
||||
PeerDirectoryVersion string `json:"peer_directory_version,omitempty"`
|
||||
PolicyVersion string `json:"policy_version,omitempty"`
|
||||
PeerEndpoints map[string]string `json:"peer_endpoints"`
|
||||
PeerEndpointCandidates map[string][]PeerEndpointCandidate `json:"peer_endpoint_candidates,omitempty"`
|
||||
PeerEndpointObservations map[string]EndpointCandidateHealthObservation `json:"peer_endpoint_observations,omitempty"`
|
||||
PeerDirectory []PeerDirectoryEntry `json:"peer_directory,omitempty"`
|
||||
RecoverySeeds []PeerRecoverySeed `json:"recovery_seeds,omitempty"`
|
||||
RendezvousLeases []PeerRendezvousLease `json:"rendezvous_leases,omitempty"`
|
||||
Routes []SyntheticRoute `json:"routes"`
|
||||
}
|
||||
|
||||
type PeerDirectoryEntry struct {
|
||||
@@ -122,6 +123,14 @@ func (cfg ScopedSyntheticConfig) Validate(local PeerIdentity) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
for endpointID, observation := range cfg.PeerEndpointObservations {
|
||||
if strings.TrimSpace(endpointID) == "" || strings.TrimSpace(observation.EndpointID) == "" || observation.EndpointID != endpointID {
|
||||
return fmt.Errorf("scoped synthetic mesh config contains invalid peer endpoint observation")
|
||||
}
|
||||
if observation.ReliabilityScore < 0 || observation.ReliabilityScore > 100 {
|
||||
return fmt.Errorf("scoped synthetic mesh config contains invalid peer endpoint observation reliability")
|
||||
}
|
||||
}
|
||||
if err := validatePeerDirectory(cfg.PeerDirectory, cfg.LocalNodeID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -33,6 +33,15 @@ func TestLoadScopedSyntheticConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
PeerEndpointObservations: map[string]EndpointCandidateHealthObservation{
|
||||
"node-b-public": {
|
||||
EndpointID: "node-b-public",
|
||||
LastLatencyMs: 42,
|
||||
SuccessCount: 3,
|
||||
ReliabilityScore: 95,
|
||||
ObservedAt: expiresAt.Add(-time.Minute),
|
||||
},
|
||||
},
|
||||
PeerDirectory: []PeerDirectoryEntry{
|
||||
{
|
||||
NodeID: "node-b",
|
||||
@@ -81,6 +90,9 @@ func TestLoadScopedSyntheticConfig(t *testing.T) {
|
||||
if got := cfg.PeerEndpointCandidates["node-b"]; len(got) != 1 || got[0].EndpointID != "node-b-public" {
|
||||
t.Fatalf("unexpected endpoint candidates: %+v", cfg.PeerEndpointCandidates)
|
||||
}
|
||||
if got := cfg.PeerEndpointObservations["node-b-public"]; got.EndpointID != "node-b-public" || got.ReliabilityScore != 95 {
|
||||
t.Fatalf("unexpected endpoint observations: %+v", cfg.PeerEndpointObservations)
|
||||
}
|
||||
if len(cfg.PeerDirectory) != 1 || cfg.PeerDirectory[0].NodeID != "node-b" || !cfg.PeerDirectory[0].RecoverySeed {
|
||||
t.Fatalf("unexpected peer directory: %+v", cfg.PeerDirectory)
|
||||
}
|
||||
@@ -162,6 +174,26 @@ func TestLoadScopedSyntheticConfigRejectsInvalidPeerEndpointCandidate(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadScopedSyntheticConfigRejectsInvalidPeerEndpointObservation(t *testing.T) {
|
||||
path := writeScopedConfig(t, ScopedSyntheticConfig{
|
||||
SchemaVersion: "c17f.synthetic.v1",
|
||||
ClusterID: "cluster-1",
|
||||
LocalNodeID: "node-a",
|
||||
PeerEndpoints: map[string]string{},
|
||||
PeerEndpointObservations: map[string]EndpointCandidateHealthObservation{
|
||||
"endpoint-a": {
|
||||
EndpointID: "endpoint-b",
|
||||
ReliabilityScore: 101,
|
||||
},
|
||||
},
|
||||
Routes: []SyntheticRoute{liveSyntheticRoute("route-a-b", []string{"node-a", "node-b"})},
|
||||
})
|
||||
_, err := LoadScopedSyntheticConfig(path, PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"})
|
||||
if err == nil {
|
||||
t.Fatal("expected invalid peer endpoint observation error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadScopedSyntheticConfigRejectsInvalidPeerDirectory(t *testing.T) {
|
||||
path := writeScopedConfig(t, ScopedSyntheticConfig{
|
||||
SchemaVersion: "c17f.synthetic.v1",
|
||||
|
||||
Reference in New Issue
Block a user