Documentation
¶
Overview ¶
Package server manages plugin process connections, the 5-stage startup protocol, and command dispatch.
Index ¶
- Constants
- Variables
- func BuiltinCount() int
- func ClientConfigKey(name string) string
- func ClientNameFromConfigKey(key string) (string, bool)
- func ExtractConfigSubtree(configTree map[string]any, path string) any
- func GetVersion() (string, string)
- func IsReadOnlyPath(path string) bool
- func IsStreamingCommand(input string) bool
- func LoadBuiltins(d *Dispatcher, wireToPath, pathToDesc map[string]string, ...)
- func LoadBuiltinsWithAliases(d *Dispatcher, wireToPaths map[string][]string, pathToDesc map[string]string, ...)
- func LookupCommandHelp(ctx *CommandContext, name, kind string) (*plugin.Response, error)
- func MonitorEventFormatter() func(string) string
- func PeerSubcommandKeywords(wireToPath map[string]string) map[string]bool
- func RegisterDefaultHandlers(d *Dispatcher, wireToPath, pathToDesc map[string]string, ...)
- func RegisterMonitorEventFormatter(fn func(string) string)
- func RegisterMonitorProvider(p MonitorProvider)
- func RegisterProcessCleanup(fn ProcessCleanupFunc)
- func RegisterRPCs(rpcs ...RPCRegistration)
- func RegisterStreamingHandler(prefix string, h StreamingHandler)
- func RequireReactor(ctx *CommandContext) (plugin.ReactorLifecycle, *plugin.Response, error)
- func SetVersion(v, d string)
- func StreamEventMonitor(ctx context.Context, s *Server, w io.Writer, _ string, args []string) error
- func StreamingPrefixes() []string
- func UnregisterStreamingHandler(prefix string)
- type Command
- type CommandContext
- func (c *CommandContext) CommitManager() any
- func (c *CommandContext) Context() context.Context
- func (c *CommandContext) Dispatcher() *Dispatcher
- func (c *CommandContext) PeerSelector() string
- func (c *CommandContext) ProtocolReactor(name string) any
- func (c *CommandContext) Reactor() plugin.ReactorLifecycle
- func (c *CommandContext) Selector(name string) string
- func (c *CommandContext) Subscriptions() *SubscriptionManager
- type CommandDef
- type CommandRegistry
- func (r *CommandRegistry) AddBuiltin(name string)
- func (r *CommandRegistry) All() []*RegisteredCommand
- func (r *CommandRegistry) Complete(partial string) []Completion
- func (r *CommandRegistry) Freeze()
- func (r *CommandRegistry) IsBuiltin(name string) bool
- func (r *CommandRegistry) Lookup(name string) *RegisteredCommand
- func (r *CommandRegistry) LookupDeprecatedPrefix(lowerInput string) (*RegisteredCommand, int)
- func (r *CommandRegistry) Register(proc *process.Process, defs []CommandDef) []RegisterResult
- func (r *CommandRegistry) RegisterDeprecated(proc *process.Process, oldName, newName string) error
- func (r *CommandRegistry) Unregister(proc *process.Process, names []string)
- func (r *CommandRegistry) UnregisterAll(proc *process.Process)
- func (r *CommandRegistry) VisibleCommandEntries() []command.CommandEntry
- type Completion
- type ConfigBlock
- type ConfigEventGateway
- func (g *ConfigEventGateway) EmitConfigEvent(eventType string, payload []byte) (int, error)
- func (g *ConfigEventGateway) SubscribeConfigEvent(eventType string, handler func(payload []byte)) func()
- func (g *ConfigEventGateway) SubscribeEvent(namespace, eventType string, handler func(payload any)) func()
- type ConfigLoader
- type ConfigReader
- type Dispatcher
- func (d *Dispatcher) BeginAccounting(ctx *CommandContext, input string) func()
- func (d *Dispatcher) Commands() []*Command
- func (d *Dispatcher) Dispatch(ctx *CommandContext, input string) (*plugin.Response, error)
- func (d *Dispatcher) ForwardToPlugin(cmdCtx *CommandContext, command string, args []string, peerSelector string) (*plugin.Response, error)
- func (d *Dispatcher) IsAuthorized(ctx *CommandContext, input string, readOnly bool) bool
- func (d *Dispatcher) Lookup(name string) *Command
- func (d *Dispatcher) Pending() *PendingRequests
- func (d *Dispatcher) Register(name string, handler Handler, help string)
- func (d *Dispatcher) RegisterWithOptions(name string, handler Handler, help string, opts RegisterOptions)
- func (d *Dispatcher) Registry() *CommandRegistry
- func (d *Dispatcher) SetAccountingHook(h aaa.Accountant)
- func (d *Dispatcher) SetAuditRecorder(recorder audit.Recorder)
- func (d *Dispatcher) SetAuthorizer(a aaa.Authorizer)
- func (d *Dispatcher) SetSubsystems(sm *SubsystemManager)
- func (d *Dispatcher) Subsystems() *SubsystemManager
- type EngineEventHandler
- type EnsureStep
- type EventMonitorOpts
- type EventRecord
- type EventRing
- type FullReloadFunc
- type Handler
- type Hub
- type ManagedConfigService
- func (s *ManagedConfigService) BuildConfigChanged(clientName string) (fleet.ConfigChanged, error)
- func (s *ManagedConfigService) HandleConfigFetch(clientName string, req fleet.ConfigFetchRequest) (fleet.ConfigFetchResponse, error)
- func (s *ManagedConfigService) RegisterClient(name string) error
- func (s *ManagedConfigService) UnregisterClient(name string)
- type ManagedServer
- type ManagedServerConfig
- type MonitorClient
- type MonitorManager
- func (mm *MonitorManager) Add(mc *MonitorClient)
- func (mm *MonitorManager) Count() int
- func (mm *MonitorManager) Deliver(namespace, eventType, direction, peerAddr, peerName, output string)
- func (mm *MonitorManager) DeliverLazy(namespace, eventType, direction, peerAddr, peerName string, ...)
- func (mm *MonitorManager) DeliverLazyTyped(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, ...)
- func (mm *MonitorManager) GetMatching(namespace, eventType, direction, peerAddr, peerName string) []*MonitorClient
- func (mm *MonitorManager) GetMatchingTyped(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, ...) []*MonitorClient
- func (mm *MonitorManager) HasMonitors() bool
- func (mm *MonitorManager) Remove(id string)
- type MonitorProvider
- type PeerFilter
- type PendingRequest
- type PendingRequests
- func (p *PendingRequests) Add(req *PendingRequest) string
- func (p *PendingRequests) CancelAll(proc *process.Process)
- func (p *PendingRequests) Complete(serial string, resp *plugin.Response) bool
- func (p *PendingRequests) Count(proc *process.Process) int
- func (p *PendingRequests) Partial(serial string, resp *plugin.Response) bool
- func (p *PendingRequests) Total() int
- type ProcessCleanupFunc
- type QuiesceFunc
- type Quiescer
- type QuiescerRegistry
- type RPCParams
- type RPCRegistration
- type RegisterOptions
- type RegisterResult
- type RegisteredCommand
- type RegisteredNotification
- type RegisteredRPC
- type Schema
- type SchemaRegistry
- func (r *SchemaRegistry) Count() int
- func (r *SchemaRegistry) FindHandler(path string) (*Schema, string)
- func (r *SchemaRegistry) FindRPC(wireMethod string) (*RegisteredRPC, error)
- func (r *SchemaRegistry) FindRPCByCommand(cliCommand string) (*RegisteredRPC, error)
- func (r *SchemaRegistry) Freeze()
- func (r *SchemaRegistry) GetByHandler(path string) (*Schema, error)
- func (r *SchemaRegistry) GetByModule(name string) (*Schema, error)
- func (r *SchemaRegistry) ListHandlers() map[string]string
- func (r *SchemaRegistry) ListModules() []string
- func (r *SchemaRegistry) ListNotifications(module string) []*RegisteredNotification
- func (r *SchemaRegistry) ListRPCs(module string) []*RegisteredRPC
- func (r *SchemaRegistry) Register(schema *Schema) error
- func (r *SchemaRegistry) RegisterCLICommand(cliCommand, wireMethod string) error
- func (r *SchemaRegistry) RegisterNotifications(module string, notifs []yang.NotificationMeta) error
- func (r *SchemaRegistry) RegisterRPCs(module string, rpcs []yang.RPCMeta) error
- type Server
- func (s *Server) AllPluginCapabilities() []plugin.InjectedCapability
- func (s *Server) CallDoctorCheck(ctx context.Context, pluginName, checkName string) (*rpc.DoctorCheckOutput, error)
- func (s *Server) CallFilterUpdate(ctx context.Context, pluginName string, input *rpc.FilterUpdateInput) (*rpc.FilterUpdateOutput, error)
- func (s *Server) CommitManager() any
- func (s *Server) ConfigPath() string
- func (s *Server) Context() context.Context
- func (s *Server) DecodeNLRI(family, hexData string) (string, error)
- func (s *Server) Dispatcher() *Dispatcher
- func (s *Server) DoctorCheckPlugins() map[string][]plugin.DoctorCheckRegistration
- func (s *Server) DrainSIGHUP() bool
- func (s *Server) Emit(namespace, eventType string, payload any) (int, error)
- func (s *Server) EmitEngineEvent(namespace, eventType string, payload any) (int, error)
- func (s *Server) EncodeNLRI(family string, args []string) ([]byte, error)
- func (s *Server) EventRing() *EventRing
- func (s *Server) FilterInfo(pluginName, filterName string) (declaredAttrs []string, raw bool)
- func (s *Server) FilterOnError(pluginName, filterName string) rpc.OnErrorPolicy
- func (s *Server) GetDecodeFamilies() []string
- func (s *Server) GetPluginCapabilitiesForPeer(peerAddr string) []plugin.InjectedCapability
- func (s *Server) GetSchemaDeclarations() []plugin.SchemaDeclaration
- func (s *Server) HandleAdHocPluginSession(reader io.ReadCloser, writer io.WriteCloser) error
- func (s *Server) HasConfigLoader() bool
- func (s *Server) HasFullReloadFunc() bool
- func (s *Server) HasProcesses() bool
- func (s *Server) MarkReloadProcessed(applied bool)
- func (s *Server) Monitors() *MonitorManager
- func (s *Server) ProcessManager() *process.ProcessManager
- func (s *Server) QueueSIGHUP()
- func (s *Server) Quiescers() []Quiescer
- func (s *Server) Reactor() plugin.ReactorLifecycle
- func (s *Server) ReactorAny() any
- func (s *Server) ReactorFor(name string) any
- func (s *Server) RegisterQuiescer(name string, fn QuiesceFunc)
- func (s *Server) ReloadConfig(ctx context.Context, newTree map[string]any) error
- func (s *Server) ReloadFromDisk(ctx context.Context) error
- func (s *Server) ReloadFull(ctx context.Context) error
- func (s *Server) ReloadStatus() (generation uint64, outcome string, at time.Time)
- func (s *Server) Running() bool
- func (s *Server) SetCommitManager(cm any)
- func (s *Server) SetConfigLoader(loader ConfigLoader)
- func (s *Server) SetFullReloadFunc(fn FullReloadFunc)
- func (s *Server) SetProcessSpawner(sp plugin.ProcessSpawner)
- func (s *Server) SetRebootFunc(fn func())
- func (s *Server) SetShutdownFunc(fn func())
- func (s *Server) Start() error
- func (s *Server) StartWithContext(ctx context.Context) error
- func (s *Server) Stop()
- func (s *Server) Subscribe(namespace, eventType string, handler func(payload any)) func()
- func (s *Server) SubscribeEngineEvent(namespace, eventType string, handler EngineEventHandler) func()
- func (s *Server) Subscriptions() *SubscriptionManager
- func (s *Server) TxLocked() bool
- func (s *Server) UpdateProtocolConfig(families, customEvents, customSendTypes []string)
- func (s *Server) Wait(ctx context.Context) error
- func (s *Server) WaitForStartupComplete(ctx context.Context) error
- type ServerConfig
- type StreamingHandler
- type Subscription
- type SubscriptionManager
- func (sm *SubscriptionManager) Add(proc *process.Process, sub *Subscription)
- func (sm *SubscriptionManager) ClearProcess(proc *process.Process)
- func (sm *SubscriptionManager) Count(proc *process.Process) int
- func (sm *SubscriptionManager) GetMatching(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, ...) []*process.Process
- func (sm *SubscriptionManager) GetSubscriptions(proc *process.Process) []*Subscription
- func (sm *SubscriptionManager) Remove(proc *process.Process, sub *Subscription) bool
- type SubsystemConfig
- type SubsystemHandler
- func (h *SubsystemHandler) Commands() []string
- func (h *SubsystemHandler) Handle(ctx context.Context, command string) (*plugin.Response, error)
- func (h *SubsystemHandler) Name() string
- func (h *SubsystemHandler) Running() bool
- func (h *SubsystemHandler) Schema() *plugin.PluginSchemaDecl
- func (h *SubsystemHandler) Signal(sig os.Signal) error
- func (h *SubsystemHandler) Start(ctx context.Context) error
- func (h *SubsystemHandler) Stop()
- type SubsystemManager
- func (m *SubsystemManager) AllCommands() []string
- func (m *SubsystemManager) AllSchemas() []*Schema
- func (m *SubsystemManager) FindHandler(command string) *SubsystemHandler
- func (m *SubsystemManager) Freeze()
- func (m *SubsystemManager) Get(name string) *SubsystemHandler
- func (m *SubsystemManager) Names() []string
- func (m *SubsystemManager) Register(config SubsystemConfig)
- func (m *SubsystemManager) RegisterSchemas(registry *SchemaRegistry) error
- func (m *SubsystemManager) Replace(name string, handler *SubsystemHandler)
- func (m *SubsystemManager) StartAll(ctx context.Context) error
- func (m *SubsystemManager) StopAll()
- func (m *SubsystemManager) Unregister(name string)
Constants ¶
const ( DefaultCommandTimeout = 30 * time.Second CompletionTimeout = 500 * time.Millisecond )
Default timeouts for plugin commands.
const ( ReloadOutcomeApplied = "applied" ReloadOutcomeFailed = "failed" // ReloadOutcomeNone is reported before the first reload is processed, // while Generation is still 0. ReloadOutcomeNone = "none" )
Reload outcome strings reported by ReloadStatus. A reload that ran to completion is "applied"; one that returned an error is "failed". Both advance the generation counter: the counter answers "was a reload PROCESSED", not "did it change anything".
const APIVersion = "0.1.0"
APIVersion is the IPC protocol version.
const MaxPendingPerProcess = 100
MaxPendingPerProcess limits pending requests to prevent memory exhaustion.
Variables ¶
var ( ErrSchemaModuleEmpty = errors.New("schema module name is empty") ErrSchemaModuleDuplicate = errors.New("schema module already registered") ErrSchemaHandlerDuplicate = errors.New("schema handler already registered") ErrSchemaNotFound = errors.New("schema not found") ErrRPCNotFound = errors.New("RPC not found") ErrRPCDuplicate = errors.New("RPC wire method already registered") ErrNotificationDuplicate = errors.New("notification wire method already registered") )
Errors for schema registration.
var ErrClientConfigNotFound = errors.New("client config not found")
ErrClientConfigNotFound is returned when no config exists for a client name.
var ErrDuplicateClient = errors.New("duplicate client name")
ErrDuplicateClient is returned when a client with the same name is already connected.
var ErrEmptyCommand = errors.New("empty command")
ErrEmptyCommand is returned when the command is empty.
var ErrPluginConnectionClosed = errors.New("plugin connection closed")
ErrPluginConnectionClosed is returned when the plugin's connection is no longer available.
var ErrPluginProcessNotRunning = errors.New("plugin process not running")
ErrPluginProcessNotRunning is returned when a plugin command targets a non-running process.
var ErrReloadInProgress = errors.New("config reload already in progress")
ErrReloadInProgress is returned when a config reload is attempted while another is already running. Callers can check this with errors.Is to decide whether to queue the reload (SIGHUP) or reject it (CLI/API).
var ErrSilent = errors.New("silent")
ErrSilent is returned when a command should produce no response.
var ErrSubsystemConnectionClosed = errors.New("subsystem connection closed")
ErrSubsystemConnectionClosed is returned when the subsystem's connection is no longer available.
var ErrSubsystemNotRunning = errors.New("subsystem not running")
ErrSubsystemNotRunning is returned when a command targets a non-running subsystem.
ErrUnauthorized is returned when a command is denied by authorization. Its text is plugin.UnauthorizedMessage because operators read it directly: the ssh exec handler prints this error, not the Response.Error below.
var ErrUnknownCommand = errors.New("unknown command")
ErrUnknownCommand is returned when a command is not recognized.
Functions ¶
func BuiltinCount ¶
func BuiltinCount() int
BuiltinCount returns the number of registered builtin handlers.
func ClientConfigKey ¶
ClientConfigKey returns the blob key (relative; storage adds the file/active/ namespace) for a managed client's config.
func ClientNameFromConfigKey ¶
ClientNameFromConfigKey extracts the managed client name from a written blob key, reporting false when the key is not a per-client config key. It tolerates the storage namespace prefix (file/active/) by matching on the key's basename, so it works whether the observer reports the relative or the resolved key.
func ExtractConfigSubtree ¶
ExtractConfigSubtree extracts a subtree from the config based on path. Always returns data wrapped in its full path structure from root. Supports:
- "*" -> entire tree
- "bgp" -> {"bgp": configTree["bgp"]}
- "bgp/peer" -> {"bgp": {"peer": configTree["bgp"]["peer"]}}
func GetVersion ¶
GetVersion returns the current version and build date.
func IsReadOnlyPath ¶
IsReadOnlyPath returns true if the command path starts with a read-only verb. With verb-first grammar, "show", "monitor", and "resolve" are read-only; "clear", "set", "request", "commit", "update" are not.
func IsStreamingCommand ¶
IsStreamingCommand returns true if the input matches any registered streaming prefix.
func LoadBuiltins ¶
func LoadBuiltins(d *Dispatcher, wireToPath, pathToDesc map[string]string, pathToArgDefs map[string][]command.ArgDef)
LoadBuiltins registers all builtin handlers with the dispatcher. The wireToPath map provides the dispatch key for each handler, derived from the YANG command tree (WireMethod -> CLI path). pathToDesc provides YANG descriptions for help text. Handlers without a YANG entry are skipped.
func LoadBuiltinsWithAliases ¶
func LoadBuiltinsWithAliases(d *Dispatcher, wireToPaths map[string][]string, pathToDesc map[string]string, pathToArgDefs map[string][]command.ArgDef, cmdTree *command.Node)
LoadBuiltinsWithAliases registers all builtin handlers with the dispatcher, including all YANG command aliases for each wire method. When cmdTree is non-nil, commands whose YANG path passes through a ze:ensure-exists node are wrapped to auto-ensure the parent resource and rollback on failure.
func LookupCommandHelp ¶
func LookupCommandHelp(ctx *CommandContext, name, kind string) (*plugin.Response, error)
LookupCommandHelp looks up a command by name in builtins then plugins. The kind parameter is used in error messages (e.g., "command", "bgp rib command").
func MonitorEventFormatter ¶
MonitorEventFormatter returns the registered event formatter, or nil if none is registered.
func PeerSubcommandKeywords ¶
PeerSubcommandKeywords returns the set of words that immediately follow `peer` in BGP peer command paths. Used by config validation to reject peer names that would collide with subcommand dispatch. The wireToPath map is typically built via yang.WireMethodToPath(loader).
func RegisterDefaultHandlers ¶
func RegisterDefaultHandlers(d *Dispatcher, wireToPath, pathToDesc map[string]string, pathToArgDefs map[string][]command.ArgDef)
RegisterDefaultHandlers registers all builtin handlers with the dispatcher.
func RegisterMonitorEventFormatter ¶
RegisterMonitorEventFormatter registers the function that formats raw JSON event lines into compact one-liners for monitor streaming output (both CLI and TUI). Called from the monitor plugin's init().
func RegisterMonitorProvider ¶
func RegisterMonitorProvider(p MonitorProvider)
RegisterMonitorProvider registers a TUI monitor provider for a streaming prefix.
func RegisterProcessCleanup ¶
func RegisterProcessCleanup(fn ProcessCleanupFunc)
RegisterProcessCleanup registers a callback invoked during cleanupProcess. Called from init() to avoid import cycles between server and command packages.
func RegisterRPCs ¶
func RegisterRPCs(rpcs ...RPCRegistration)
RegisterRPCs adds RPCs to the package-level registry. Called from init() in register.go files.
func RegisterStreamingHandler ¶
func RegisterStreamingHandler(prefix string, h StreamingHandler)
RegisterStreamingHandler registers a streaming command handler for a prefix. The prefix is matched case-insensitively against command input. Called from plugin init() functions.
func RequireReactor ¶
func RequireReactor(ctx *CommandContext) (plugin.ReactorLifecycle, *plugin.Response, error)
RequireReactor returns the reactor or an error response if not available.
func SetVersion ¶
func SetVersion(v, d string)
SetVersion sets the application version and build date (called from main).
func StreamEventMonitor ¶
StreamEventMonitor is the streaming handler for the "event monitor" command. It parses arguments, creates subscriptions, registers a MonitorClient, and streams events until the context is canceled. Registration: called from internal/component/bgp/plugins/cmd/monitor/monitor.go init() via RegisterStreamingHandler("event monitor", StreamEventMonitor).
func StreamingPrefixes ¶
func StreamingPrefixes() []string
StreamingPrefixes returns the registered streaming command prefixes, sorted.
func UnregisterStreamingHandler ¶
func UnregisterStreamingHandler(prefix string)
UnregisterStreamingHandler removes a previously registered streaming handler.
Types ¶
type Command ¶
type Command struct {
Name string
Handler Handler
Help string
ReadOnly bool // True if command only reads state (safe for "ze show")
RequiresSelector bool // True if command requires an explicit selector instead of implicit/all scope
ArgDefs []command.ArgDef // Typed argument definitions from YANG leaves.
}
Command represents a registered command with metadata.
type CommandContext ¶
type CommandContext struct {
Server *Server // Gateway to all server state (reactor, dispatcher, etc.)
Process *process.Process // The API process (for session state)
RequestContext context.Context // Request-scoped context from the trusted transport.
Peer string // Peer selector: "*" for all, or specific peer selector value. Empty = "*"
Username string // Authenticated username (empty = no auth, full access)
RemoteAddr string // Remote address of the client (e.g., SSH peer IP:port)
Surface string // Trusted caller surface for audit attribution.
Meta map[string]any // Route metadata from UpdateRoute RPC; nil if not set.
Selectors map[string]string // Extracted typed selector values, keyed by selector keyword.
}
CommandContext provides access to reactor and session state. Dependencies are accessed through Server; per-request state is stored directly.
func (*CommandContext) CommitManager ¶
func (c *CommandContext) CommitManager() any
CommitManager returns the commit manager via Server. Nil-safe: returns nil if Server is nil.
func (*CommandContext) Context ¶
func (c *CommandContext) Context() context.Context
Context returns the request context for this command. Nil-safe: falls back from request -> server -> background.
func (*CommandContext) Dispatcher ¶
func (c *CommandContext) Dispatcher() *Dispatcher
Dispatcher returns the command dispatcher via Server. Nil-safe: returns nil if Server is nil.
func (*CommandContext) PeerSelector ¶
func (c *CommandContext) PeerSelector() string
PeerSelector returns the effective neighbor selector. Returns "*" if no neighbor was specified.
func (*CommandContext) ProtocolReactor ¶
func (c *CommandContext) ProtocolReactor(name string) any
ProtocolReactor returns a named protocol reactor from the Coordinator. Callers type-assert to the protocol-specific interface they need. Nil-safe: returns nil if Server is nil or protocol not registered.
func (*CommandContext) Reactor ¶
func (c *CommandContext) Reactor() plugin.ReactorLifecycle
Reactor returns the BGP reactor lifecycle interface via Server. Nil-safe: returns nil if Server is nil.
func (*CommandContext) Selector ¶
func (c *CommandContext) Selector(name string) string
Selector returns the extracted typed selector value for keyword `name`. Nil-safe. Lookup is case-insensitive.
func (*CommandContext) Subscriptions ¶
func (c *CommandContext) Subscriptions() *SubscriptionManager
Subscriptions returns the subscription manager via Server. Nil-safe: returns nil if Server is nil.
type CommandDef ¶
type CommandDef struct {
Name string // Command name (e.g., "myapp status")
Description string // Help text
Args string // Usage hint (e.g., "<component>")
Completable bool // Process handles arg completion
Hidden bool // Hidden from completion and help (works when typed in full)
Timeout time.Duration // Per-command timeout (0 = default 30s)
}
CommandDef describes a command to register. Passed from process to registry during registration.
type CommandRegistry ¶
type CommandRegistry struct {
// contains filtered or unexported fields
}
CommandRegistry manages plugin commands. Thread-safe for concurrent registration and lookup.
func NewCommandRegistry ¶
func NewCommandRegistry() *CommandRegistry
NewCommandRegistry creates a new command registry.
func (*CommandRegistry) AddBuiltin ¶
func (r *CommandRegistry) AddBuiltin(name string)
AddBuiltin marks a command name as builtin (cannot be shadowed). Called during dispatcher initialization.
func (*CommandRegistry) All ¶
func (r *CommandRegistry) All() []*RegisteredCommand
All returns all registered commands.
func (*CommandRegistry) Complete ¶
func (r *CommandRegistry) Complete(partial string) []Completion
Complete returns commands matching the partial input. Used for CLI command completion.
func (*CommandRegistry) Freeze ¶
func (r *CommandRegistry) Freeze()
Freeze creates an immutable snapshot of the commands and deprecated maps. After Freeze(), Lookup uses atomic.Load instead of RLock. MUST be called after all Register calls complete (after startup barrier). Safe to call multiple times (each call overwrites the previous snapshot).
func (*CommandRegistry) IsBuiltin ¶
func (r *CommandRegistry) IsBuiltin(name string) bool
IsBuiltin returns true if the command name is a builtin.
func (*CommandRegistry) Lookup ¶
func (r *CommandRegistry) Lookup(name string) *RegisteredCommand
Lookup finds a command by exact name (case-insensitive). If no primary match is found, checks deprecated aliases and returns the canonical command (logging a deprecation warning once per session). After Freeze(), uses lock-free atomic.Load on the frozen snapshot.
func (*CommandRegistry) LookupDeprecatedPrefix ¶
func (r *CommandRegistry) LookupDeprecatedPrefix(lowerInput string) (*RegisteredCommand, int)
LookupDeprecatedPrefix finds the longest deprecated alias that is a prefix of lowerInput (already lowercased by the caller). Returns the canonical RegisteredCommand and the matched prefix length, or (nil, 0) if no deprecated alias matches. Logs a deprecation warning on first match.
func (*CommandRegistry) Register ¶
func (r *CommandRegistry) Register(proc *process.Process, defs []CommandDef) []RegisterResult
Register adds commands for a process. Returns results for each command (success or failure reason).
func (*CommandRegistry) RegisterDeprecated ¶
func (r *CommandRegistry) RegisterDeprecated(proc *process.Process, oldName, newName string) error
RegisterDeprecated adds a deprecated alias that maps oldName to the canonical command registered under newName. When the old name is looked up, the canonical RegisteredCommand is returned and a deprecation warning is logged once per session.
The alias name is validated with the same parser as a real command, and the alias is rejected if it conflicts with a builtin, an already-registered command, or an existing alias, or if the canonical command is not registered. This makes an unreachable or shadowing alias impossible to register.
Requiring the canonical to be already registered is safe because a plugin's deprecated aliases (CommandDeprecatedNames) reference that same plugin's commands, which startup registers immediately before the aliases.
func (*CommandRegistry) Unregister ¶
func (r *CommandRegistry) Unregister(proc *process.Process, names []string)
Unregister removes commands owned by the process. Only the owning process can unregister a command. Unknown commands are silently ignored. If frozen, publishes a new snapshot reflecting the removal.
func (*CommandRegistry) UnregisterAll ¶
func (r *CommandRegistry) UnregisterAll(proc *process.Process)
UnregisterAll removes all commands and deprecated aliases owned by the process. Called when a process dies. If frozen, publishes a new snapshot reflecting the removal.
func (*CommandRegistry) VisibleCommandEntries ¶
func (r *CommandRegistry) VisibleCommandEntries() []command.CommandEntry
VisibleCommandEntries returns completion-tree entries for every non-hidden registered command. Hidden commands are excluded so they never surface in tab-completion or help (they still dispatch when typed in full via Lookup). Used to inject plugin-registered commands into the operational command tree (command.MergeCommandPaths) so interactive tab-completion offers them, matching the shell-completion path that already reads Complete().
type Completion ¶
type Completion struct {
Value string `json:"value"` // The completion text
Help string `json:"help,omitempty"` // Optional description
Source string `json:"source,omitempty"` // "builtin" or process name (verbose mode)
Hidden bool `json:"hidden,omitempty"` // Hidden from completion tree (works when typed in full)
}
Completion represents a single completion suggestion. Used for both command and argument completion.
type ConfigBlock ¶
type ConfigBlock struct {
Handler string // Handler path (e.g., "bgp/peer")
Action string // create, modify, delete
Path string // Full path (e.g., "bgp/peer[address=192.0.2.1]")
Data string // JSON data
}
ConfigBlock represents a config command to send to a plugin.
func ParseCommand ¶
func ParseCommand(line string) (*ConfigBlock, error)
ParseCommand parses a namespace command. Format: <namespace> <path> <action> {json}. Or: <namespace> <action> {json} (for namespace-level config). Or: <namespace> commit|rollback|diff.
type ConfigEventGateway ¶
type ConfigEventGateway struct {
// contains filtered or unexported fields
}
ConfigEventGateway adapts Server to the internal/component/config/transaction.EventGateway interface used by the config transaction orchestrator.
The adapter hides the namespace parameter (always "config") and converts between the orchestrator's []byte payloads and Server's string event payloads.
Performance note: each emit/dispatch round-trips through []byte -> string -> []byte (one copy in EmitConfigEvent, one copy in the SubscribeConfigEvent handler bridge). This is acceptable for small config transaction payloads (~hundreds of bytes per ack) and trades two small allocations against the simpler string-based deliverEvent path. If this ever becomes a hot path, the right fix is to add a []byte-native variant to deliverEvent rather than complicating the adapter.
func NewConfigEventGateway ¶
func NewConfigEventGateway(s *Server) *ConfigEventGateway
NewConfigEventGateway creates a new adapter wrapping the given Server. The Server must outlive the gateway; the gateway holds a reference but does not manage Server lifecycle.
func (*ConfigEventGateway) EmitConfigEvent ¶
func (g *ConfigEventGateway) EmitConfigEvent(eventType string, payload []byte) (int, error)
EmitConfigEvent publishes a stream event in the config namespace. Returns the number of plugin processes that received the event. Empty payloads are rejected — config acks always carry at least a transaction-id envelope, so an empty []byte is a programmer error.
func (*ConfigEventGateway) SubscribeConfigEvent ¶
func (g *ConfigEventGateway) SubscribeConfigEvent(eventType string, handler func(payload []byte)) func()
SubscribeConfigEvent registers a handler for a config namespace event type. The handler is invoked synchronously from deliverEvent. Returns an unsubscribe function; nil handler returns a no-op unsubscribe.
func (*ConfigEventGateway) SubscribeEvent ¶
func (g *ConfigEventGateway) SubscribeEvent(namespace, eventType string, handler func(payload any)) func()
SubscribeEvent registers a handler for any namespace/event pair. Operation settlement uses this to wait for side-effect events outside config.
type ConfigLoader ¶
ConfigLoader loads a new config tree from disk or other source. Returns the parsed config tree or an error. Set on Server.configLoader before calling ReloadFromDisk.
type ConfigReader ¶
ConfigReader reads a client's config by name from the hub's blob store. Returns the raw config bytes, or ErrClientConfigNotFound if the client has no config entry.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher routes commands to handlers.
func NewDispatcher ¶
func NewDispatcher() *Dispatcher
NewDispatcher creates a new command dispatcher.
func (*Dispatcher) BeginAccounting ¶
func (d *Dispatcher) BeginAccounting(ctx *CommandContext, input string) func()
BeginAccounting records command START and returns a function that records STOP. It is exported for command paths such as streaming handlers that intentionally bypass Dispatch but must still share the same AAA accounting hook.
func (*Dispatcher) Commands ¶
func (d *Dispatcher) Commands() []*Command
Commands returns all registered commands.
func (*Dispatcher) Dispatch ¶
func (d *Dispatcher) Dispatch(ctx *CommandContext, input string) (*plugin.Response, error)
Dispatch parses and executes a command. Supports inline selector extraction both for typed forms like `show demo name <name> detail` and for positional selector slots that appear before a later action token.
func (*Dispatcher) ForwardToPlugin ¶
func (d *Dispatcher) ForwardToPlugin(cmdCtx *CommandContext, command string, args []string, peerSelector string) (*plugin.Response, error)
ForwardToPlugin routes a command to a plugin process by exact name lookup. Used by proxy handlers that bridge CLI builtins to plugin commands. Returns ErrUnknownCommand if the command is not registered (plugin may not be running).
func (*Dispatcher) IsAuthorized ¶
func (d *Dispatcher) IsAuthorized(ctx *CommandContext, input string, readOnly bool) bool
IsAuthorized checks if the user is allowed to execute the command. Exported for use by streaming handlers (e.g., monitor) that bypass the normal dispatch path.
func (*Dispatcher) Lookup ¶
func (d *Dispatcher) Lookup(name string) *Command
Lookup finds a command by exact name.
func (*Dispatcher) Pending ¶
func (d *Dispatcher) Pending() *PendingRequests
Pending returns the pending requests tracker.
func (*Dispatcher) Register ¶
func (d *Dispatcher) Register(name string, handler Handler, help string)
Register adds a builtin command handler. Also marks the command as builtin in the registry to prevent shadowing.
func (*Dispatcher) RegisterWithOptions ¶
func (d *Dispatcher) RegisterWithOptions(name string, handler Handler, help string, opts RegisterOptions)
RegisterWithOptions adds a builtin command handler with additional options.
func (*Dispatcher) Registry ¶
func (d *Dispatcher) Registry() *CommandRegistry
Registry returns the plugin command registry.
func (*Dispatcher) SetAccountingHook ¶
func (d *Dispatcher) SetAccountingHook(h aaa.Accountant)
SetAccountingHook sets the accounting recorder for the dispatcher. When set, command START/STOP records are sent for every dispatched command. Accounting failures never block command execution.
func (*Dispatcher) SetAuditRecorder ¶
func (d *Dispatcher) SetAuditRecorder(recorder audit.Recorder)
SetAuditRecorder sets the structured audit recorder for mutation commands.
func (*Dispatcher) SetAuthorizer ¶
func (d *Dispatcher) SetAuthorizer(a aaa.Authorizer)
SetAuthorizer sets the authorization checker for the dispatcher. When set, all commands are checked against the authorizer before execution.
func (*Dispatcher) SetSubsystems ¶
func (d *Dispatcher) SetSubsystems(sm *SubsystemManager)
SetSubsystems sets the subsystem manager.
func (*Dispatcher) Subsystems ¶
func (d *Dispatcher) Subsystems() *SubsystemManager
Subsystems returns the subsystem manager.
type EngineEventHandler ¶
type EngineEventHandler func(payload any)
EngineEventHandler is invoked when a stream event matches an engine subscription. The payload is the publisher's typed Go value, passed as `any`. Consumers type-assert to the documented payload type for the (namespace, eventType) pair. Handlers are called synchronously from deliverEvent; they MUST NOT block on external I/O.
A handler that panics is recovered by the dispatch loop, logged, and the remaining handlers for the same event still fire. The panic does NOT propagate to the emitter.
type EnsureStep ¶
type EnsureStep struct {
Handler Handler // Creation handler (idempotent: succeeds if resource exists)
RollbackHandler Handler // Deletion handler for undo on descendant failure
}
EnsureStep describes one ancestor resource that must exist before a descendant command can execute. Built at registration time from the YANG command tree's ze:ensure-exists annotations.
type EventMonitorOpts ¶
type EventMonitorOpts struct {
IncludeTypes []string
ExcludeTypes []string
Peer string
Direction string
}
EventMonitorOpts holds parsed arguments for the event monitor command.
func ParseEventMonitorArgs ¶
func ParseEventMonitorArgs(args []string) (*EventMonitorOpts, error)
ParseEventMonitorArgs parses keyword arguments for the event monitor command.
Syntax: [include|exclude <types>] [peer <selector>] [direction received|sent] Keywords may appear in any order. Include and exclude are mutually exclusive.
type EventRecord ¶
EventRecord is one entry in the global event ring.
type EventRing ¶
type EventRing struct {
// contains filtered or unexported fields
}
EventRing is a fixed-size circular buffer of EventRecord values. Safe for concurrent use. Append is O(1) with no allocation.
func NewEventRing ¶
NewEventRing creates a ring with the given capacity.
func (*EventRing) NamespaceCounts ¶
NamespaceCounts returns a map of namespace -> event count.
func (*EventRing) SetOnAppend ¶
func (r *EventRing) SetOnAppend(fn func(EventRecord))
SetOnAppend registers a callback invoked after each Append, outside the lock. Used by the web SSE broker to push live log entries. The callback must not block; a slow callback delays the Append caller.
type FullReloadFunc ¶
FullReloadFunc runs the hub-level reload path for commits triggered through RPC. It includes plugin transactions plus ConfigProvider, engine, and subsystem refresh.
type Handler ¶
type Handler func(ctx *CommandContext, args []string) (*plugin.Response, error)
Handler processes a command and returns a response.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub orchestrates plugin communication and command routing.
func NewHub ¶
func NewHub(registry *SchemaRegistry, subsystems *SubsystemManager) *Hub
NewHub creates a new Hub with the given registry and subsystem manager.
func (*Hub) ProcessConfig ¶
func (h *Hub) ProcessConfig(ctx context.Context, blocks []ConfigBlock) error
ProcessConfig processes a configuration transaction. Sends all commands to plugins, then commits each affected namespace.
func (*Hub) RouteCommand ¶
func (h *Hub) RouteCommand(ctx context.Context, block *ConfigBlock) error
RouteCommand routes a command to the appropriate plugin. Format: <namespace> <path> <action> {json}.
func (*Hub) RouteCommit ¶
RouteCommit sends a commit command to a plugin. Format: <namespace> commit.
type ManagedConfigService ¶
type ManagedConfigService struct {
// contains filtered or unexported fields
}
ManagedConfigService handles hub-side config-fetch and config-changed operations for managed clients. It reads client configs via a ConfigReader and computes version hashes for change detection. Tracks connected clients and rejects duplicate names. Safe for concurrent use.
func NewManagedConfigService ¶
func NewManagedConfigService(reader ConfigReader) *ManagedConfigService
NewManagedConfigService creates a service that reads client configs via reader.
func (*ManagedConfigService) BuildConfigChanged ¶
func (s *ManagedConfigService) BuildConfigChanged(clientName string) (fleet.ConfigChanged, error)
BuildConfigChanged creates a config-changed notification for a client. Reads the client's current config and computes its version hash.
func (*ManagedConfigService) HandleConfigFetch ¶
func (s *ManagedConfigService) HandleConfigFetch(clientName string, req fleet.ConfigFetchRequest) (fleet.ConfigFetchResponse, error)
HandleConfigFetch processes a config-fetch request from a managed client. If the client's version matches the current config, returns status "current". Otherwise returns the full config as base64 with the new version hash.
func (*ManagedConfigService) RegisterClient ¶
func (s *ManagedConfigService) RegisterClient(name string) error
RegisterClient marks a client as connected. Returns ErrDuplicateClient if a client with the same name is already connected. Caller MUST call UnregisterClient when the client disconnects.
func (*ManagedConfigService) UnregisterClient ¶
func (s *ManagedConfigService) UnregisterClient(name string)
UnregisterClient removes a client from the connected set.
type ManagedServer ¶
type ManagedServer struct {
// contains filtered or unexported fields
}
ManagedServer authenticates managed fleet clients (per-client secret), answers config-fetch/config-ack/ping over MuxConn, and pushes config-changed to connected clients. It owns its listeners and one goroutine per connection.
func NewManagedServer ¶
func NewManagedServer(cfg ManagedServerConfig) (*ManagedServer, error)
NewManagedServer builds a managed server. ReadConfig is required. A self-signed TLS certificate is generated: the transport is encrypted, but a remote managed client cannot verify a self-signed cert against a CA, so today it must connect with tls-insecure. Verifiable server-cert distribution (CA cert or pinned fingerprint in the client config) is tracked in plan/spec-managed-server-hardening.md.
func (*ManagedServer) Addrs ¶
func (s *ManagedServer) Addrs() []net.Addr
Addrs returns the bound listener addresses (useful when a port-0 was requested, and for tests to discover the ephemeral port).
func (*ManagedServer) NotifyConfigChanged ¶
func (s *ManagedServer) NotifyConfigChanged(name string)
NotifyConfigChanged enqueues a config-changed push for the named client. It is non-blocking and safe to call from the storage write path: the round-trip runs on notifyWorker. On a full queue the notify is dropped (the client picks up the change on its next fetch/reconnect).
func (*ManagedServer) Start ¶
func (s *ManagedServer) Start(ctx context.Context) error
Start binds the listeners and begins serving in background goroutines. It returns once binding succeeds; serving continues until Stop or ctx cancellation.
func (*ManagedServer) Stop ¶
func (s *ManagedServer) Stop()
Stop cancels serving and waits for all goroutines to drain. Listeners are closed by closeOnDone when the context is canceled.
type ManagedServerConfig ¶
type ManagedServerConfig struct {
Addrs []string // Listen addresses (server blocks that declare client entries).
ClientSecrets map[string]string // Per-client name -> secret (authoritative for managed clients).
ReadConfig ConfigReader // Reads a client's config by name (over the hub blob store).
Metrics metrics.Registry // Optional; nil installs no-op counters.
}
ManagedServerConfig configures the dedicated managed-config TLS server.
type MonitorClient ¶
type MonitorClient struct {
EventChan chan string // Buffered channel for formatted events.
Ctx context.Context // Client-scoped context for cancellation.
Dropped atomic.Uint64 // Count of events dropped due to full channel.
// contains filtered or unexported fields
}
MonitorClient represents an active monitor session.
func NewMonitorClient ¶
func NewMonitorClient(ctx context.Context, id string, subs []*Subscription, bufSize int) *MonitorClient
NewMonitorClient creates a monitor client with the given subscriptions and buffer size. Caller MUST call MonitorManager.Remove(id) when done to release resources.
type MonitorManager ¶
type MonitorManager struct {
// contains filtered or unexported fields
}
MonitorManager manages active monitor clients. Parallel to SubscriptionManager (which manages plugin process subscriptions).
func NewMonitorManager ¶
func NewMonitorManager() *MonitorManager
NewMonitorManager creates a new monitor manager.
func (*MonitorManager) Add ¶
func (mm *MonitorManager) Add(mc *MonitorClient)
Add registers a monitor client.
func (*MonitorManager) Count ¶
func (mm *MonitorManager) Count() int
Count returns the number of active monitors.
func (*MonitorManager) Deliver ¶
func (mm *MonitorManager) Deliver(namespace, eventType, direction, peerAddr, peerName, output string)
Deliver sends a formatted event to all matching monitors. Uses non-blocking send: if a monitor's channel is full, the event is dropped and the dropped counter is incremented (backpressure). peerName is the configured peer name (may be empty).
func (*MonitorManager) DeliverLazy ¶
func (mm *MonitorManager) DeliverLazy(namespace, eventType, direction, peerAddr, peerName string, build func() string)
DeliverLazy sends an event to matching monitors, invoking build only when at least one monitor matches. This avoids formatting cost for events that no monitor subscribes to (the common case when structured plugin consumers are present but no CLI monitor is attached). build is called outside the manager lock so JSON formatting does not block monitor registration. peerName is the configured peer name (may be empty).
Race note: GetMatching releases mm.mu before build() and enqueue() run, so a concurrent Remove(id) may drop a monitor between matching and delivery. That is safe: enqueue uses a non-blocking send on a buffered channel that the removed client's reader will simply stop consuming on Ctx cancellation. The dropped counter on the removed client may tick up, which is harmless.
func (*MonitorManager) DeliverLazyTyped ¶
func (mm *MonitorManager) DeliverLazyTyped(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, peerAddr, peerName string, build func() string)
DeliverLazyTyped is the hot-path variant of DeliverLazy. It accepts pre-resolved typed IDs, skipping the string-to-ID lookups and their associated global event registry RLock acquisitions. Returns immediately via an atomic load when no monitors are registered (the common production case).
func (*MonitorManager) GetMatching ¶
func (mm *MonitorManager) GetMatching(namespace, eventType, direction, peerAddr, peerName string) []*MonitorClient
GetMatching returns monitors with subscriptions matching the event. A monitor matches if any of its subscriptions match. peerName is the configured peer name (may be empty).
func (*MonitorManager) GetMatchingTyped ¶
func (mm *MonitorManager) GetMatchingTyped(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, peerAddr, peerName string) []*MonitorClient
GetMatchingTyped returns monitors with subscriptions matching the event, using pre-resolved typed IDs. Avoids the string-to-ID lookups in GetMatching.
func (*MonitorManager) HasMonitors ¶
func (mm *MonitorManager) HasMonitors() bool
HasMonitors returns true if any monitor clients are registered. Uses an atomic load instead of acquiring the mutex, making it suitable for hot-path early-exit checks.
func (*MonitorManager) Remove ¶
func (mm *MonitorManager) Remove(id string)
Remove unregisters a monitor client by ID.
type MonitorProvider ¶
type MonitorProvider struct {
Prefix string
CreateFn func(ctx context.Context, args []string) (eventCh <-chan string, renderFn func(w, h int) string, cancel func(), err error)
}
MonitorProvider creates a TUI monitor session for a streaming command.
func GetMonitorProvider ¶
func GetMonitorProvider(input string) (*MonitorProvider, []string)
GetMonitorProvider returns a provider for the given command input, or nil.
type PeerFilter ¶
type PeerFilter struct {
Selector string // "*", "10.0.0.1", "!10.0.0.1", "my-peer", "!my-peer"
}
PeerFilter specifies which peers to filter.
func (*PeerFilter) Matches ¶
func (pf *PeerFilter) Matches(peerAddr, peerName string) bool
Matches returns true if the peer matches this filter. Matches against both the peer address (IP) and peer name.
type PendingRequest ¶
type PendingRequest struct {
Serial string // Alpha serial (a, b, bcd, ...)
Command string // Matched command name
Process *process.Process // Target process
Timeout time.Duration // Timeout for response
RespChan chan *plugin.Response // Channel to deliver response
// contains filtered or unexported fields
}
PendingRequest represents an in-flight plugin command request.
type PendingRequests ¶
type PendingRequests struct {
// contains filtered or unexported fields
}
PendingRequests tracks in-flight plugin command requests. Thread-safe for concurrent access.
func NewPendingRequests ¶
func NewPendingRequests() *PendingRequests
NewPendingRequests creates a new pending requests tracker.
func (*PendingRequests) Add ¶
func (p *PendingRequests) Add(req *PendingRequest) string
Add registers a new pending request and starts the timeout timer. Returns the assigned alpha serial, or empty string if limit exceeded. If limit exceeded, sends error response to RespChan.
func (*PendingRequests) CancelAll ¶
func (p *PendingRequests) CancelAll(proc *process.Process)
CancelAll cancels all pending requests for a process (process death). Sends error response to all waiting clients.
func (*PendingRequests) Complete ¶
func (p *PendingRequests) Complete(serial string, resp *plugin.Response) bool
Complete delivers a final response and removes the request. Returns true if the serial was found (response delivered).
func (*PendingRequests) Count ¶
func (p *PendingRequests) Count(proc *process.Process) int
Count returns the number of pending requests for a process.
func (*PendingRequests) Partial ¶
func (p *PendingRequests) Partial(serial string, resp *plugin.Response) bool
Partial delivers a partial response (streaming) and resets the timeout. Returns true if the serial was found.
func (*PendingRequests) Total ¶
func (p *PendingRequests) Total() int
Total returns the total number of pending requests.
type ProcessCleanupFunc ¶
type ProcessCleanupFunc func(processName string)
ProcessCleanupFunc is called when a plugin process exits. Receives the process name for scoped cleanup.
type QuiesceFunc ¶
QuiesceFunc drains a subsystem's pending asynchronous work, returning when the subsystem has settled or ctx is canceled (deadline reached).
A QuiesceFunc MUST honor ctx cancellation. quiesceAll bounds each drain with a per-quiescer deadline by canceling ctx, but it cannot force-return a drain that ignores ctx — such a quiescer would hang the barrier (and the caller) despite the timeout. The only current registrant, the reactor's FlushForwardPool, selects on ctx.Done() (forward_pool_barrier.go).
type Quiescer ¶
type Quiescer struct {
Name string
Quiesce QuiesceFunc
}
Quiescer is a named subsystem drain invoked by `request quiesce`.
type QuiescerRegistry ¶
type QuiescerRegistry struct {
// contains filtered or unexported fields
}
QuiescerRegistry holds subsystem drains invoked by `request quiesce`. Registration is at runtime (a subsystem needs a live reference such as the reactor), so this is a lock-guarded registry rather than an init() table.
func (*QuiescerRegistry) All ¶
func (r *QuiescerRegistry) All() []Quiescer
All returns a snapshot of the registered quiescers.
func (*QuiescerRegistry) Register ¶
func (r *QuiescerRegistry) Register(name string, fn QuiesceFunc)
Register adds a named subsystem drain. Safe for concurrent use.
type RPCParams ¶
type RPCParams struct {
Selector string `json:"selector,omitempty"` // Peer selector (optional)
Args []string `json:"args,omitempty"` // Command arguments (optional)
}
RPCParams is the standard params format for JSON RPC requests from socket clients. Handlers receive Args as positional arguments and Selector as the peer filter. Identity (Username) is never accepted from client JSON -- it MUST be injected by the transport layer (SSH session, plugin process manager, TLS auth).
type RPCRegistration ¶
type RPCRegistration struct {
WireMethod string // "module:rpc-name" format (e.g., "ze-bgp:peer-list")
Handler Handler // Handler function
RequiresSelector bool // True if peer commands must have explicit selector (not default "*")
PluginCommand string // If set, this builtin proxies to a runtime plugin command (e.g., "bgp rib show")
}
RPCRegistration maps a YANG RPC wire method to its handler function. The CLI command name is derived from the YANG command tree (-cmd.yang modules) via yang.WireMethodToPath(). It is not stored in the registration. Help text comes from YANG descriptions. Read-only classification comes from the verb position in the command tree (show/validate/monitor = read-only).
func AllBuiltinRPCs ¶
func AllBuiltinRPCs() []RPCRegistration
AllBuiltinRPCs returns all RPCs registered via init() + RegisterRPCs(). Includes server, handler, and editor RPCs (when their packages are imported).
type RegisterOptions ¶
type RegisterOptions struct {
ReadOnly bool // True if command only reads state
RequiresSelector bool // True if the command requires an explicit selector value
PluginProxy bool // True if this builtin proxies to a plugin command (allows plugin to register same name)
ArgDefs []command.ArgDef // Typed argument definitions from YANG leaves
}
RegisterOptions holds optional settings for command registration.
type RegisterResult ¶
type RegisterResult struct {
Name string // Command that was registered
OK bool // True if registration succeeded
Error string // Error message if failed
}
RegisterResult holds the result of a single command registration.
type RegisteredCommand ¶
type RegisteredCommand struct {
Name string
LowerName string // Pre-lowercased at registration for dispatch matching (zero alloc per lookup)
Description string
Args string // Usage hint (e.g., "<component>")
Completable bool // Process handles arg completion
Hidden bool // Hidden from completion and help (works when typed in full)
Timeout time.Duration // Per-command timeout
Process *process.Process // Owning process
RegisteredAt time.Time
}
RegisteredCommand represents a plugin command in the registry.
type RegisteredNotification ¶
type RegisteredNotification struct {
Module string // YANG module name
Name string // Notification name in kebab-case
WireMethod string // Wire format "module:notification-name"
Description string // From YANG description
Leaves []yang.LeafMeta // Notification data leaves
}
RegisteredNotification represents a notification indexed in the schema registry.
type RegisteredRPC ¶
type RegisteredRPC struct {
Module string // YANG module name (e.g., "ze-bgp-api")
Name string // RPC name in kebab-case (e.g., "peer-list")
WireMethod string // Wire format "module:rpc-name" (e.g., "ze-bgp:peer-list")
CLICommand string // CLI text command (e.g., "bgp peer list")
Description string // From YANG description
Input []yang.LeafMeta // Input parameter leaves
Output []yang.LeafMeta // Output parameter leaves
Handler Handler // Handler function (set during registration)
}
RegisteredRPC represents an RPC indexed in the schema registry.
type Schema ¶
type Schema struct {
Module string // YANG module name
Namespace string // YANG namespace URI
Yang string // Full YANG module text
Imports []string // Imported module names (from YANG import statements)
Handlers []string // Handler paths (e.g., "bgp", "bgp/peer")
Plugin string // Plugin that registered this schema
Priority int // Config ordering (lower = processed first, default 1000)
WantsConfig []string // Config roots plugin wants (from "declare wants config <root>")
}
Schema represents a YANG schema registered by a plugin.
type SchemaRegistry ¶
type SchemaRegistry struct {
// contains filtered or unexported fields
}
SchemaRegistry stores and manages schemas from all plugins.
func NewSchemaRegistry ¶
func NewSchemaRegistry() *SchemaRegistry
NewSchemaRegistry creates a new schema registry.
func (*SchemaRegistry) Count ¶
func (r *SchemaRegistry) Count() int
Count returns the number of registered schemas.
func (*SchemaRegistry) FindHandler ¶
func (r *SchemaRegistry) FindHandler(path string) (*Schema, string)
FindHandler returns the schema for a handler path using longest prefix match. For example, if "bgp" and "bgp/peer" are registered, FindHandler("bgp/peer/timers") returns the schema for "bgp/peer". Predicates like [address=192.0.2.1] are stripped before matching. After Freeze(), uses lock-free atomic.Load on the frozen snapshot.
func (*SchemaRegistry) FindRPC ¶
func (r *SchemaRegistry) FindRPC(wireMethod string) (*RegisteredRPC, error)
FindRPC returns the registered RPC for an exact wire method match.
func (*SchemaRegistry) FindRPCByCommand ¶
func (r *SchemaRegistry) FindRPCByCommand(cliCommand string) (*RegisteredRPC, error)
FindRPCByCommand returns the registered RPC for a CLI text command.
func (*SchemaRegistry) Freeze ¶
func (r *SchemaRegistry) Freeze()
Freeze creates an immutable snapshot of the handler and module maps. After Freeze(), FindHandler uses atomic.Load instead of RLock. MUST be called after all Register calls complete (after startup barrier). Safe to call multiple times (each call overwrites the previous snapshot).
func (*SchemaRegistry) GetByHandler ¶
func (r *SchemaRegistry) GetByHandler(path string) (*Schema, error)
GetByHandler returns a schema by exact handler path.
func (*SchemaRegistry) GetByModule ¶
func (r *SchemaRegistry) GetByModule(name string) (*Schema, error)
GetByModule returns a schema by module name.
func (*SchemaRegistry) ListHandlers ¶
func (r *SchemaRegistry) ListHandlers() map[string]string
ListHandlers returns all registered handler paths with their modules.
func (*SchemaRegistry) ListModules ¶
func (r *SchemaRegistry) ListModules() []string
ListModules returns all registered module names.
func (*SchemaRegistry) ListNotifications ¶
func (r *SchemaRegistry) ListNotifications(module string) []*RegisteredNotification
ListNotifications returns all registered notifications, optionally filtered by YANG module name. Pass empty string to list all notifications.
func (*SchemaRegistry) ListRPCs ¶
func (r *SchemaRegistry) ListRPCs(module string) []*RegisteredRPC
ListRPCs returns all registered RPCs, optionally filtered by YANG module name. Pass empty string to list all RPCs.
func (*SchemaRegistry) Register ¶
func (r *SchemaRegistry) Register(schema *Schema) error
Register adds a schema to the registry. Returns error if module name or handler paths conflict with existing registrations.
func (*SchemaRegistry) RegisterCLICommand ¶
func (r *SchemaRegistry) RegisterCLICommand(cliCommand, wireMethod string) error
RegisterCLICommand associates a CLI text command with a wire method. The wire method must already be registered via RegisterRPCs.
func (*SchemaRegistry) RegisterNotifications ¶
func (r *SchemaRegistry) RegisterNotifications(module string, notifs []yang.NotificationMeta) error
RegisterNotifications indexes notifications extracted from a YANG module.
func (*SchemaRegistry) RegisterRPCs ¶
func (r *SchemaRegistry) RegisterRPCs(module string, rpcs []yang.RPCMeta) error
RegisterRPCs indexes RPCs extracted from a YANG module. Wire methods use the stripped module prefix (e.g., "ze-bgp-api" → "ze-bgp:peer-list").
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server manages API connections and command dispatch.
func NewServer ¶
func NewServer(config *ServerConfig, reactor plugin.ReactorLifecycle) (*Server, error)
NewServer creates a new API server.
func (*Server) AllPluginCapabilities ¶
func (s *Server) AllPluginCapabilities() []plugin.InjectedCapability
AllPluginCapabilities returns all stored capabilities (global + all per-peer). Used by the restart handler to compute max restart-time for the GR marker.
func (*Server) CallDoctorCheck ¶
func (s *Server) CallDoctorCheck(ctx context.Context, pluginName, checkName string) (*rpc.DoctorCheckOutput, error)
CallDoctorCheck invokes a plugin's doctor check callback and returns diagnostics.
func (*Server) CallFilterUpdate ¶
func (s *Server) CallFilterUpdate(ctx context.Context, pluginName string, input *rpc.FilterUpdateInput) (*rpc.FilterUpdateOutput, error)
CallFilterUpdate sends a filter-update RPC to a named plugin and returns the response. Returns an error if the plugin is not found, not connected, or the RPC fails.
func (*Server) CommitManager ¶
CommitManager returns the commit manager.
func (*Server) ConfigPath ¶
ConfigPath returns the path to the config file. Empty if not set.
func (*Server) Context ¶
Context returns the server's context. Used by RPC handlers that need a cancellable context tied to the server's lifetime (e.g., coordinator reload).
func (*Server) DecodeNLRI ¶
DecodeNLRI decodes NLRI by routing to the appropriate family plugin via RPC. Returns the JSON representation of the decoded NLRI. Returns error if no plugin registered or plugin not running.
func (*Server) Dispatcher ¶
func (s *Server) Dispatcher() *Dispatcher
Dispatcher returns the command dispatcher.
func (*Server) DoctorCheckPlugins ¶
func (s *Server) DoctorCheckPlugins() map[string][]plugin.DoctorCheckRegistration
DoctorCheckPlugins returns plugin names and their doctor check registrations.
func (*Server) DrainSIGHUP ¶
DrainSIGHUP returns true if a SIGHUP was queued and clears the flag.
func (*Server) Emit ¶
Emit satisfies the pkg/ze.EventBus interface. It is a thin alias for EmitEngineEvent so engine components can depend on the public ze.EventBus type without importing this package directly.
func (*Server) EmitEngineEvent ¶
EmitEngineEvent publishes an event from the engine to the stream system. Both engine subscribers and plugin process subscribers receive it. Returns the number of plugin processes that received the event (engine handler count is intentionally not reported because engine subscribers are in-process and always receive synchronously when matching).
The event must use a registered (namespace, eventType) per events.IsValidEvent; unknown pairs return an error and deliver to nobody (neither engine handlers nor plugin subscribers).
payload is the publisher's typed Go value. In-process subscribers receive it directly; plugin-process subscribers receive JSON bytes marshaled once per Emit (only when at least one plugin-process subscriber exists).
func (*Server) EncodeNLRI ¶
EncodeNLRI encodes NLRI by routing to the appropriate family plugin via RPC. Returns error if no plugin registered or plugin not running.
func (*Server) FilterInfo ¶
FilterInfo returns declaration info for a named filter: declared attributes and raw flag. Returns nil attributes and false if the plugin or filter is not found.
func (*Server) FilterOnError ¶
func (s *Server) FilterOnError(pluginName, filterName string) rpc.OnErrorPolicy
FilterOnError returns the declared on-error mode for a named filter. Returns rpc.OnErrorReject (fail-closed) if the plugin or filter is not found.
func (*Server) GetDecodeFamilies ¶
GetDecodeFamilies returns all families that have decode plugins registered. Used by Session to auto-add Multiprotocol capabilities in OPEN. Plugins that can decode a family should advertise that family to peers.
func (*Server) GetPluginCapabilitiesForPeer ¶
func (s *Server) GetPluginCapabilitiesForPeer(peerAddr string) []plugin.InjectedCapability
GetPluginCapabilitiesForPeer returns plugin-declared capabilities for a specific peer. Returns global capabilities plus any peer-specific capabilities (per-peer takes precedence).
func (*Server) GetSchemaDeclarations ¶
func (s *Server) GetSchemaDeclarations() []plugin.SchemaDeclaration
GetSchemaDeclarations returns all schema declarations from registered plugins. Used for two-phase config parsing to extend the schema before parsing peer config. Should be called after Stage 1 (Registration) completes for all plugins.
func (*Server) HandleAdHocPluginSession ¶
func (s *Server) HandleAdHocPluginSession(reader io.ReadCloser, writer io.WriteCloser) error
HandleAdHocPluginSession runs the 5-stage plugin handshake and runtime command loop over an arbitrary bidirectional stream (e.g., an SSH channel). The session uses coordinator == nil, so all stage barriers are skipped. Blocks until the connection closes or the server shuts down. Caller MUST close reader and writer after this returns.
func (*Server) HasConfigLoader ¶
HasConfigLoader reports whether a config loader has been set. Used by SIGHUP handler to decide between coordinator path and direct reload.
func (*Server) HasFullReloadFunc ¶
HasFullReloadFunc reports whether a hub-level reload hook has been set.
func (*Server) HasProcesses ¶
HasProcesses returns true if any plugin processes were loaded during startup. Used by the main loop to decide whether to listen for server-done (all processes exited). Without this, configs with no plugins cause immediate daemon exit.
func (*Server) MarkReloadProcessed ¶
MarkReloadProcessed records that a reload sequence completed and advances the generation counter. `applied` is false when the reload returned an error.
MUST be called only once the ENTIRE reload sequence has run, not merely the plugin-server half: the config knobs a reload rejects are diffed by the subsystems that engine.Reload fans out to, which runs AFTER Server.ReloadConfig. Marking any earlier would advance the fence before the rejection it is meant to fence had happened, and an observer could then read state the reload had not yet touched. cmd/ze/hub/main_reload.go doReload is the correct (and only) caller.
A reload refused with ErrReloadInProgress was never processed -- it is queued and replayed -- so its caller must not mark it.
func (*Server) Monitors ¶
func (s *Server) Monitors() *MonitorManager
Monitors returns the monitor manager for CLI monitor sessions.
func (*Server) ProcessManager ¶
func (s *Server) ProcessManager() *process.ProcessManager
ProcessManager returns the process manager. Used by BGP hook implementations to iterate plugin processes.
func (*Server) QueueSIGHUP ¶
func (s *Server) QueueSIGHUP()
QueueSIGHUP queues a SIGHUP for later processing if a transaction is active.
func (*Server) Reactor ¶
func (s *Server) Reactor() plugin.ReactorLifecycle
func (*Server) ReactorAny ¶
ReactorAny returns the reactor as any, satisfying registry.PluginServerAccessor.
func (*Server) ReactorFor ¶
ReactorFor returns a named protocol reactor from the Coordinator, or nil. This allows plugins to access non-BGP reactors (e.g., OSPF, IS-IS) by name.
func (*Server) RegisterQuiescer ¶
func (s *Server) RegisterQuiescer(name string, fn QuiesceFunc)
RegisterQuiescer registers a named subsystem drain, invoked by `request quiesce`. Called at wiring time (e.g. when the reactor is attached to the server), not from init(), because the drain closes over a live reference.
func (*Server) ReloadConfig ¶
ReloadConfig orchestrates config reload across all config-interested plugins. Follows verify→apply protocol: all plugins must verify before any apply. Returns nil if there are no changes, or if verify→apply succeeds. Returns error if verify fails for any plugin, or if a reload is already in progress.
func (*Server) ReloadFromDisk ¶
ReloadFromDisk loads the config from the configured loader and triggers reload. Returns error if the loader is not set, parsing fails, or reload fails.
func (*Server) ReloadFull ¶
ReloadFull runs the hub-level reload hook.
func (*Server) ReloadStatus ¶
ReloadStatus returns the number of reloads processed since daemon start, the outcome of the most recent one, and when it finished. Before the first reload: (0, ReloadOutcomeNone, zero time).
An observer fences on the generation: read it, trigger a reload, then poll until it advances. At that point every reload step has run, so the resulting state (or the deliberate absence of a change) is safe to assert.
func (*Server) SetCommitManager ¶
SetCommitManager sets the commit manager. Called by the BGP plugin during configuration to inject a CommitManager created with BGP-specific types. MUST be called before any RPC dispatch (i.e., during init-time registration). NOT safe for concurrent use with CommitManager().
func (*Server) SetConfigLoader ¶
func (s *Server) SetConfigLoader(loader ConfigLoader)
SetConfigLoader sets the function used by ReloadFromDisk to load the config tree.
func (*Server) SetFullReloadFunc ¶
func (s *Server) SetFullReloadFunc(fn FullReloadFunc)
SetFullReloadFunc sets the function used by daemon-reload RPC when the hub is wired.
func (*Server) SetProcessSpawner ¶
func (s *Server) SetProcessSpawner(sp plugin.ProcessSpawner)
SetProcessSpawner sets the PluginManager as the process spawner. When set, runPluginPhase delegates process creation to the spawner instead of creating ProcessManager directly. Must be called before Start. If the spawner supports SetMetricsRegistry (e.g., PluginManager), the server's metrics registry is forwarded for plugin health metrics.
func (*Server) SetRebootFunc ¶
func (s *Server) SetRebootFunc(fn func())
SetRebootFunc sets the function called for "daemon reboot" commands. Called by the daemon to wire graceful shutdown + OS reboot.
func (*Server) SetShutdownFunc ¶
func (s *Server) SetShutdownFunc(fn func())
SetShutdownFunc sets a reactor-independent daemon-shutdown callback. The daemon wires it (ungated by BGP) to the same signal-based teardown SIGTERM triggers, so `request shutdown` stops a reactorless daemon (OSPF-only, etc.).
func (*Server) StartWithContext ¶
StartWithContext begins accepting connections with the given context. External access is via SSH; the plugin server handles only in-process dispatch.
func (*Server) Stop ¶
func (s *Server) Stop()
Stop signals the server to stop and cleans up resources.
func (*Server) Subscribe ¶
Subscribe satisfies the pkg/ze.EventBus interface. It is a thin alias for SubscribeEngineEvent that adapts the handler signature from EngineEventHandler (a named type) to a plain func, which is what ze.EventBus declares.
func (*Server) SubscribeEngineEvent ¶
func (s *Server) SubscribeEngineEvent(namespace, eventType string, handler EngineEventHandler) func()
SubscribeEngineEvent registers an engine-side handler for stream events matching the given namespace and event type. The returned function unregisters the handler when called; safe to call multiple times.
Handlers fire synchronously from deliverEvent. They must not block on external I/O. The handler receives the publisher's typed payload via `any`; consumers type-assert to the canonical type documented next to the event constant in the publishing package.
Engine subscriptions are parallel to plugin process subscriptions managed by SubscriptionManager. Both fire on the same deliverEvent call.
Subscriptions are NOT validated against the event registry: subscribing to an unknown (namespace, eventType) pair, or to a per-plugin event type that is not yet registered, succeeds silently. Such a subscription is dead until the matching emit arrives. This avoids races with per-plugin event types like "verify-bgp" that are registered dynamically when the plugin starts.
Engine subscribers receive ALL events for the given (namespace, eventType) regardless of direction or peer address. Plugin process subscribers can filter on direction and peer; engine subscribers cannot. This is intended for engine-internal coordination (e.g. config transactions) where direction has no meaning.
A nil handler is rejected: the call returns a no-op unsubscribe function without registering anything. This catches programmer errors loudly via "the handler I just registered never fires" rather than via a nil-pointer panic at first dispatch.
func (*Server) Subscriptions ¶
func (s *Server) Subscriptions() *SubscriptionManager
Subscriptions returns the subscription manager.
func (*Server) UpdateProtocolConfig ¶
UpdateProtocolConfig sets protocol-specific auto-load configuration after the reactor has parsed settings. Called by the protocol plugin's RunEngine after creating the reactor, so that family/event/send auto-load phases have the data.
func (*Server) WaitForStartupComplete ¶
WaitForStartupComplete blocks until all plugin startup phases are done. Returns a non-nil error if a config-path plugin failed during startup (e.g., invalid BGP config) or if the context deadline is exceeded.
type ServerConfig ¶
type ServerConfig struct {
ConfigPath string // Path to config file (for peer save)
Plugins []plugin.PluginConfig // External plugins to spawn
ConfiguredFamilies []string // Families configured on peers (for deferred auto-load)
ConfiguredCustomEvents []string // Custom event types in peer receive config (for auto-load)
ConfiguredCustomSendTypes []string // Custom send types in peer send config (for auto-load)
ConfiguredPaths []string // Top-level config sections present (for config-driven auto-load)
Hub *plugin.HubConfig // TLS transport config (nil = no TLS listener)
MetricsRegistry metrics.Registry // Prometheus metrics registry (nil = metrics disabled)
}
ServerConfig holds API server configuration.
type StreamingHandler ¶
type StreamingHandler func(ctx context.Context, s *Server, w io.Writer, username string, args []string) error
StreamingHandler handles streaming commands (e.g., monitor). ctx is the session context, s is the plugin server, w is the output writer, username is the authenticated SSH user (for authorization), args are command arguments.
func GetStreamingHandlerForCommand ¶
func GetStreamingHandlerForCommand(input string) (StreamingHandler, []string)
GetStreamingHandlerForCommand returns the handler and extracted args for a command. Matches the longest registered prefix. Returns (nil, nil) if no prefix matches.
type Subscription ¶
type Subscription struct {
Namespace events.NamespaceID // compact ID assigned at registration time
EventType events.EventTypeID // compact ID assigned at registration time
Direction events.Direction // typed enum (DirReceived, DirSent, DirBoth)
PeerFilter *PeerFilter // nil = all peers
PluginFilter string // plugin name filter (empty = all)
}
Subscription represents an event subscription.
func BuildEventMonitorSubscriptions ¶
func BuildEventMonitorSubscriptions(opts *EventMonitorOpts) []*Subscription
BuildEventMonitorSubscriptions creates subscriptions from parsed options. With no include/exclude filter, subscribes to all event types across all namespaces. With include, subscribes only to those types (in whichever namespaces they exist). With exclude, subscribes to all types except those listed.
func ParseSubscription ¶
func ParseSubscription(args []string) (*Subscription, error)
ParseSubscription parses a subscribe/unsubscribe command. Format: [peer <sel> | plugin <name>] [<namespace>] event <type> [direction received|sent|both]. Namespace defaults to "bgp" when peer is set.
func (*Subscription) Equals ¶
func (s *Subscription) Equals(other *Subscription) bool
Equals returns true if two subscriptions are identical.
func (*Subscription) Matches ¶
func (s *Subscription) Matches(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, peerAddr, peerName string) bool
Matches returns true if this subscription matches the event. peerAddr is the peer's IP address; peerName is the configured peer name (may be empty).
type SubscriptionManager ¶
type SubscriptionManager struct {
// contains filtered or unexported fields
}
SubscriptionManager tracks subscriptions per process.
func NewSubscriptionManager ¶
func NewSubscriptionManager() *SubscriptionManager
NewSubscriptionManager creates a new subscription manager.
func (*SubscriptionManager) Add ¶
func (sm *SubscriptionManager) Add(proc *process.Process, sub *Subscription)
Add adds a subscription for a process.
func (*SubscriptionManager) ClearProcess ¶
func (sm *SubscriptionManager) ClearProcess(proc *process.Process)
ClearProcess removes all subscriptions for a process.
func (*SubscriptionManager) Count ¶
func (sm *SubscriptionManager) Count(proc *process.Process) int
Count returns the number of subscriptions for a process.
func (*SubscriptionManager) GetMatching ¶
func (sm *SubscriptionManager) GetMatching(ns events.NamespaceID, et events.EventTypeID, dir events.Direction, peerAddr, peerName string) []*process.Process
GetMatching returns all processes with subscriptions matching the event. peerName is the configured peer name (may be empty for non-BGP events or emit-event RPCs).
func (*SubscriptionManager) GetSubscriptions ¶
func (sm *SubscriptionManager) GetSubscriptions(proc *process.Process) []*Subscription
GetSubscriptions returns all subscriptions for a process.
func (*SubscriptionManager) Remove ¶
func (sm *SubscriptionManager) Remove(proc *process.Process, sub *Subscription) bool
Remove removes a subscription for a process. Returns true if the subscription was found and removed.
type SubsystemConfig ¶
type SubsystemConfig struct {
Name string // Subsystem name (cache, route, session)
Binary string // Path to binary or full command
Commands []string // Commands this subsystem handles (for pre-registration)
ConfigPath string // Config file path (passed to child process)
}
SubsystemConfig describes a forked subsystem process.
type SubsystemHandler ¶
type SubsystemHandler struct {
// contains filtered or unexported fields
}
SubsystemHandler wraps a forked process that handles a subset of commands. It spawns the subprocess, completes the 5-stage protocol, and routes commands to it via pipes.
func NewSubsystemHandler ¶
func NewSubsystemHandler(config SubsystemConfig) *SubsystemHandler
NewSubsystemHandler creates a handler backed by a forked process.
func (*SubsystemHandler) Commands ¶
func (h *SubsystemHandler) Commands() []string
Commands returns the commands this subsystem handles.
func (*SubsystemHandler) Handle ¶
Handle sends a command to the subsystem via RPC and returns the response.
func (*SubsystemHandler) Name ¶
func (h *SubsystemHandler) Name() string
Name returns the subsystem name.
func (*SubsystemHandler) Running ¶
func (h *SubsystemHandler) Running() bool
Running returns true if the subsystem process is running.
func (*SubsystemHandler) Schema ¶
func (h *SubsystemHandler) Schema() *plugin.PluginSchemaDecl
Schema returns the YANG schema declared by this subsystem, or nil if none.
func (*SubsystemHandler) Signal ¶
func (h *SubsystemHandler) Signal(sig os.Signal) error
Signal sends an OS signal to the subsystem's external process. Returns an error if the process is not running or is internal (goroutine).
func (*SubsystemHandler) Start ¶
func (h *SubsystemHandler) Start(ctx context.Context) error
Start spawns the subsystem process and completes the 5-stage protocol.
func (*SubsystemHandler) Stop ¶
func (h *SubsystemHandler) Stop()
Stop terminates the subsystem process.
type SubsystemManager ¶
type SubsystemManager struct {
// contains filtered or unexported fields
}
SubsystemManager manages multiple subsystem handlers.
func NewSubsystemManager ¶
func NewSubsystemManager() *SubsystemManager
NewSubsystemManager creates a new subsystem manager.
func (*SubsystemManager) AllCommands ¶
func (m *SubsystemManager) AllCommands() []string
AllCommands returns all commands from all subsystems.
func (*SubsystemManager) AllSchemas ¶
func (m *SubsystemManager) AllSchemas() []*Schema
AllSchemas returns all schemas from all subsystems.
func (*SubsystemManager) FindHandler ¶
func (m *SubsystemManager) FindHandler(command string) *SubsystemHandler
FindHandler returns the handler for a given command, or nil if not found. After Freeze(), uses lock-free atomic.Load on the frozen snapshot.
func (*SubsystemManager) Freeze ¶
func (m *SubsystemManager) Freeze()
Freeze creates an immutable snapshot of the handler map. After Freeze(), Get and FindHandler use atomic.Load instead of RLock. MUST be called after all Register calls complete (after startup barrier). Safe to call multiple times (each call overwrites the previous snapshot).
func (*SubsystemManager) Get ¶
func (m *SubsystemManager) Get(name string) *SubsystemHandler
Get returns a subsystem handler by name. After Freeze(), uses lock-free atomic.Load on the frozen snapshot.
func (*SubsystemManager) Names ¶
func (m *SubsystemManager) Names() []string
Names returns the names of all registered subsystems.
func (*SubsystemManager) Register ¶
func (m *SubsystemManager) Register(config SubsystemConfig)
Register adds a subsystem configuration.
func (*SubsystemManager) RegisterSchemas ¶
func (m *SubsystemManager) RegisterSchemas(registry *SchemaRegistry) error
RegisterSchemas registers all subsystem schemas with the given registry.
func (*SubsystemManager) Replace ¶
func (m *SubsystemManager) Replace(name string, handler *SubsystemHandler)
Replace swaps in an already-constructed handler and stops the previous one after publishing the replacement. Used by reload paths that pre-start a replacement before disrupting the old subsystem.
func (*SubsystemManager) StartAll ¶
func (m *SubsystemManager) StartAll(ctx context.Context) error
StartAll starts all registered subsystems.
func (*SubsystemManager) StopAll ¶
func (m *SubsystemManager) StopAll()
StopAll stops all subsystems.
func (*SubsystemManager) Unregister ¶
func (m *SubsystemManager) Unregister(name string)
Unregister stops and removes a subsystem by name. No-op if the name is not registered. If frozen, publishes a new snapshot reflecting the removal.
Source Files
¶
- adhoc.go
- command.go
- command_registry.go
- config.go
- config_tx_bridge.go
- dispatch.go
- dispatch_cached.go
- dispatch_registry.go
- dispatch_route.go
- doc.go
- engine_event.go
- engine_event_gateway.go
- enricher.go
- ensure.go
- event_monitor.go
- event_ring.go
- events.go
- handler.go
- hub.go
- managed.go
- managed_serve.go
- monitor.go
- pending.go
- plugin_rpc.go
- quiesce.go
- register.go
- reload.go
- reload_generation.go
- reload_tx.go
- rpc_register.go
- schema.go
- server.go
- session.go
- startup.go
- startup_autoload.go
- startup_driver.go
- subscribe.go
- subsystem.go
- system.go