Documentation
¶
Overview ¶
Package debug provides controller-specific debug variable implementations.
This package integrates the generic pkg/introspection infrastructure with controller-specific state. It defines:
- StateProvider interface for accessing controller internal state
- Var implementations (ConfigVar, RenderedVar, etc.)
- Event buffer for tracking recent events
- Registration logic for publishing variables
The controller implements StateProvider and provides thread-safe access to its internal state (config, rendered output, resources, etc.).
Index ¶
- Constants
- func RegisterEventsHandler(server *introspection.Server, eventBuffer *EventBuffer)
- func RegisterVariables(registry *introspection.Registry, provider StateProvider, ...)
- type DeploymentStatus
- type ErrorInfo
- type ErrorSummary
- type Event
- type EventBuffer
- type EventsVar
- type FailedEndpoint
- type PipelineStatus
- type RenderingStatus
- type StateProvider
- type TriggerStatus
- type ValidatedConfigInfo
- type ValidationStatus
Constants ¶
const ComponentName = "event-buffer"
ComponentName is the unique identifier for the event buffer component.
Variables ¶
This section is empty.
Functions ¶
func RegisterEventsHandler ¶
func RegisterEventsHandler(server *introspection.Server, eventBuffer *EventBuffer)
RegisterEventsHandler registers the /debug/events endpoint with correlation query support.
This handler supports:
- GET /debug/events - Returns last 100 events
- GET /debug/events?limit=N - Returns last N events
- GET /debug/events?correlation_id=<id> - Returns events with matching correlation ID
Example:
debug.RegisterEventsHandler(server, eventBuffer) go server.Start(ctx)
func RegisterVariables ¶
func RegisterVariables( registry *introspection.Registry, provider StateProvider, eventBuffer *EventBuffer, )
RegisterVariables registers all controller debug variables with the registry.
This function should be called during controller initialization, after components are set up but before the debug server starts.
Registered variables:
- config: Current controller configuration
- credentials: Credential metadata (not actual values)
- rendered: Last rendered HAProxy config
- auxfiles: Auxiliary files (SSL, maps, etc.)
- resources: Resource counts by type
- events: Recent events (default: last 100)
- state: Full state dump (use carefully - large response)
- uptime: Time since controller started
- pipeline: Reconciliation pipeline status (trigger, render, validate, deploy)
- validated: Last successfully validated HAProxy config
- errors: Aggregated error summary across all phases
Example:
registry := introspection.NewRegistry()
eventBuffer := debug.NewEventBuffer(1000, bus)
debug.RegisterVariables(registry, controller, eventBuffer)
server := introspection.NewServer(":6060", registry)
go server.Start(ctx)
Types ¶
type DeploymentStatus ¶
type DeploymentStatus struct {
Status string `json:"status"` // "succeeded" | "failed" | "skipped" | "pending"
Reason string `json:"reason,omitempty"`
Timestamp time.Time `json:"timestamp"`
DurationMs int64 `json:"duration_ms,omitempty"`
EndpointsTotal int `json:"endpoints_total"`
EndpointsSucceeded int `json:"endpoints_succeeded"`
EndpointsFailed int `json:"endpoints_failed"`
FailedEndpoints []FailedEndpoint `json:"failed_endpoints,omitempty"`
}
DeploymentStatus represents the deployment phase status.
type ErrorSummary ¶
type ErrorSummary struct {
ConfigParseError *ErrorInfo `json:"config_parse_error,omitempty"`
TemplateRenderError *ErrorInfo `json:"template_render_error,omitempty"`
HAProxyValidationError *ErrorInfo `json:"haproxy_validation_error,omitempty"`
DeploymentErrors []ErrorInfo `json:"deployment_errors,omitempty"`
LastErrorTimestamp time.Time `json:"last_error_timestamp"`
}
ErrorSummary provides an aggregated view of recent errors across all phases.
type Event ¶
type Event struct {
Timestamp time.Time `json:"timestamp"`
Type string `json:"type"`
Summary string `json:"summary"`
Details any `json:"details,omitempty"`
CorrelationID string `json:"correlation_id,omitempty"`
}
Event represents a debug event with timestamp and details.
This is a simplified representation of controller events for debug purposes. It captures the essential information without exposing internal event structures.
type EventBuffer ¶
type EventBuffer struct {
// contains filtered or unexported fields
}
EventBuffer maintains a ring buffer of recent events for debug purposes.
This is separate from the EventCommentator's ring buffer to avoid coupling debug functionality to the commentator component. It subscribes to the EventBus and stores simplified event representations.
func NewEventBuffer ¶
func NewEventBuffer(size int, eventBus *busevents.EventBus) *EventBuffer
NewEventBuffer creates a new event buffer with the specified capacity.
The buffer subscribes to all events from the EventBus and stores the last N events (where N is the size parameter).
Note: The buffer subscribes during construction per CLAUDE.md guidelines to ensure subscription happens before EventBus.Start() is called.
Example:
eventBuffer := debug.NewEventBuffer(1000, eventBus) go eventBuffer.Start(ctx)
func (*EventBuffer) FindByCorrelationID ¶
func (eb *EventBuffer) FindByCorrelationID(correlationID string) []Event
FindByCorrelationID returns events matching the specified correlation ID.
This method searches through all events in the buffer and returns those that have a matching correlation ID. Events are returned in chronological order.
Example:
events := eventBuffer.FindByCorrelationID("550e8400-e29b-41d4-a716-446655440000")
func (*EventBuffer) GetLast ¶
func (eb *EventBuffer) GetLast(n int) []Event
GetLast returns the last n events in chronological order.
Example:
recent := eventBuffer.GetLast(100) // Last 100 events
func (*EventBuffer) Start ¶
func (eb *EventBuffer) Start(ctx context.Context) error
Start begins collecting events from the EventBus.
This method blocks until the context is cancelled. It processes events from the pre-subscribed channel. It should be run in a goroutine.
Example:
go eventBuffer.Start(ctx)
type EventsVar ¶
type EventsVar struct {
// contains filtered or unexported fields
}
EventsVar exposes recent events as a debug variable.
Returns a JSON array of recent events.
Example response:
[
{
"timestamp": "2025-01-15T10:30:45Z",
"type": "config.validated",
"summary": "config.validated"
},
{
"timestamp": "2025-01-15T10:30:46Z",
"type": "reconciliation.triggered",
"summary": "reconciliation.triggered"
}
]
type FailedEndpoint ¶
FailedEndpoint contains details about a failed deployment endpoint.
type PipelineStatus ¶
type PipelineStatus struct {
LastTrigger *TriggerStatus `json:"last_trigger"`
Rendering *RenderingStatus `json:"rendering"`
Validation *ValidationStatus `json:"validation"`
Deployment *DeploymentStatus `json:"deployment"`
}
PipelineStatus represents the complete status of the last reconciliation pipeline.
This provides visibility into each stage of the pipeline: trigger, rendering, validation, and deployment.
type RenderingStatus ¶
type RenderingStatus struct {
Status string `json:"status"` // "succeeded" | "failed"
Timestamp time.Time `json:"timestamp"`
DurationMs int64 `json:"duration_ms"`
ConfigBytes int `json:"config_bytes"`
Error string `json:"error,omitempty"`
}
RenderingStatus represents the template rendering phase status.
type StateProvider ¶
type StateProvider interface {
// GetConfig returns the current validated configuration and its version.
//
// Returns error if config is not yet loaded.
//
// Example return:
// config: &config.Config{...}
// version: "v123"
// error: nil
GetConfig() (*config.Config, string, error)
// GetCredentials returns the current credentials and their version.
//
// Returns error if credentials are not yet loaded.
//
// Example return:
// creds: &config.Credentials{...}
// version: "v456"
// error: nil
GetCredentials() (*config.Credentials, string, error)
// GetRenderedConfig returns the most recently rendered HAProxy configuration
// and the timestamp when it was rendered.
//
// Returns error if no config has been rendered yet.
//
// Example return:
// rendered: "global\n maxconn 2000\n..."
// timestamp: 2025-01-15 10:30:45
// error: nil
GetRenderedConfig() (string, time.Time, error)
// GetAuxiliaryFiles returns the most recently used auxiliary files
// (SSL certificates, map files, general files) and the timestamp.
//
// Returns error if no auxiliary files have been cached yet.
//
// Example return:
// auxFiles: &dataplane.AuxiliaryFiles{SSLCertificates: [...], ...}
// timestamp: 2025-01-15 10:30:45
// error: nil
GetAuxiliaryFiles() (*dataplane.AuxiliaryFiles, time.Time, error)
// GetResourceCounts returns a map of resource type → count.
//
// The keys are resource names as defined in the controller configuration
// (e.g., "ingresses", "services", "haproxy-pods").
//
// Example return:
// {
// "ingresses": 5,
// "services": 12,
// "haproxy-pods": 2
// }
GetResourceCounts() (map[string]int, error)
// GetResourcesByType returns the resources of a specific type.
//
// The resourceType parameter should match a key from GetResourceCounts().
//
// Partial-result contract: for `store: on-demand` resource types, the
// returned slice is the subset currently warm in the store's cache only —
// NOT the full set of tracked references. Listing the full set would fan
// out one kube-apiserver lookup per reference, which this method
// deliberately avoids. The count from GetResourceCounts() is therefore the
// authoritative total; this slice may be shorter. Callers wiring this to a
// user-facing endpoint must surface that the result is the warm subset so
// consumers don't mistake it for the complete set. For `store: full`
// resource types the result is complete.
//
// Returns error if the resource type is not found.
//
// Example:
// resources, err := provider.GetResourcesByType("ingresses")
GetResourcesByType(resourceType string) ([]any, error)
// GetPipelineStatus returns the complete status of the last reconciliation pipeline.
//
// Returns error if no pipeline has run yet.
//
// Example return:
// status: &PipelineStatus{
// LastTrigger: &TriggerStatus{Timestamp: ..., Reason: "config_change"},
// Rendering: &RenderingStatus{Status: "succeeded", ...},
// Validation: &ValidationStatus{Status: "failed", Errors: [...]},
// Deployment: &DeploymentStatus{Status: "skipped", Reason: "validation_failed"},
// }
GetPipelineStatus() (*PipelineStatus, error)
// GetValidatedConfig returns the last successfully validated HAProxy configuration.
//
// Unlike GetRenderedConfig(), this only returns configs that passed validation.
// Returns error if no config has been validated successfully yet.
//
// Example return:
// info: &ValidatedConfigInfo{
// Config: "global\n maxconn 2000\n...",
// Timestamp: 2025-01-15 10:30:45,
// ConfigBytes: 4567,
// ValidationDurationMs: 200,
// }
GetValidatedConfig() (*ValidatedConfigInfo, error)
// GetErrors returns an aggregated summary of recent errors across all phases.
//
// This is useful for quick diagnosis of configuration issues.
//
// Example return:
// summary: &ErrorSummary{
// HAProxyValidationError: &ErrorInfo{
// Timestamp: 2025-01-15 10:30:47,
// Errors: ["[ALERT] parsing [haproxy.cfg:3] : unknown keyword..."],
// },
// LastErrorTimestamp: 2025-01-15 10:30:47,
// }
GetErrors() (*ErrorSummary, error)
}
StateProvider provides access to controller internal state.
This interface is implemented by the controller to expose its state to debug variables in a thread-safe manner. The controller caches state by subscribing to events (ConfigValidatedEvent, RenderCompletedEvent, etc.) and updates the cached values accordingly.
All methods must be thread-safe as they may be called concurrently from HTTP request handlers.
type TriggerStatus ¶
TriggerStatus represents what triggered the last reconciliation.
type ValidatedConfigInfo ¶
type ValidatedConfigInfo struct {
Config string `json:"config"`
Timestamp time.Time `json:"timestamp"`
ConfigBytes int `json:"config_bytes"`
ValidationDurationMs int64 `json:"validation_duration_ms"`
}
ValidatedConfigInfo contains information about the last successfully validated config.
type ValidationStatus ¶
type ValidationStatus struct {
Status string `json:"status"` // "succeeded" | "failed" | "pending"
Timestamp time.Time `json:"timestamp"`
DurationMs int64 `json:"duration_ms"`
Errors []string `json:"errors,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
ValidationStatus represents the HAProxy validation phase status.