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 ¶
- func RegisterEventsHandler(server *introspection.Server, eventBuffer *EventBuffer)
- func RegisterVariables(registry *introspection.Registry, provider StateProvider, ...)
- type AuxFilesVar
- type ComponentStatus
- type ConfigVar
- type CredentialsVar
- type DeploymentStatus
- type ErrorInfo
- type ErrorSummary
- type ErrorsVar
- type Event
- type EventBuffer
- type EventsVar
- type FailedEndpoint
- type FullStateVar
- type PipelineStatus
- type PipelineVar
- type RenderedVar
- type RenderingStatus
- type ResourcesVar
- type StateProvider
- type TriggerStatus
- type ValidatedConfigInfo
- type ValidatedVar
- type ValidationStatus
Constants ¶
This section is empty.
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 AuxFilesVar ¶
type AuxFilesVar struct {
// contains filtered or unexported fields
}
AuxFilesVar exposes the auxiliary files used in the last deployment.
Returns a JSON object containing:
- files: the AuxiliaryFiles struct with SSL certs, maps, general files
- timestamp: when these files were last used
- summary: counts of each file type
Example response:
{
"files": {
"ssl_certificates": [...],
"map_files": [...],
"general_files": [...]
},
"timestamp": "2025-01-15T10:30:45Z",
"summary": {
"ssl_count": 2,
"map_count": 1,
"general_count": 3
}
}
func (*AuxFilesVar) Get ¶
func (v *AuxFilesVar) Get() (interface{}, error)
Get implements introspection.Var.
type ComponentStatus ¶
type ComponentStatus struct {
// Running indicates if the component is currently active
Running bool `json:"running"`
// LastSeen is the timestamp of the last activity from this component
LastSeen time.Time `json:"last_seen"`
// ErrorRate is the percentage of errors (0.0 to 1.0)
// Optional - may be 0 if not tracked
ErrorRate float64 `json:"error_rate,omitempty"`
// Details provides additional component-specific information
// Optional - may be nil
Details map[string]interface{} `json:"details,omitempty"`
}
ComponentStatus represents the status of a controller component.
Used by GetComponentStatus() to provide insight into component health.
type ConfigVar ¶
type ConfigVar struct {
// contains filtered or unexported fields
}
ConfigVar exposes the current controller configuration.
Returns a JSON object containing:
- config: the full Config struct
- version: the ConfigMap resource version
- updated: timestamp when the config was last updated
Example response:
{
"config": {
"templates": {"main": "..."},
"watched_resources": [...]
},
"version": "v123",
"updated": "2025-01-15T10:30:45Z"
}
type CredentialsVar ¶
type CredentialsVar struct {
// contains filtered or unexported fields
}
CredentialsVar exposes the current controller credentials.
Returns a JSON object containing:
- version: the Secret resource version
- updated: timestamp when credentials were last updated
Note: Does NOT expose actual credential values for security.
Example response:
{
"version": "v456",
"updated": "2025-01-15T10:30:45Z",
"has_dataplane_creds": true
}
func (*CredentialsVar) Get ¶
func (v *CredentialsVar) Get() (interface{}, error)
Get implements introspection.Var.
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,omitempty"`
}
ErrorSummary provides an aggregated view of recent errors across all phases.
type ErrorsVar ¶
type ErrorsVar struct {
// contains filtered or unexported fields
}
ErrorsVar exposes an aggregated view of recent errors across all phases.
Returns a JSON object containing errors from each phase:
- config_parse_error: config parsing errors
- template_render_error: template rendering errors
- haproxy_validation_error: HAProxy validation errors
- deployment_errors: per-endpoint deployment errors
- last_error_timestamp: when the most recent error occurred
Example response:
{
"haproxy_validation_error": {
"timestamp": "2025-01-15T10:30:47Z",
"errors": ["[ALERT] parsing [haproxy.cfg:3] : unknown keyword..."]
},
"last_error_timestamp": "2025-01-15T10:30:47Z"
}
type Event ¶
type Event struct {
Timestamp time.Time `json:"timestamp"`
Type string `json:"type"`
Summary string `json:"summary"`
Details interface{} `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) GetAll ¶
func (eb *EventBuffer) GetAll() []Event
GetAll returns all events in the buffer.
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) Len ¶
func (eb *EventBuffer) Len() int
Len returns the current number of events in the buffer.
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 FullStateVar ¶
type FullStateVar struct {
// contains filtered or unexported fields
}
FullStateVar exposes all controller state in a single dump.
Warning: This can return very large responses. Use with caution. Prefer querying specific variables or using field selection.
Returns a JSON object containing:
- config: current config and version
- rendered: last rendered config
- auxfiles: auxiliary files
- resources: resource counts
- recent_events: last 100 events
- snapshot_time: when this snapshot was taken
func (*FullStateVar) Get ¶
func (v *FullStateVar) Get() (interface{}, error)
Get implements introspection.Var.
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 PipelineVar ¶
type PipelineVar struct {
// contains filtered or unexported fields
}
PipelineVar exposes the reconciliation pipeline status.
Returns a JSON object containing the status of each pipeline phase:
- last_trigger: what triggered the reconciliation
- rendering: template rendering status
- validation: HAProxy validation status
- deployment: deployment to HAProxy instances status
Example response:
{
"last_trigger": {"timestamp": "2025-01-15T10:30:45Z", "reason": "config_change"},
"rendering": {"status": "succeeded", ...},
"validation": {"status": "failed", "errors": [...]},
"deployment": {"status": "skipped", "reason": "validation_failed"}
}
func (*PipelineVar) Get ¶
func (v *PipelineVar) Get() (interface{}, error)
Get implements introspection.Var.
type RenderedVar ¶
type RenderedVar struct {
// contains filtered or unexported fields
}
RenderedVar exposes the most recently rendered HAProxy configuration.
Returns a JSON object containing:
- config: the rendered HAProxy config string
- timestamp: when it was rendered
- size: length of the config in bytes
Example response:
{
"config": "global\n maxconn 2000\n...",
"timestamp": "2025-01-15T10:30:45Z",
"size": 4567
}
func (*RenderedVar) Get ¶
func (v *RenderedVar) Get() (interface{}, error)
Get implements introspection.Var.
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 ResourcesVar ¶
type ResourcesVar struct {
// contains filtered or unexported fields
}
ResourcesVar exposes resource counts by type.
Returns a map of resource type → count.
Example response:
{
"ingresses": 5,
"services": 12,
"haproxy-pods": 2
}
func (*ResourcesVar) Get ¶
func (v *ResourcesVar) Get() (interface{}, error)
Get implements introspection.Var.
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 all resources of a specific type.
//
// The resourceType parameter should match a key from GetResourceCounts().
//
// Returns error if the resource type is not found.
//
// Example:
// resources, err := provider.GetResourcesByType("ingresses")
GetResourcesByType(resourceType string) ([]interface{}, 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 ValidatedVar ¶
type ValidatedVar struct {
// contains filtered or unexported fields
}
ValidatedVar exposes the last successfully validated HAProxy configuration.
Unlike RenderedVar, this only shows configs that passed validation. This is useful to see what config is actually safe to deploy.
Example response:
{
"config": "global\n maxconn 2000\n...",
"timestamp": "2025-01-15T10:30:45Z",
"config_bytes": 4567,
"validation_duration_ms": 200
}
func (*ValidatedVar) Get ¶
func (v *ValidatedVar) Get() (interface{}, error)
Get implements introspection.Var.
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.