CI / changes (push) Successful in 5s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 24s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Has been skipped
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Successful in 13s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Successful in 1m2s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Successful in 1m35s
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Successful in 1m24s
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Successful in 1m29s
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Successful in 1m25s
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Successful in 1m16s
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Successful in 1m27s
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Successful in 1m25s
204 lines
8.1 KiB
Go
204 lines
8.1 KiB
Go
package store
|
|
|
|
import "time"
|
|
|
|
// Backend is the persistence abstraction for the control plane (memory, PostgreSQL, SQLite).
|
|
type Backend interface {
|
|
MaterializedPrefixStats() (max int, sum int)
|
|
PeerCount() int
|
|
PeerSessionCountsByState() map[string]int
|
|
// DemoIDs is non-empty only after SeedDemo (memory or seeded SQL).
|
|
DemoIDs() (tenant, moduleCDN, moduleIP, revision, speaker string)
|
|
|
|
// ListTenantIDs returns distinct tenant identifiers (for background workers).
|
|
ListTenantIDs() ([]string, error)
|
|
|
|
ListModules(tenantID string) []*Module
|
|
GetModule(tenantID, moduleID string) (*Module, error)
|
|
CreateModule(tenantID string, in *Module) (*Module, error)
|
|
UpdateModule(tenantID, moduleID string, patch *ModulePatch) (*Module, error)
|
|
SoftDeleteModule(tenantID, moduleID string) error
|
|
|
|
ListCDNSources(tenantID, moduleID string) ([]*CDNSource, error)
|
|
CreateCDNSource(tenantID, moduleID string, in *CDNSource) (*CDNSource, error)
|
|
UpdateCDNSource(tenantID, moduleID, sourceID string, patch *CDNSourcePatch) (*CDNSource, error)
|
|
DeleteCDNSource(tenantID, moduleID, sourceID string) error
|
|
|
|
ListASEntries(tenantID, moduleID string) ([]*ASEntry, error)
|
|
CreateASEntry(tenantID, moduleID string, in *ASEntry) (*ASEntry, error)
|
|
UpdateASEntry(tenantID, moduleID, entryID string, patch *ASEntryPatch) (*ASEntry, error)
|
|
DeleteASEntry(tenantID, moduleID, entryID string) error
|
|
|
|
ListDomainEntries(tenantID, moduleID string) ([]*DomainEntry, error)
|
|
CreateDomainEntry(tenantID, moduleID string, in *DomainEntry) (*DomainEntry, error)
|
|
UpdateDomainEntry(tenantID, moduleID, entryID string, patch *DomainEntryPatch) (*DomainEntry, error)
|
|
DeleteDomainEntry(tenantID, moduleID, entryID string) error
|
|
|
|
ListIPRangeEntries(tenantID, moduleID string) ([]*IPRangeEntry, error)
|
|
CreateIPRangeEntry(tenantID, moduleID string, in *IPRangeEntry) (*IPRangeEntry, error)
|
|
UpdateIPRangeEntry(tenantID, moduleID, entryID string, patch *IPRangePatch) (*IPRangeEntry, error)
|
|
DeleteIPRangeEntry(tenantID, moduleID, entryID string) error
|
|
|
|
ListDohProfiles(tenantID string) ([]*DohProfile, error)
|
|
GetDohProfile(tenantID, id string) (*DohProfile, error)
|
|
CreateDohProfile(tenantID string, in *DohProfile) (*DohProfile, error)
|
|
UpdateDohProfile(tenantID, id string, patch *DohProfilePatch) (*DohProfile, error)
|
|
DeleteDohProfile(tenantID, id string) error
|
|
|
|
ListCommunities(tenantID string) ([]*Community, error)
|
|
GetCommunity(tenantID, id string) (*Community, error)
|
|
CreateCommunity(tenantID string, in *Community) (*Community, error)
|
|
UpdateCommunity(tenantID, id string, patch *CommunityPatch) (*Community, error)
|
|
DeleteCommunity(tenantID, id string) error
|
|
|
|
ListPeers(tenantID string) []*BGPPeer
|
|
GetPeer(tenantID, id string) (*BGPPeer, error)
|
|
CreatePeer(tenantID string, in *BGPPeer) (*BGPPeer, error)
|
|
UpdatePeer(tenantID, id string, patch *PeerPatch) (*BGPPeer, error)
|
|
DeletePeer(tenantID, id string) error
|
|
|
|
ListSpeakersForTenant(tenantID string) []*Speaker
|
|
GetSpeaker(tenantID, speakerID string) (*Speaker, error)
|
|
GetSpeakerAnyTenant(speakerID string) (*Speaker, error)
|
|
CreateSpeaker(tenantID string, in *Speaker) (*Speaker, error)
|
|
UpdateSpeaker(tenantID, id string, patch *SpeakerPatch) (*Speaker, error)
|
|
|
|
GetRevision(tenantID, revisionID string) (*Revision, error)
|
|
ListRevisions(tenantID, moduleID string, cursor string, limit int) (items []*Revision, nextCursor string, hasMore bool)
|
|
ListRevisionPrefixes(tenantID, revisionID string, cursor string, limit int) (prefixes []PrefixRow, next string, more bool)
|
|
CreateRollbackRevision(tenantID, sourceRevisionID string) (newID string, err error)
|
|
// CreateRenderRevision inserts a new config_revision (revID must be unique) with materialized prefixes and preview fragments.
|
|
CreateRenderRevision(revisionID, tenantID, moduleID string, parentRevisionID *string, contentHash string, previewFragments map[string]string, prefixes []PrefixRow) error
|
|
RevisionDiff(tenantID, aID, bID string) (map[string]any, error)
|
|
SetLastAppliedRevision(tenantID, speakerID, revisionID string) error
|
|
PublishRevisionForSpeaker(speakerID, revisionID string) error
|
|
LatestPublishedRevision(speakerID string) (revisionID string, publishedAt time.Time, err error)
|
|
|
|
ListGlobalSettings(tenantID string) (map[string]any, error)
|
|
PatchGlobalSettings(tenantID string, patch map[string]any) error
|
|
}
|
|
|
|
// ModulePatch is a partial update for module.
|
|
type ModulePatch struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Enabled *bool `json:"enabled,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
RefreshIntervalSec *int `json:"refresh_interval_sec,omitempty"`
|
|
CronExpr *string `json:"cron_expr,omitempty"`
|
|
DefaultCommunityID *string `json:"default_community_id,omitempty"`
|
|
DohProfileID *string `json:"doh_profile_id,omitempty"`
|
|
}
|
|
|
|
// CDNSource is a row under a CDN module.
|
|
type CDNSource struct {
|
|
ID string `json:"id,omitempty"`
|
|
ModuleID string `json:"module_id,omitempty"`
|
|
SourceKind string `json:"source_kind"`
|
|
URL string `json:"url"`
|
|
Etag string `json:"etag"`
|
|
RefreshIntervalSec *int `json:"refresh_interval_sec"`
|
|
CommunityID *string `json:"community_id"`
|
|
}
|
|
|
|
type CDNSourcePatch struct {
|
|
SourceKind *string `json:"source_kind,omitempty"`
|
|
URL *string `json:"url,omitempty"`
|
|
Etag *string `json:"etag,omitempty"`
|
|
RefreshIntervalSec *int `json:"refresh_interval_sec,omitempty"`
|
|
CommunityID *string `json:"community_id,omitempty"`
|
|
}
|
|
|
|
type ASEntry struct {
|
|
ID string `json:"id,omitempty"`
|
|
ModuleID string `json:"module_id,omitempty"`
|
|
ASN int64 `json:"asn"`
|
|
CommunityID *string `json:"community_id"`
|
|
}
|
|
|
|
type ASEntryPatch struct {
|
|
ASN *int64 `json:"asn,omitempty"`
|
|
CommunityID *string `json:"community_id,omitempty"`
|
|
}
|
|
|
|
// ValidASN reports whether n is a usable BGP ASN (1..4294967295).
|
|
func ValidASN(n int64) bool {
|
|
return n >= 1 && n <= 4294967295
|
|
}
|
|
|
|
type DomainEntry struct {
|
|
ID string `json:"id,omitempty"`
|
|
ModuleID string `json:"module_id,omitempty"`
|
|
FQDN string `json:"fqdn"`
|
|
CommunityID *string `json:"community_id"`
|
|
}
|
|
|
|
type DomainEntryPatch struct {
|
|
FQDN *string `json:"fqdn,omitempty"`
|
|
CommunityID *string `json:"community_id,omitempty"`
|
|
}
|
|
|
|
type IPRangeEntry struct {
|
|
ID string `json:"id,omitempty"`
|
|
ModuleID string `json:"module_id,omitempty"`
|
|
Prefix string `json:"prefix"`
|
|
CommunityID *string `json:"community_id"`
|
|
}
|
|
|
|
type IPRangePatch struct {
|
|
Prefix *string `json:"prefix,omitempty"`
|
|
CommunityID *string `json:"community_id,omitempty"`
|
|
}
|
|
|
|
type DohProfile struct {
|
|
ID string `json:"id,omitempty"`
|
|
TenantID string `json:"tenant_id,omitempty"`
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
TimeoutMs *int `json:"timeout_ms"`
|
|
SecretRef *string `json:"vault_secret_ref"`
|
|
}
|
|
|
|
type DohProfilePatch struct {
|
|
Name *string `json:"name,omitempty"`
|
|
URL *string `json:"url,omitempty"`
|
|
TimeoutMs *int `json:"timeout_ms,omitempty"`
|
|
SecretRef *string `json:"vault_secret_ref,omitempty"`
|
|
}
|
|
|
|
type Community struct {
|
|
ID string `json:"id,omitempty"`
|
|
TenantID string `json:"tenant_id,omitempty"`
|
|
Name string `json:"name"`
|
|
Kind string `json:"kind"`
|
|
ValueJSON string `json:"value_json"`
|
|
}
|
|
|
|
type CommunityPatch struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Kind *string `json:"kind,omitempty"`
|
|
ValueJSON *string `json:"value_json,omitempty"`
|
|
}
|
|
|
|
type PeerPatch struct {
|
|
Neighbor *string `json:"neighbor,omitempty"`
|
|
RemoteASN *int64 `json:"remote_asn,omitempty"`
|
|
SpeakerID *string `json:"bgp_speaker_id,omitempty"`
|
|
Enabled *bool `json:"enabled,omitempty"`
|
|
Name *string `json:"name,omitempty"`
|
|
SessionState *string `json:"session_state,omitempty"`
|
|
PoliciesJSON *string `json:"policies_json,omitempty"`
|
|
}
|
|
|
|
type SpeakerPatch struct {
|
|
Role *string `json:"role,omitempty"`
|
|
Endpoint *string `json:"endpoint,omitempty"`
|
|
MetaJSON *string `json:"meta_json,omitempty"`
|
|
}
|
|
|
|
// PrefixRow is one materialized prefix for GET /revisions/.../prefixes.
|
|
type PrefixRow struct {
|
|
Prefix string
|
|
CommunityID *string
|
|
Source string
|
|
}
|