Documentation
¶
Overview ¶
Package events contains all domain event type definitions for the HAPTIC controller.
Event Immutability Contract ¶
Events in this system are intended to be immutable after creation. They represent historical facts about what happened in the system and should not be modified after being published to the EventBus.
To support this immutability contract:
All event types use pointer receivers for their Event interface methods. This avoids copying large structs (200+ bytes) and follows Go best practices.
All event fields are exported to support JSON serialization and idiomatic Go access. This follows industry standards (Kubernetes, NATS) rather than enforcing immutability through unexported fields and getters.
Constructors perform defensive copying of slices and maps to prevent mutations from affecting the published event. Publishers cannot modify events after creation.
Consumers MUST NOT modify event fields. This immutability contract is enforced through: - A custom static analyzer (tools/linters/eventimmutability) that detects parameter mutations - Code review for cases not caught by the analyzer - Team discipline and documentation
This approach balances performance, Go idioms, and practical immutability for an internal project where all consumers are controlled.
Event Categories ¶
Events are organized into separate files by category:
- config.go: HAProxyTemplateConfig CRD changes and validation events
- resource.go: Kubernetes resource indexing and synchronization events
- reconciliation.go: Template rendering and deployment cycle events
- template.go: Template rendering operation events
- validation.go: Configuration validation (syntax and semantics) events
- deployment.go: HAProxy configuration deployment events
- discovery.go: HAProxy pod discovery events
- credentials.go: Credentials loading and validation events
- leader.go: Leader election events
- publishing.go: Config publishing events (including SyncMetadata types)
- certificate.go: Webhook certificate events
- http.go: HTTP resource events
- proposal.go: Speculative validation requests/responses (used by webhook and HTTP store)
- status.go: Status patch application events
Index ¶
- Constants
- type BecameLeaderEvent
- type ConfigAppliedToPodEvent
- type ConfigInvalidEvent
- type ConfigParsedEvent
- type ConfigPublishedEvent
- type ConfigResourceChangedEvent
- type ConfigValidatedEvent
- type ConfigValidationRequest
- type ConfigValidationResponse
- type CorrelatedEvent
- type Correlation
- type CorrelationOption
- type CredentialsInvalidEvent
- type CredentialsUpdatedEvent
- type DeployedConfigPublishRequest
- type DeploymentCancelRequestEvent
- type DeploymentCompletedEvent
- type DeploymentResult
- type DeploymentScheduledEvent
- type DeploymentSkippedEvent
- type DeploymentStartedEvent
- type DriftPreventionTriggeredEvent
- type HAProxyPodRejectedEvent
- type HAProxyPodTerminatedEvent
- type HAProxyPodsDiscoveredEvent
- type HTTPResourceAcceptedEvent
- type HTTPResourceRejectedEvent
- type HTTPResourceUpdatedEvent
- type IndexSynchronizedEvent
- type InstanceDeployedEvent
- type InstanceDeploymentFailedEvent
- type LeaderElectionStartedEvent
- type LostLeadershipEvent
- type NewLeaderObservedEvent
- type OperationCounts
- type ProposalValidationCompletedEvent
- type ProposalValidationRequestedEvent
- type ReconciliationCompletedEvent
- type ReconciliationFailedEvent
- type ReconciliationStartedEvent
- type ReconciliationTriggeredEvent
- type ResourceIndexUpdatedEvent
- type ResourceSyncCompleteEvent
- type ResourcesAppliedEvent
- type RuntimeFastPathResultEvent
- type SecretResourceChangedEvent
- type StatusPatchPhase
- type StatusUpdateCompletedEvent
- type StatusUpdateFailedEvent
- type SyncMetadata
- type TemplateRenderFailedEvent
- type TemplateRenderedEvent
- type ValidationCompletedEvent
- type ValidationFailedEvent
Constants ¶
const ( // Configuration event types. EventTypeConfigParsed = "config.parsed" EventTypeConfigValidationRequest = "config.validation.request" EventTypeConfigValidationResponse = "config.validation.response" EventTypeConfigValidated = "config.validated" EventTypeConfigInvalid = "config.invalid" EventTypeConfigResourceChanged = "config.resource.changed" // Resource event types. EventTypeResourceIndexUpdated = "resource.index.updated" EventTypeResourceSyncComplete = "resource.sync.complete" EventTypeIndexSynchronized = "index.synchronized" // Reconciliation event types. EventTypeReconciliationTriggered = "reconciliation.triggered" EventTypeReconciliationStarted = "reconciliation.started" EventTypeReconciliationCompleted = "reconciliation.completed" // EventTypeResourcesApplied is published by the ResourceApplier after a // cycle's rendered resources are applied; carries the cycle's status // patches forward so the rendered status variant applies after the // resources exist. EventTypeResourcesApplied = "resources.applied" EventTypeReconciliationFailed = "reconciliation.failed" // Template event types. EventTypeTemplateRendered = "template.rendered" EventTypeTemplateRenderFailed = "template.render.failed" // Validation event types (HAProxy dataplane API validation). EventTypeValidationCompleted = "validation.completed" EventTypeValidationFailed = "validation.failed" // Deployment event types. EventTypeDeploymentScheduled = "deployment.scheduled" EventTypeDeploymentStarted = "deployment.started" EventTypeInstanceDeployed = "instance.deployed" EventTypeInstanceDeploymentFailed = "instance.deployment.failed" EventTypeDeploymentCompleted = "deployment.completed" EventTypeDeploymentSkipped = "deployment.skipped" EventTypeDeploymentCancelRequest = "deployment.cancel.request" EventTypeRuntimeFastPathResult = "runtime.fastpath.result" EventTypeDriftPreventionTriggered = "drift.prevention.triggered" // HAProxy pod event types. EventTypeHAProxyPodsDiscovered = "haproxy.pods.discovered" EventTypeHAProxyPodTerminated = "haproxy.pod.terminated" EventTypeHAProxyPodRejected = "haproxy.pod.rejected" // Config publishing event types. EventTypeConfigPublished = "config.published" EventTypeConfigAppliedToPod = "config.applied.to.pod" EventTypeDeployedConfigPublishRequest = "config.deployed.publish.request" // Credentials event types. EventTypeSecretResourceChanged = "secret.resource.changed" EventTypeCredentialsUpdated = "credentials.updated" EventTypeCredentialsInvalid = "credentials.invalid" // Leader election event types. EventTypeLeaderElectionStarted = "leader.election.started" EventTypeBecameLeader = "leader.became" EventTypeLostLeadership = "leader.lost" EventTypeNewLeaderObserved = "leader.observed" // HTTP resource event types. EventTypeHTTPResourceUpdated = "http.resource.updated" EventTypeHTTPResourceAccepted = "http.resource.accepted" EventTypeHTTPResourceRejected = "http.resource.rejected" // Proposal validation event types. // Used for validating hypothetical configuration changes before committing them. // See proposal.go for event definitions. EventTypeProposalValidationRequested = "proposal.validation.requested" EventTypeProposalValidationCompleted = "proposal.validation.completed" // Status update event types. // Published by StatusApplier after applying template-driven status patches to Kubernetes resources. EventTypeStatusUpdateCompleted = "status.update.completed" EventTypeStatusUpdateFailed = "status.update.failed" )
const (
TriggerReasonDriftPrevention = "drift_prevention"
)
TriggerReason constants for reconciliation events. These are propagated through the event chain via TriggerReason fields.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BecameLeaderEvent ¶
type BecameLeaderEvent struct {
Identity string
// contains filtered or unexported fields
}
BecameLeaderEvent is published when this replica becomes the leader.
func NewBecameLeaderEvent ¶
func NewBecameLeaderEvent(identity string) *BecameLeaderEvent
NewBecameLeaderEvent creates a new BecameLeaderEvent.
func (*BecameLeaderEvent) EventType ¶
func (e *BecameLeaderEvent) EventType() string
type ConfigAppliedToPodEvent ¶
type ConfigAppliedToPodEvent struct {
RuntimeConfigName string
RuntimeConfigNamespace string
PodName string
PodNamespace string
Checksum string
// IsDriftCheck indicates whether this was a drift prevention check (GET-only)
// or an actual sync operation (POST/PUT/DELETE).
//
// True: Drift check - no actual changes were made, just verified config is current
// False: Actual sync - configuration was written to HAProxy
IsDriftCheck bool
// SyncMetadata contains detailed information about the sync operation.
// Only populated for actual syncs (IsDriftCheck=false).
SyncMetadata *SyncMetadata
// contains filtered or unexported fields
}
ConfigAppliedToPodEvent is published after configuration is successfully applied to a HAProxy pod.
This triggers updating the deployment status in runtime config resources.
func NewConfigAppliedToPodEvent ¶
func NewConfigAppliedToPodEvent(runtimeConfigName, runtimeConfigNamespace, podName, podNamespace, checksum string, isDriftCheck bool, syncMetadata *SyncMetadata) *ConfigAppliedToPodEvent
NewConfigAppliedToPodEvent creates a new ConfigAppliedToPodEvent.
func (*ConfigAppliedToPodEvent) EventType ¶
func (e *ConfigAppliedToPodEvent) EventType() string
type ConfigInvalidEvent ¶
type ConfigInvalidEvent struct {
Version string
// TemplateConfig is the original HAProxyTemplateConfig CRD.
// Type: any to avoid circular dependencies.
// Used by status updater to set validation errors on the CRD status.
TemplateConfig any
// ValidationErrors maps validator names to their error messages.
ValidationErrors map[string][]string
// contains filtered or unexported fields
}
ConfigInvalidEvent is published when config validation fails.
The controller will continue running with the previous valid config and wait for the next HAProxyTemplateConfig CRD update.
func NewConfigInvalidEvent ¶
func NewConfigInvalidEvent(version string, templateConfig any, validationErrors map[string][]string) *ConfigInvalidEvent
NewConfigInvalidEvent creates a new ConfigInvalidEvent. Performs defensive copy of the validation errors map and its slice values.
func (*ConfigInvalidEvent) EventType ¶
func (e *ConfigInvalidEvent) EventType() string
type ConfigParsedEvent ¶
type ConfigParsedEvent struct {
// Config contains the parsed configuration.
// Type: any to avoid circular dependencies.
// Consumers should type-assert to their expected config type.
Config any
// TemplateConfig is the original HAProxyTemplateConfig CRD.
// Type: any to avoid circular dependencies.
// Needed by ConfigPublisher to extract Kubernetes metadata (name, namespace, UID).
TemplateConfig any
// Version is the resourceVersion of the HAProxyTemplateConfig CRD.
Version string
// SecretVersion is the resourceVersion of the credentials Secret.
SecretVersion string
// contains filtered or unexported fields
}
ConfigParsedEvent is published when the HAProxyTemplateConfig CRD has been successfully parsed into a Config structure.
This event does not mean the config is valid - only that it could be parsed. Validation occurs in a subsequent step.
func NewConfigParsedEvent ¶
func NewConfigParsedEvent(config, templateConfig any, version, secretVersion string) *ConfigParsedEvent
NewConfigParsedEvent creates a new ConfigParsedEvent.
func (*ConfigParsedEvent) EventType ¶
func (e *ConfigParsedEvent) EventType() string
type ConfigPublishedEvent ¶
type ConfigPublishedEvent struct {
RuntimeConfigName string
RuntimeConfigNamespace string
MapFileCount int
SecretCount int
// contains filtered or unexported fields
}
ConfigPublishedEvent is published after runtime configuration resources are created/updated.
This is a non-critical event - publishing failures do not affect controller operation.
func NewConfigPublishedEvent ¶
func NewConfigPublishedEvent(runtimeConfigName, runtimeConfigNamespace string, mapFileCount, secretCount int) *ConfigPublishedEvent
NewConfigPublishedEvent creates a new ConfigPublishedEvent.
func (*ConfigPublishedEvent) EventType ¶
func (e *ConfigPublishedEvent) EventType() string
type ConfigResourceChangedEvent ¶
type ConfigResourceChangedEvent struct {
// Resource contains the raw HAProxyTemplateConfig CRD resource.
// Type: any to avoid circular dependencies.
// Consumers should type-assert to *unstructured.Unstructured.
Resource any
// contains filtered or unexported fields
}
ConfigResourceChangedEvent is published when the HAProxyTemplateConfig CRD resource is added, updated, or deleted.
This is a low-level event published directly by the SingleWatcher callback in the controller package. The ConfigLoaderComponent subscribes to this event and handles parsing.
func NewConfigResourceChangedEvent ¶
func NewConfigResourceChangedEvent(resource any) *ConfigResourceChangedEvent
NewConfigResourceChangedEvent creates a new ConfigResourceChangedEvent.
func (*ConfigResourceChangedEvent) EventType ¶
func (e *ConfigResourceChangedEvent) EventType() string
type ConfigValidatedEvent ¶
type ConfigValidatedEvent struct {
Config any
// TemplateConfig is the original HAProxyTemplateConfig CRD.
// Type: any to avoid circular dependencies.
// Needed by ConfigPublisher to extract Kubernetes metadata (name, namespace, UID).
TemplateConfig any
Version string
SecretVersion string
// contains filtered or unexported fields
}
ConfigValidatedEvent is published when all validators have confirmed the config is valid.
After receiving this event, the controller proceeds to start resource watchers. with the validated configuration.
func NewConfigValidatedEvent ¶
func NewConfigValidatedEvent(config, templateConfig any, version, secretVersion string) *ConfigValidatedEvent
NewConfigValidatedEvent creates a new ConfigValidatedEvent.
func (*ConfigValidatedEvent) EventType ¶
func (e *ConfigValidatedEvent) EventType() string
type ConfigValidationRequest ¶
type ConfigValidationRequest struct {
// Config contains the configuration to validate.
Config any
// Version is the resourceVersion being validated.
Version string
// contains filtered or unexported fields
}
ConfigValidationRequest is published to request validation of a parsed config.
This is a Request event used in the scatter-gather pattern. Multiple validators (basic, template, jsonpath) will respond with ConfigValidationResponse events.
func NewConfigValidationRequest ¶
func NewConfigValidationRequest(config any, version string) *ConfigValidationRequest
NewConfigValidationRequest creates a new ConfigValidationRequest.
func (*ConfigValidationRequest) EventType ¶
func (e *ConfigValidationRequest) EventType() string
func (*ConfigValidationRequest) RequestID ¶
func (e *ConfigValidationRequest) RequestID() string
type ConfigValidationResponse ¶
type ConfigValidationResponse struct {
// ValidatorName identifies which validator produced this response (basic, template, jsonpath).
ValidatorName string
// Valid is true if this validator found no errors.
Valid bool
// Errors contains validation error messages, empty if Valid is true.
Errors []string
// contains filtered or unexported fields
}
ConfigValidationResponse is sent by validators in response to ConfigValidationRequest.
This is a Response event used in the scatter-gather pattern. pkg/controller/configchange.ConfigChangeHandler issues the request, collects all responses, and determines if the config is valid overall.
func NewConfigValidationResponse ¶
func NewConfigValidationResponse(requestID, validatorName string, valid bool, errors []string) *ConfigValidationResponse
NewConfigValidationResponse creates a new ConfigValidationResponse. Performs defensive copy of the errors slice.
func (*ConfigValidationResponse) EventType ¶
func (e *ConfigValidationResponse) EventType() string
func (*ConfigValidationResponse) RequestID ¶
func (e *ConfigValidationResponse) RequestID() string
func (*ConfigValidationResponse) Responder ¶
func (e *ConfigValidationResponse) Responder() string
type CorrelatedEvent ¶
type CorrelatedEvent interface {
// Each event instance has its own unique EventID.
// This is used as the CausationID for downstream events.
EventID() string
// All events in the same reconciliation cycle share the same correlation ID.
// Returns empty string if correlation is not set.
CorrelationID() string
// This enables building causal chains for debugging.
// Returns empty string if causation is not set.
CausationID() string
}
CorrelatedEvent is an interface for events that support correlation tracking.
Events that implement this interface can be linked together to trace causal chains through the reconciliation pipeline. This enables:
- Querying all events for a specific reconciliation cycle
- Building event graphs for debugging
- Measuring end-to-end latency for pipelines
- OpenTelemetry integration
Not all events need to implement this interface. It's optional and primarily useful for events in the reconciliation pipeline.
type Correlation ¶
type Correlation struct {
// contains filtered or unexported fields
}
Correlation holds event ID, correlation ID, and causation ID for event tracing.
This struct is embedded in event types that need correlation support. It's designed to be optional - events can work without correlation, and consumers can check for empty IDs.
The IDs serve different purposes:
- eventID: Unique identifier for THIS specific event instance
- correlationID: Shared ID linking all events in a reconciliation cycle
- causationID: The eventID of the event that triggered this one
func (*Correlation) CausationID ¶
func (c *Correlation) CausationID() string
CausationID returns the causation ID, or empty string if not set.
func (*Correlation) CorrelationID ¶
func (c *Correlation) CorrelationID() string
CorrelationID returns the correlation ID, or empty string if not set.
func (*Correlation) EventID ¶
func (c *Correlation) EventID() string
EventID returns the unique identifier for this specific event.
type CorrelationOption ¶
type CorrelationOption struct {
// contains filtered or unexported fields
}
CorrelationOption holds data for setting correlation on events. This is a data struct rather than a closure to ensure events are fully initialized in their struct literals without post-creation mutation.
func PropagateCorrelation ¶
func PropagateCorrelation(source any) CorrelationOption
PropagateCorrelation extracts correlation context from a source event and returns a CorrelationOption that can be applied to a new event. If the source event doesn't implement CorrelatedEvent, returns an empty option.
The correlation ID is copied from the source event (maintaining pipeline identity). The causation ID is set to the source event's EventID (creating causal chain).
Example:
func handleEvent(sourceEvent Event) {
newEvent := events.NewTemplateRenderedEvent(...,
events.PropagateCorrelation(sourceEvent))
}
func WithCorrelation ¶
func WithCorrelation(correlationID, causationID string) CorrelationOption
WithCorrelation sets both correlation and causation IDs on an event. Use this when propagating correlation context from a triggering event.
Example:
triggeredEvent := events.NewReconciliationTriggeredEvent("config_change", true, events.WithNewCorrelation())
renderedEvent := events.NewTemplateRenderedEvent(...,
events.WithCorrelation(triggeredEvent.CorrelationID(), triggeredEvent.EventID()))
func WithNewCorrelation ¶
func WithNewCorrelation() CorrelationOption
WithNewCorrelation generates a new correlation ID and sets it on an event. Use this at the start of a new pipeline (e.g., ReconciliationTriggeredEvent).
Example:
event := events.NewReconciliationTriggeredEvent("config_change", true,
events.WithNewCorrelation())
type CredentialsInvalidEvent ¶
type CredentialsInvalidEvent struct {
SecretVersion string
Error string
// contains filtered or unexported fields
}
CredentialsInvalidEvent is published when credential loading or validation fails.
The controller will continue running with the previous valid credentials and wait. for the next Secret update.
func NewCredentialsInvalidEvent ¶
func NewCredentialsInvalidEvent(secretVersion, errMsg string) *CredentialsInvalidEvent
NewCredentialsInvalidEvent creates a new CredentialsInvalidEvent.
func (*CredentialsInvalidEvent) EventType ¶
func (e *CredentialsInvalidEvent) EventType() string
type CredentialsUpdatedEvent ¶
type CredentialsUpdatedEvent struct {
// Credentials contains the validated credentials.
// Type: any to avoid circular dependencies.
// Consumers should type-assert to their expected credentials type.
Credentials any
// SecretVersion is the resourceVersion of the Secret.
SecretVersion string
// contains filtered or unexported fields
}
CredentialsUpdatedEvent is published when credentials have been successfully. loaded and validated from the Secret.
func NewCredentialsUpdatedEvent ¶
func NewCredentialsUpdatedEvent(credentials any, secretVersion string) *CredentialsUpdatedEvent
NewCredentialsUpdatedEvent creates a new CredentialsUpdatedEvent.
func (*CredentialsUpdatedEvent) EventType ¶
func (e *CredentialsUpdatedEvent) EventType() string
type DeployedConfigPublishRequest ¶
type DeployedConfigPublishRequest struct {
RuntimeConfigName string
RuntimeConfigNamespace string
Config string
AuxiliaryFiles *dataplane.AuxiliaryFiles
ContentChecksum string
// contains filtered or unexported fields
}
DeployedConfigPublishRequest asks the config-publisher to publish, as the HAProxyCfg spec, the exact config bytes the deployer just applied to the pods. It closes a CR self-consistency gap: the deployer stamps status.deployedToPods[].Checksum from these bytes (via dataplane.ComputeContentChecksum), but the validation-driven spec publish for that same render can be throttled/coalesced away under churn — leaving a pod's recorded checksum that never appears in any published spec.Checksum. Emitting this on every successful, non-drift deploy guarantees the deployed checksum becomes an observable published spec.
Config/AuxiliaryFiles are the deployer's immutable post-render bytes; like DeploymentScheduledEvent, AuxiliaryFiles is carried by pointer (never mutated after rendering).
func NewDeployedConfigPublishRequest ¶
func NewDeployedConfigPublishRequest(runtimeConfigName, runtimeConfigNamespace, config string, auxFiles *dataplane.AuxiliaryFiles, contentChecksum string) *DeployedConfigPublishRequest
NewDeployedConfigPublishRequest creates a new DeployedConfigPublishRequest.
func (*DeployedConfigPublishRequest) EventType ¶
func (e *DeployedConfigPublishRequest) EventType() string
type DeploymentCancelRequestEvent ¶
type DeploymentCancelRequestEvent struct {
// Reason describes why the deployment is being cancelled.
Reason string
Correlation
// contains filtered or unexported fields
}
DeploymentCancelRequestEvent is published when the scheduler requests cancellation of an in-progress deployment (e.g., due to timeout).
Published by: DeploymentScheduler (on timeout) Consumed by: Deployer (to cancel running deployment)
The CorrelationID must match the deployment being cancelled.
func NewDeploymentCancelRequestEvent ¶
func NewDeploymentCancelRequestEvent(reason string, opts ...CorrelationOption) *DeploymentCancelRequestEvent
NewDeploymentCancelRequestEvent creates a new DeploymentCancelRequestEvent.
func (*DeploymentCancelRequestEvent) EventType ¶
func (e *DeploymentCancelRequestEvent) EventType() string
type DeploymentCompletedEvent ¶
type DeploymentCompletedEvent struct {
Total int // Total number of instances
Succeeded int // Number of successful deployments
Failed int // Number of failed deployments
DurationMs int64 // Total deployment duration in milliseconds
ReloadsTriggered int // Count of instances that triggered HAProxy reload
TotalAPIOperations int // Sum of API operations across all instances
// OperationBreakdown provides a generic breakdown of operations performed.
// Keys are formatted as "section_type" (e.g., "backend_create", "server_update", "global_update").
// Values are the count of operations of that type.
// Aggregated across all successfully deployed instances.
OperationBreakdown map[string]int
// BackendDiffFields summarizes which BackendBase fields caused backend updates.
// Empty when no backend attribute diffs were detected.
// Example: "[GUID] (48 backends)" or "[Mode, Balance] (3 backends)"
BackendDiffFields string
// StatusPatches are the chart-rendered status patches that correspond to
// the configuration this deployment carried. The StatusApplier reads them
// from this event and applies the "deployed" variant — guaranteeing that
// the status conditions it writes describe the config the data plane is
// actually serving (no side-channel cache, no LATEST-vs-deployed race).
//
// Threaded through unchanged from the DeploymentScheduledEvent that
// triggered this deployment.
StatusPatches []templating.StatusPatch
// ContentChecksum is the checksum of the config + auxiliary files THIS
// deployment actually pushed to the data plane. Threaded through
// unchanged from the DeploymentScheduledEvent so the DeploymentScheduler
// can update its lastDeployedConfigHash from a value that's tied to the
// completing deployment, not from the latest render (which a parallel
// reconcile may have overwritten while this deployment was in flight).
//
// Without this, the scheduler reads s.lastContentChecksum at completion
// time and mis-records the in-flight render's checksum as "what was just
// deployed" — silently making future deployments with the same hash
// hit the unchanged-skip branch and never reach HAProxy. Symptom in CI:
// a freshly-added Ingress's redirect/auth directive never appears in
// the live haproxy.cfg even though the controller did render it.
//
// Empty string for the zero-endpoint code path (nothing was deployed).
ContentChecksum string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
DeploymentCompletedEvent is published when deployment to all HAProxy instances completes.
This event propagates the correlation ID from DeploymentStartedEvent.
func NewDeploymentCompletedEvent ¶
func NewDeploymentCompletedEvent(result *DeploymentResult, opts ...CorrelationOption) *DeploymentCompletedEvent
NewDeploymentCompletedEvent creates a new DeploymentCompletedEvent.
`result` is taken by pointer because DeploymentResult is large enough (≥96 bytes) that gocritic flags pass-by-value as `hugeParam`.
`result.StatusPatches` should be forwarded unchanged from the DeploymentScheduledEvent that triggered the deployment so the StatusApplier reads the patches that correspond exactly to the configuration that just shipped (the chart's "deployed" variant).
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewDeploymentCompletedEvent(&events.DeploymentResult{
Total: len(endpoints),
Succeeded: successCount,
Failed: failureCount,
DurationMs: totalDurationMs,
ReloadsTriggered: reloads,
TotalAPIOperations: ops,
OperationBreakdown: breakdown,
StatusPatches: scheduledEvent.StatusPatches, // forward unchanged
}, events.PropagateCorrelation(startedEvent))
func (*DeploymentCompletedEvent) Coalescible ¶
func (e *DeploymentCompletedEvent) Coalescible() bool
Coalescible implements busevents.CoalescibleEvent. A completed event is a full-state notification: it carries the complete status patch set of the config the deploy shipped, so for consumers that declare it in their CoalescesOn list (only the status applier) the newest of an uninterrupted run supersedes the older ones. Consumers with per-event bookkeeping (the deployer clears its in-flight flag per completion) must simply not declare this type — coalescing is always per-subscriber opt-in.
func (*DeploymentCompletedEvent) EventType ¶
func (e *DeploymentCompletedEvent) EventType() string
type DeploymentResult ¶
type DeploymentResult struct {
Total int // Total number of instances
Succeeded int // Number of successful deployments
Failed int // Number of failed deployments
DurationMs int64 // Total deployment duration in milliseconds
ReloadsTriggered int // Count of instances that triggered HAProxy reload
TotalAPIOperations int // Sum of API operations across all instances
// OperationBreakdown provides a generic breakdown of operations performed.
// Keys are formatted as "section_type" (e.g., "backend_create", "server_update", "global_update").
// Values are the count of operations of that type.
OperationBreakdown map[string]int
// BackendDiffFields summarizes which BackendBase fields caused backend updates.
// Empty when no backend attribute diffs were detected.
BackendDiffFields string
// StatusPatches are the chart-rendered status patches for the
// configuration this deployment carried. Forwarded from the
// DeploymentScheduledEvent and surfaced on DeploymentCompletedEvent for
// the StatusApplier to consume.
StatusPatches []templating.StatusPatch
// ContentChecksum is the checksum of the config + auxiliary files
// THIS deployment pushed (forwarded from DeploymentScheduledEvent).
// See DeploymentCompletedEvent.ContentChecksum for the full rationale.
// Empty when no deployment occurred (zero-endpoint path).
ContentChecksum string
}
DeploymentResult contains the outcome of a deployment operation. Used with NewDeploymentCompletedEvent for cleaner parameter passing.
type DeploymentScheduledEvent ¶
type DeploymentScheduledEvent struct {
// Config is the rendered HAProxy configuration to deploy.
Config string
// AuxiliaryFiles contains all rendered auxiliary files.
AuxiliaryFiles *dataplane.AuxiliaryFiles
// ParsedConfig is the pre-parsed desired configuration from validation.
// May be nil if validation cache was used.
// When non-nil, passed to sync operations to skip redundant parsing.
ParsedConfig *parser.StructuredConfig
// Endpoints is the list of HAProxy endpoints to deploy to.
Endpoints []dataplane.Endpoint
// RuntimeConfigName is the name of the HAProxyCfg resource.
// Used for publishing ConfigAppliedToPodEvent after successful deployment.
RuntimeConfigName string
// RuntimeConfigNamespace is the namespace of the HAProxyCfg resource.
// Used for publishing ConfigAppliedToPodEvent after successful deployment.
RuntimeConfigNamespace string
// ContentChecksum is the pre-computed content checksum covering config + aux files.
// Propagated from TemplateRenderedEvent to enable aux file comparison caching
// in the deployer — when the checksum matches the last-deployed checksum for
// an endpoint, the expensive aux file comparison (Dataplane API downloads) is skipped.
ContentChecksum string
// Reason describes why this deployment was scheduled.
// Examples: "config_validation", "pod_discovery", "drift_prevention"
Reason string
// StatusPatches are the chart-rendered status patches for this
// configuration. The Deployer forwards them unchanged into
// DeploymentCompletedEvent so the StatusApplier can apply the
// "deployed" variant with the patches that correspond exactly to
// the config this deployment shipped.
StatusPatches []templating.StatusPatch
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
DeploymentScheduledEvent is published when the deployment scheduler has decided. to execute a deployment. This event contains all necessary data for the deployer to execute the deployment without maintaining state.
Published by: DeploymentScheduler. Consumed by: Deployer component.
This event propagates the correlation ID from ValidationCompletedEvent.
This event implements CoalescibleEvent. The coalescible flag is propagated from ValidationCompletedEvent to enable coalescing throughout the reconciliation pipeline.
func NewDeploymentScheduledEvent ¶
func NewDeploymentScheduledEvent(config string, auxFiles *dataplane.AuxiliaryFiles, parsedConfig *parser.StructuredConfig, endpoints []dataplane.Endpoint, runtimeConfigName, runtimeConfigNamespace, reason, contentChecksum string, statusPatches []templating.StatusPatch, coalescible bool, opts ...CorrelationOption) *DeploymentScheduledEvent
NewDeploymentScheduledEvent creates a new DeploymentScheduledEvent. Performs defensive copy of endpoints slice.
The coalescible parameter should be propagated from ValidationCompletedEvent.Coalescible() to enable coalescing throughout the reconciliation pipeline.
The parsedConfig parameter contains the pre-parsed desired configuration from validation. Pass nil if validation cache was used or if the parsed config is not available.
The contentChecksum is the pre-computed checksum of config + aux files, propagated from TemplateRenderedEvent. It enables the deployer to skip expensive aux file comparison when the content hasn't changed since the last successful sync to an endpoint.
statusPatches is the chart-rendered patch set for this configuration. The Deployer forwards it unchanged into DeploymentCompletedEvent so the StatusApplier can apply the "deployed" variant with the patches that correspond exactly to the config this deployment shipped. The outer slice is defensively cloned.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewDeploymentScheduledEvent(config, auxFiles, parsedConfig, endpoints, name, ns, reason, contentChecksum, statusPatches, coalescible,
events.PropagateCorrelation(validationEvent))
func (*DeploymentScheduledEvent) Coalescible ¶
func (e *DeploymentScheduledEvent) Coalescible() bool
Coalescible returns true if this event can be safely skipped when a newer event of the same type is available. This implements the CoalescibleEvent interface.
func (*DeploymentScheduledEvent) EventType ¶
func (e *DeploymentScheduledEvent) EventType() string
type DeploymentSkippedEvent ¶
type DeploymentSkippedEvent struct {
// Total is the number of HAProxy endpoints already serving the rendered
// configuration. Mirrors DeploymentCompletedEvent.Total so subscribers
// can apply the same "is there actually a data plane to talk to?" guard.
Total int
// Reason is a short tag describing why the deployment was skipped.
// Currently always "config_unchanged"; left as a string to leave room
// for future skip causes (e.g. "drift_check_only") without an event
// schema change.
Reason string
// ConfigHash is the content checksum of the rendered HAProxy
// configuration that matched the last successful deployment. Useful
// for debugging / correlation across the deployer's logs.
ConfigHash string
// PodSetHash is the hash of the endpoint set that matched the last
// successful deployment. Useful for debugging / correlation.
PodSetHash string
// StatusPatches are the chart-rendered status patches for the
// already-deployed configuration. The StatusApplier reads them from
// this event to write the "deployed" variant — the data plane is
// serving this exact config, so conditions gated on data-plane
// readiness should reflect the current generation.
StatusPatches []templating.StatusPatch
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
DeploymentSkippedEvent is published when the deployment scheduler determines that the data plane is already at the just-rendered configuration and no deployment work needs to be performed (typically: rendered config hash and pod-set hash both match the last successful deployment).
Semantically this is NOT a deployment — nothing was pushed, no reload was triggered, no API operations were issued. It exists as its own event type so that downstream consumers can distinguish "the controller is converged" from "the controller just completed work."
Currently consumed by:
- statusapplier, which treats this equivalently to DeploymentCompletedEvent for the purpose of applying the "deployed" status-patch variant — the data plane is serving the latest config, so Kubernetes status conditions gated on data-plane readiness should reflect the current generation.
Other consumers (metrics, commentator, drift_monitor, scheduler, statecache) do not subscribe by design — skipped deployments are a steady-state signal and bursting through those consumers would either produce log spam (commentator) or misleading counters (metrics). They can opt in later if there's a concrete need.
This event propagates the correlation ID from the triggering event (typically ValidationCompletedEvent) so the converged path remains observable in correlation-based tracing.
func NewDeploymentSkippedEvent ¶
func NewDeploymentSkippedEvent(total int, reason, configHash, podSetHash string, statusPatches []templating.StatusPatch, opts ...CorrelationOption) *DeploymentSkippedEvent
NewDeploymentSkippedEvent creates a new DeploymentSkippedEvent.
statusPatches is the chart-rendered patch set for the already-deployed configuration; the StatusApplier reads it from the event to write the "deployed" variant. The outer slice is defensively cloned per the immutability contract documented in events/CLAUDE.md.
Use PropagateCorrelation() to propagate correlation from the triggering event so the skip remains correlated with the originating reconciliation:
event := events.NewDeploymentSkippedEvent(
len(endpoints),
"config_unchanged",
configHash,
podSetHash,
statusPatches,
events.PropagateCorrelation(scheduledEvent),
)
func (*DeploymentSkippedEvent) Coalescible ¶
func (e *DeploymentSkippedEvent) Coalescible() bool
Coalescible implements busevents.CoalescibleEvent — same full-state latest-wins rationale as DeploymentCompletedEvent.Coalescible.
func (*DeploymentSkippedEvent) EventType ¶
func (e *DeploymentSkippedEvent) EventType() string
type DeploymentStartedEvent ¶
type DeploymentStartedEvent struct {
// EndpointCount is the number of HAProxy instances this deploy targets.
// Only the count is carried: subscribers (statecache, commentator) never
// read more than len(), and carrying the full slice forced a defensive
// deep-copy of every endpoint's address and credentials on each publish.
EndpointCount int
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
DeploymentStartedEvent is published when deployment to HAProxy instances begins.
This event propagates the correlation ID from DeploymentScheduledEvent.
func NewDeploymentStartedEvent ¶
func NewDeploymentStartedEvent(endpointCount int, opts ...CorrelationOption) *DeploymentStartedEvent
NewDeploymentStartedEvent creates a new DeploymentStartedEvent.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewDeploymentStartedEvent(len(endpoints),
events.PropagateCorrelation(scheduledEvent))
func (*DeploymentStartedEvent) EventType ¶
func (e *DeploymentStartedEvent) EventType() string
type DriftPreventionTriggeredEvent ¶
type DriftPreventionTriggeredEvent struct {
// TimeSinceLastDeployment is the duration since the last deployment completed.
TimeSinceLastDeployment time.Duration
// contains filtered or unexported fields
}
DriftPreventionTriggeredEvent is published when the drift prevention monitor. detects that no deployment has occurred within the configured interval and triggers a deployment to prevent configuration drift.
Published by: DriftPreventionMonitor. Consumed by: DeploymentScheduler (which then schedules a deployment).
func NewDriftPreventionTriggeredEvent ¶
func NewDriftPreventionTriggeredEvent(timeSinceLast time.Duration) *DriftPreventionTriggeredEvent
NewDriftPreventionTriggeredEvent creates a new DriftPreventionTriggeredEvent.
func (*DriftPreventionTriggeredEvent) EventType ¶
func (e *DriftPreventionTriggeredEvent) EventType() string
type HAProxyPodRejectedEvent ¶
type HAProxyPodRejectedEvent struct {
// PodName is the rejected pod's name (used for correlation with
// k8s events / pod logs).
PodName string
// Reason categorises the rejection. Stable identifiers used as a
// Prometheus label, so prefer a fixed enum:
// - "version_mismatch_older" — remote HAProxy is older than local
// - "version_mismatch_newer" — remote HAProxy is newer than local
// - "version_check_failed" — could not probe remote version (transient)
Reason string
// contains filtered or unexported fields
}
HAProxyPodRejectedEvent is published by the discovery component when a candidate HAProxy pod is refused admission. The most common cause is a remote HAProxy version mismatch with the controller's bundled version, which is a deliberate safety property — the controller cannot safely push config to a major.minor-different HAProxy. Surfaced via Prometheus (haptic_haproxy_pods_rejected_total{reason}) so operators can alert on "controller refuses to talk to N HAProxy pods" without log-grepping.
func NewHAProxyPodRejectedEvent ¶
func NewHAProxyPodRejectedEvent(podName, reason string) *HAProxyPodRejectedEvent
NewHAProxyPodRejectedEvent creates a new HAProxyPodRejectedEvent.
func (*HAProxyPodRejectedEvent) EventType ¶
func (e *HAProxyPodRejectedEvent) EventType() string
type HAProxyPodTerminatedEvent ¶
type HAProxyPodTerminatedEvent struct {
PodName string
PodNamespace string
// contains filtered or unexported fields
}
HAProxyPodTerminatedEvent is published when a HAProxy pod terminates.
This triggers cleanup of the pod from all runtime config status fields.
func NewHAProxyPodTerminatedEvent ¶
func NewHAProxyPodTerminatedEvent(podName, podNamespace string) *HAProxyPodTerminatedEvent
NewHAProxyPodTerminatedEvent creates a new HAProxyPodTerminatedEvent.
func (*HAProxyPodTerminatedEvent) EventType ¶
func (e *HAProxyPodTerminatedEvent) EventType() string
type HAProxyPodsDiscoveredEvent ¶
type HAProxyPodsDiscoveredEvent struct {
// Endpoints is the list of discovered HAProxy Dataplane API endpoints.
Endpoints []dataplane.Endpoint
Count int
// contains filtered or unexported fields
}
HAProxyPodsDiscoveredEvent is published when HAProxy pods are discovered or updated. This event is always coalescible since it represents endpoint state where only the latest set of endpoints matters.
func NewHAProxyPodsDiscoveredEvent ¶
func NewHAProxyPodsDiscoveredEvent(endpoints []dataplane.Endpoint, count int) *HAProxyPodsDiscoveredEvent
NewHAProxyPodsDiscoveredEvent creates a new HAProxyPodsDiscoveredEvent. Performs defensive copy of the endpoints slice.
func (*HAProxyPodsDiscoveredEvent) Coalescible ¶
func (e *HAProxyPodsDiscoveredEvent) Coalescible() bool
Coalescible returns true because endpoint discovery events represent state where only the latest set of endpoints matters. Older discoveries can be safely skipped during high-frequency pod churn (scaling, rolling updates).
func (*HAProxyPodsDiscoveredEvent) EventType ¶
func (e *HAProxyPodsDiscoveredEvent) EventType() string
type HTTPResourceAcceptedEvent ¶
type HTTPResourceAcceptedEvent struct {
URL string // The URL whose content was accepted
ContentChecksum string // SHA256 checksum of accepted content
ContentSize int // Size of accepted content in bytes
// contains filtered or unexported fields
}
HTTPResourceAcceptedEvent is published when pending HTTP content passes validation. The content has been promoted from "pending" to "accepted" state.
func NewHTTPResourceAcceptedEvent ¶
func NewHTTPResourceAcceptedEvent(url, checksum string, size int) *HTTPResourceAcceptedEvent
NewHTTPResourceAcceptedEvent creates a new HTTPResourceAcceptedEvent.
func (*HTTPResourceAcceptedEvent) EventType ¶
func (e *HTTPResourceAcceptedEvent) EventType() string
type HTTPResourceRejectedEvent ¶
type HTTPResourceRejectedEvent struct {
URL string // The URL whose content was rejected
ContentChecksum string // SHA256 checksum of rejected content
Reason string // Why the content was rejected
// contains filtered or unexported fields
}
HTTPResourceRejectedEvent is published when pending HTTP content fails validation. The old accepted content remains in use.
Observability-only: there is no business-logic subscriber by design. The httpstore component already WARN-logs the rejection, and the commentator surfaces the event; nothing needs to react functionally.
func NewHTTPResourceRejectedEvent ¶
func NewHTTPResourceRejectedEvent(url, checksum, reason string) *HTTPResourceRejectedEvent
NewHTTPResourceRejectedEvent creates a new HTTPResourceRejectedEvent.
func (*HTTPResourceRejectedEvent) EventType ¶
func (e *HTTPResourceRejectedEvent) EventType() string
type HTTPResourceUpdatedEvent ¶
type HTTPResourceUpdatedEvent struct {
URL string // The URL that was refreshed
ContentChecksum string // SHA256 checksum of new content
ContentSize int // Size of new content in bytes
// contains filtered or unexported fields
}
HTTPResourceUpdatedEvent is published when HTTP resource content has changed. This triggers a reconciliation cycle with the new content as "pending". The content must pass validation before being promoted to "accepted". This event is always coalescible since it represents content state where only the latest content for a URL matters.
func NewHTTPResourceUpdatedEvent ¶
func NewHTTPResourceUpdatedEvent(url, checksum string, size int) *HTTPResourceUpdatedEvent
NewHTTPResourceUpdatedEvent creates a new HTTPResourceUpdatedEvent.
func (*HTTPResourceUpdatedEvent) Coalescible ¶
func (e *HTTPResourceUpdatedEvent) Coalescible() bool
Coalescible returns true because HTTP resource update events represent state where only the latest content matters. If the same URL updates multiple times before reconciliation completes, older updates can be safely skipped.
func (*HTTPResourceUpdatedEvent) EventType ¶
func (e *HTTPResourceUpdatedEvent) EventType() string
type IndexSynchronizedEvent ¶
type IndexSynchronizedEvent struct {
// ResourceCounts maps resource types to their counts.
ResourceCounts map[string]int
// contains filtered or unexported fields
}
IndexSynchronizedEvent is published when all resource watchers have completed. their initial sync and the system has a complete view of all resources.
This is a critical milestone - the controller waits for this event before. starting reconciliation to ensure it has complete data.
func NewIndexSynchronizedEvent ¶
func NewIndexSynchronizedEvent(resourceCounts map[string]int) *IndexSynchronizedEvent
NewIndexSynchronizedEvent creates a new IndexSynchronizedEvent. Performs defensive copy of the resource counts map.
func (*IndexSynchronizedEvent) EventType ¶
func (e *IndexSynchronizedEvent) EventType() string
type InstanceDeployedEvent ¶
type InstanceDeployedEvent struct {
Endpoint any // The HAProxy endpoint that was deployed to
DurationMs int64
ReloadRequired bool // Whether this deployment required a HAProxy reload
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
InstanceDeployedEvent is published when deployment to a single HAProxy instance succeeds.
This event propagates the correlation ID from DeploymentStartedEvent.
Observability-only: consumed by the commentator's deploymentInsight for per-instance logging; no business-logic subscriber reacts to it.
func NewInstanceDeployedEvent ¶
func NewInstanceDeployedEvent(endpoint any, durationMs int64, reloadRequired bool, opts ...CorrelationOption) *InstanceDeployedEvent
NewInstanceDeployedEvent creates a new InstanceDeployedEvent.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewInstanceDeployedEvent(endpoint, durationMs, reloadRequired,
events.PropagateCorrelation(startedEvent))
func (*InstanceDeployedEvent) EventType ¶
func (e *InstanceDeployedEvent) EventType() string
type InstanceDeploymentFailedEvent ¶
type InstanceDeploymentFailedEvent struct {
Endpoint any
Error string
Retryable bool // Whether this failure is retryable
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
InstanceDeploymentFailedEvent is published when deployment to a single HAProxy instance fails.
This event propagates the correlation ID from DeploymentStartedEvent.
func NewInstanceDeploymentFailedEvent ¶
func NewInstanceDeploymentFailedEvent(endpoint any, err string, retryable bool, opts ...CorrelationOption) *InstanceDeploymentFailedEvent
NewInstanceDeploymentFailedEvent creates a new InstanceDeploymentFailedEvent.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewInstanceDeploymentFailedEvent(endpoint, err, retryable,
events.PropagateCorrelation(startedEvent))
func (*InstanceDeploymentFailedEvent) EventType ¶
func (e *InstanceDeploymentFailedEvent) EventType() string
type LeaderElectionStartedEvent ¶
type LeaderElectionStartedEvent struct {
Identity string
LeaseName string
LeaseNamespace string
// contains filtered or unexported fields
}
LeaderElectionStartedEvent is published when leader election is initiated.
func NewLeaderElectionStartedEvent ¶
func NewLeaderElectionStartedEvent(identity, leaseName, leaseNamespace string) *LeaderElectionStartedEvent
NewLeaderElectionStartedEvent creates a new LeaderElectionStartedEvent.
func (*LeaderElectionStartedEvent) EventType ¶
func (e *LeaderElectionStartedEvent) EventType() string
type LostLeadershipEvent ¶
type LostLeadershipEvent struct {
Identity string
Reason string // graceful_shutdown, lease_expired, etc.
// contains filtered or unexported fields
}
LostLeadershipEvent is published when this replica loses leadership.
func NewLostLeadershipEvent ¶
func NewLostLeadershipEvent(identity, reason string) *LostLeadershipEvent
NewLostLeadershipEvent creates a new LostLeadershipEvent.
func (*LostLeadershipEvent) EventType ¶
func (e *LostLeadershipEvent) EventType() string
type NewLeaderObservedEvent ¶
type NewLeaderObservedEvent struct {
NewLeaderIdentity string
IsSelf bool // true if this replica is the new leader
// contains filtered or unexported fields
}
NewLeaderObservedEvent is published when a new leader is observed.
func NewNewLeaderObservedEvent ¶
func NewNewLeaderObservedEvent(newLeaderIdentity string, isSelf bool) *NewLeaderObservedEvent
NewNewLeaderObservedEvent creates a new NewLeaderObservedEvent.
func (*NewLeaderObservedEvent) EventType ¶
func (e *NewLeaderObservedEvent) EventType() string
type OperationCounts ¶
type OperationCounts struct {
// Config operations
TotalAPIOperations int
BackendsAdded int
BackendsRemoved int
BackendsModified int
ServersAdded int
ServersRemoved int
ServersModified int
FrontendsAdded int
FrontendsRemoved int
FrontendsModified int
// Auxiliary file operations
MapsAdded int
MapsRemoved int
MapsModified int
SSLCertsAdded int
SSLCertsRemoved int
SSLCertsModified int
GeneralFilesAdded int
GeneralFilesRemoved int
GeneralFilesModified int
}
OperationCounts provides statistics about sync operations.
type ProposalValidationCompletedEvent ¶
type ProposalValidationCompletedEvent struct {
// RequestID correlates this response to the original request.
RequestID string
// Valid is true if the proposed configuration passed all validation phases.
Valid bool
// Phase indicates which validation phase failed (syntax, schema, semantic).
// Empty if Valid is true.
Phase string
// Error contains the validation error message if Valid is false.
// Empty if Valid is true.
Error string
// DurationMs is the total validation duration in milliseconds.
DurationMs int64
// contains filtered or unexported fields
}
ProposalValidationCompletedEvent is published when proposal validation completes.
This event indicates whether the proposed configuration changes would result in a valid HAProxy configuration.
Contract:
- Published by: ProposalValidator
- Consumed by: HTTPStore, Webhook (via event subscription or sync call result)
func NewProposalValidationCompletedEvent ¶
func NewProposalValidationCompletedEvent(requestID string, durationMs int64) *ProposalValidationCompletedEvent
NewProposalValidationCompletedEvent creates a successful validation completion event.
Parameters:
- requestID: ID from the corresponding ProposalValidationRequestedEvent
- durationMs: Total validation duration in milliseconds
Returns:
- Immutable ProposalValidationCompletedEvent indicating success.
func NewProposalValidationFailedEvent ¶
func NewProposalValidationFailedEvent(requestID, phase string, err error, durationMs int64) *ProposalValidationCompletedEvent
NewProposalValidationFailedEvent creates a failed validation completion event.
Parameters:
- requestID: ID from the corresponding ProposalValidationRequestedEvent
- phase: Validation phase that failed (syntax, schema, semantic, render)
- err: The validation error
- durationMs: Total validation duration in milliseconds
Returns:
- Immutable ProposalValidationCompletedEvent indicating failure.
func (*ProposalValidationCompletedEvent) EventType ¶
func (e *ProposalValidationCompletedEvent) EventType() string
EventType implements the Event interface.
type ProposalValidationRequestedEvent ¶
type ProposalValidationRequestedEvent struct {
// ID uniquely identifies this validation request for response correlation.
ID string
// Overlays maps store names to their proposed changes.
// The ProposalValidator will create a CompositeStoreProvider using these.
// Key: store name (e.g., "ingresses", "services")
// Value: proposed changes for that store
Overlays map[string]*stores.StoreOverlay
// HTTPOverlay contains pending HTTP content changes for validation.
// When present, the ProposalValidator includes this in the ValidationContext
// so the render pipeline sees pending HTTP content.
// Nil when validating K8s-only changes (e.g., webhook admission).
HTTPOverlay stores.HTTPContentOverlay
// Source identifies where this request originated from.
// Examples: "httpstore", "webhook"
Source string
// SourceContext provides additional context about the source.
// For httpstore: resource URL
// For webhook: resource GVK and namespace/name
SourceContext string
// contains filtered or unexported fields
}
ProposalValidationRequestedEvent is published when a component wants to validate a hypothetical configuration change without deploying it.
This is used for: - HTTP store content validation (validate before accepting new content) - Webhook admission validation (validate resource changes before admission)
Contract:
- Published by: HTTPStore, Webhook
- Consumed by: ProposalValidator
- Response: ProposalValidationCompletedEvent with matching RequestID
func NewProposalValidationRequestedEvent ¶
func NewProposalValidationRequestedEvent(overlays map[string]*stores.StoreOverlay, httpOverlay stores.HTTPContentOverlay, source, sourceContext string) *ProposalValidationRequestedEvent
NewProposalValidationRequestedEvent creates a new proposal validation request.
Parameters:
- overlays: Map of store name to proposed changes (can be nil for HTTP-only validation)
- httpOverlay: HTTP content overlay (can be nil for K8s-only validation)
- source: Identifier for the request source (e.g., "httpstore", "webhook")
- sourceContext: Additional context about the source
Returns:
- Immutable ProposalValidationRequestedEvent with unique ID.
func (*ProposalValidationRequestedEvent) EventType ¶
func (e *ProposalValidationRequestedEvent) EventType() string
EventType implements the Event interface.
func (*ProposalValidationRequestedEvent) RequestID ¶
func (e *ProposalValidationRequestedEvent) RequestID() string
RequestID returns the unique request identifier for correlation.
type ReconciliationCompletedEvent ¶
type ReconciliationCompletedEvent struct {
DurationMs int64
// RenderedResources are the Kubernetes resources the templates declared
// under spec.k8sResources in this cycle. The
// ResourceApplier reads them directly from the event so it stays
// stateless on the success path — patches/resources travel with the
// event that triggers their apply, never via a side-channel cache. May
// be nil when the render didn't emit any K8s resources.
RenderedResources []templating.RenderedResource
// StatusPatches are the chart-rendered status patches of this cycle.
// The ResourceApplier forwards them on ResourcesAppliedEvent after its
// apply pass so the StatusApplier writes the "rendered" variant only
// AFTER the same render's infrastructure resources exist (conditions
// must describe materialized state — conformance's GatewayInfrastructure
// lists labeled resources the moment Accepted turns True).
StatusPatches []templating.StatusPatch
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ReconciliationCompletedEvent is published when a reconciliation cycle completes successfully.
This event propagates the correlation ID from the reconciliation chain.
func NewReconciliationCompletedEvent ¶
func NewReconciliationCompletedEvent( durationMs int64, renderedResources []templating.RenderedResource, statusPatches []templating.StatusPatch, opts ...CorrelationOption, ) *ReconciliationCompletedEvent
NewReconciliationCompletedEvent creates a new ReconciliationCompletedEvent.
renderedResources is the slice of resources the templates declared under spec.k8sResources in this cycle. The outer slice is defensively cloned so publishers reusing a cached slice (e.g. coordinator forwarding PipelineResult.RenderedResources) can't mutate published events.
Use WithCorrelation() to propagate correlation from the pipeline:
event := events.NewReconciliationCompletedEvent(durationMs, resources,
events.WithCorrelation(correlationID, causationID))
func (*ReconciliationCompletedEvent) Coalescible ¶
func (e *ReconciliationCompletedEvent) Coalescible() bool
Coalescible implements busevents.CoalescibleEvent. A completed cycle is a full-state notification — RenderedResources and StatusPatches are the COMPLETE desired set of the render — so for consumers that declare it in their CoalescesOn list only the newest of an uninterrupted run matters.
func (*ReconciliationCompletedEvent) EventType ¶
func (e *ReconciliationCompletedEvent) EventType() string
type ReconciliationFailedEvent ¶
type ReconciliationFailedEvent struct {
Error string
Phase string // Which phase failed: "render", "validate", "deploy"
// StatusPatches are the chart-rendered status patches from the most
// recent SUCCESSFUL render (the failure itself rarely produces patches —
// render failures have none; validation failures have the just-rendered
// set). The StatusApplier reads them to write the renderFailed /
// deployFailed variant on the affected resources. May be nil if no
// successful render has happened yet (early bootstrap failures); the
// applier handles nil gracefully by skipping the apply.
StatusPatches []templating.StatusPatch
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ReconciliationFailedEvent is published when a reconciliation cycle fails.
This event propagates the correlation ID from the reconciliation chain.
func NewReconciliationFailedEvent ¶
func NewReconciliationFailedEvent(err, phase string, statusPatches []templating.StatusPatch, opts ...CorrelationOption) *ReconciliationFailedEvent
NewReconciliationFailedEvent creates a new ReconciliationFailedEvent.
statusPatches should be the patches from the most recent successful render, or nil if none exists yet. The outer slice is defensively cloned.
Use WithCorrelation() to propagate correlation from the pipeline:
event := events.NewReconciliationFailedEvent(err, phase, statusPatches,
events.WithCorrelation(correlationID, causationID))
func (*ReconciliationFailedEvent) EventType ¶
func (e *ReconciliationFailedEvent) EventType() string
type ReconciliationStartedEvent ¶
type ReconciliationStartedEvent struct {
// Trigger describes what triggered this reconciliation.
Trigger string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ReconciliationStartedEvent is published when the Executor begins a reconciliation cycle.
This event propagates the correlation ID from ReconciliationTriggeredEvent.
func NewReconciliationStartedEvent ¶
func NewReconciliationStartedEvent(trigger string, opts ...CorrelationOption) *ReconciliationStartedEvent
NewReconciliationStartedEvent creates a new ReconciliationStartedEvent.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewReconciliationStartedEvent(trigger,
events.PropagateCorrelation(triggeredEvent))
func (*ReconciliationStartedEvent) EventType ¶
func (e *ReconciliationStartedEvent) EventType() string
type ReconciliationTriggeredEvent ¶
type ReconciliationTriggeredEvent struct {
// Reason describes why reconciliation was triggered.
// Examples: "debounce_timer", "config_change", "manual_trigger"
Reason string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ReconciliationTriggeredEvent is published when a reconciliation cycle should start.
This event is typically published by the Reconciler after the debounce timer. expires, or immediately for config changes.
This event starts a new correlation chain. Downstream events (TemplateRenderedEvent, ValidationCompletedEvent, DeploymentScheduledEvent, etc.) should propagate the correlation ID to enable end-to-end tracing.
This event implements CoalescibleEvent. The coalescible flag is set by the emitter (Reconciler) based on the trigger context:
- coalescible=true for state updates (debounce_timer, resource_change)
- coalescible=false for commands (index_synchronized, drift_prevention)
func NewReconciliationTriggeredEvent ¶
func NewReconciliationTriggeredEvent(reason string, coalescible bool, opts ...CorrelationOption) *ReconciliationTriggeredEvent
NewReconciliationTriggeredEvent creates a new ReconciliationTriggeredEvent.
The coalescible parameter is set by the emitter based on trigger context:
- true for state updates where only the latest matters (debounce_timer, resource_change)
- false for commands that must be processed (index_synchronized, drift_prevention)
Use WithNewCorrelation() to start a new correlation chain:
event := events.NewReconciliationTriggeredEvent("config_change", true,
events.WithNewCorrelation())
func (*ReconciliationTriggeredEvent) Coalescible ¶
func (e *ReconciliationTriggeredEvent) Coalescible() bool
Coalescible returns true if this event can be safely skipped when a newer event of the same type is available. This implements the CoalescibleEvent interface.
func (*ReconciliationTriggeredEvent) EventType ¶
func (e *ReconciliationTriggeredEvent) EventType() string
type ResourceIndexUpdatedEvent ¶
type ResourceIndexUpdatedEvent struct {
// ResourceTypeName identifies the watched resource type as configured in
// spec.watchedResources (the plural form, e.g. "services").
ResourceTypeName string
// ChangeStats provides detailed change statistics including Created, Modified, Deleted counts
// and whether this event occurred during initial sync.
ChangeStats types.ChangeStats
// contains filtered or unexported fields
}
ResourceIndexUpdatedEvent is published when a watched Kubernetes resource. has been added, updated, or deleted in the local index.
func NewResourceIndexUpdatedEvent ¶
func NewResourceIndexUpdatedEvent(resourceTypeName string, changeStats types.ChangeStats) *ResourceIndexUpdatedEvent
NewResourceIndexUpdatedEvent creates a new ResourceIndexUpdatedEvent. Performs a value copy of ChangeStats (it's a small struct with no pointers).
func (*ResourceIndexUpdatedEvent) EventType ¶
func (e *ResourceIndexUpdatedEvent) EventType() string
type ResourceSyncCompleteEvent ¶
type ResourceSyncCompleteEvent struct {
// ResourceTypeName identifies the resource type from config (e.g., "ingresses").
ResourceTypeName string
// InitialCount is the number of resources loaded during initial sync.
InitialCount int
// contains filtered or unexported fields
}
ResourceSyncCompleteEvent is published when a resource watcher has completed. its initial sync with the Kubernetes API.
func NewResourceSyncCompleteEvent ¶
func NewResourceSyncCompleteEvent(resourceTypeName string, initialCount int) *ResourceSyncCompleteEvent
NewResourceSyncCompleteEvent creates a new ResourceSyncCompleteEvent.
func (*ResourceSyncCompleteEvent) EventType ¶
func (e *ResourceSyncCompleteEvent) EventType() string
type ResourcesAppliedEvent ¶
type ResourcesAppliedEvent struct {
// StatusPatches forwarded from the ReconciliationCompletedEvent that
// triggered the apply pass.
StatusPatches []templating.StatusPatch
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ResourcesAppliedEvent is published by the ResourceApplier after it finishes applying a cycle's rendered resources (and pruning orphans). It forwards the cycle's StatusPatches so the StatusApplier writes the "rendered" status variant strictly AFTER the same render's infrastructure resources exist. Without this ordering the two appliers race: Accepted=True could land while e.g. the per-Gateway Service is still being created, and consumers (including the Gateway API conformance GatewayInfrastructure test) that list infrastructure the moment Accepted turns True find nothing.
func NewResourcesAppliedEvent ¶
func NewResourcesAppliedEvent(statusPatches []templating.StatusPatch, opts ...CorrelationOption) *ResourcesAppliedEvent
NewResourcesAppliedEvent creates a new ResourcesAppliedEvent. The patches slice is NOT cloned: the publisher forwards the (already defensively cloned) slice from the ReconciliationCompletedEvent it consumed.
func (*ResourcesAppliedEvent) Coalescible ¶
func (e *ResourcesAppliedEvent) Coalescible() bool
Coalescible implements busevents.CoalescibleEvent — full-state semantics, same rationale as ReconciliationCompletedEvent.Coalescible.
func (*ResourcesAppliedEvent) EventType ¶
func (e *ResourcesAppliedEvent) EventType() string
type RuntimeFastPathResultEvent ¶
type RuntimeFastPathResultEvent struct {
// ServerUpdates is the number of runtime-eligible server updates applied to
// the live worker on this fire (0 = fired, nothing to do).
ServerUpdates int
// Failed is true when the apply errored. Best-effort: the scheduled deploy
// is the correctness floor and converges the pod regardless.
Failed bool
// contains filtered or unexported fields
}
RuntimeFastPathResultEvent reports one runtime-eligible fast-path apply attempt (one per HAProxy pod, per reconcile). The deployer's fast path publishes it on every fire so the metrics component can track the fire-vs- apply distinction without parsing DEBUG logs: ServerUpdates == 0 means the fast path fired but the in-memory render diff had no runtime-eligible server change to apply (the common steady-state case).
func NewRuntimeFastPathResultEvent ¶
func NewRuntimeFastPathResultEvent(serverUpdates int, failed bool) *RuntimeFastPathResultEvent
NewRuntimeFastPathResultEvent builds a RuntimeFastPathResultEvent.
func (*RuntimeFastPathResultEvent) EventType ¶
func (e *RuntimeFastPathResultEvent) EventType() string
EventType returns the event type identifier.
type SecretResourceChangedEvent ¶
type SecretResourceChangedEvent struct {
// Resource contains the raw Secret resource.
// Type: any to avoid circular dependencies.
// Consumers should type-assert to *unstructured.Unstructured or *corev1.Secret.
Resource any
// contains filtered or unexported fields
}
SecretResourceChangedEvent is published when the Secret resource is added, updated, or deleted.
This is a low-level event published directly by the SingleWatcher callback in the controller package. The CredentialsLoaderComponent subscribes to this event and handles parsing.
func NewSecretResourceChangedEvent ¶
func NewSecretResourceChangedEvent(resource any) *SecretResourceChangedEvent
NewSecretResourceChangedEvent creates a new SecretResourceChangedEvent.
func (*SecretResourceChangedEvent) EventType ¶
func (e *SecretResourceChangedEvent) EventType() string
type StatusPatchPhase ¶
type StatusPatchPhase string
StatusPatchPhase identifies which pipeline phase triggered a status patch application.
const ( // StatusPatchPhaseRendered is applied after successful template rendering. StatusPatchPhaseRendered StatusPatchPhase = "rendered" // StatusPatchPhaseDeployed is applied after successful HAProxy deployment. StatusPatchPhaseDeployed StatusPatchPhase = "deployed" // StatusPatchPhaseRenderFailed is applied when template rendering fails // before any output is produced. StatusPatchPhaseRenderFailed StatusPatchPhase = "renderFailed" // StatusPatchPhaseValidateFailed is applied when the rendered config // passed templating but was rejected by validation (syntax, schema, or // semantic checks) before any deploy attempt. Distinct from // renderFailed (no output produced) and deployFailed (deploy attempted // and rolled back). Chart templates may emit the same payload as // renderFailed until validation failures need a distinct surface. StatusPatchPhaseValidateFailed StatusPatchPhase = "validateFailed" // StatusPatchPhaseDeployFailed is applied when HAProxy deployment fails. StatusPatchPhaseDeployFailed StatusPatchPhase = "deployFailed" )
type StatusUpdateCompletedEvent ¶
type StatusUpdateCompletedEvent struct {
// Phase identifies which pipeline phase triggered this status update.
Phase StatusPatchPhase
// AppliedCount is the number of status patches successfully applied.
AppliedCount int
// SkippedCount is the number of status patches skipped (checksum match).
SkippedCount int
// DurationMs is the total duration of status patch application.
DurationMs int64
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
StatusUpdateCompletedEvent is published when status patch application completes.
This event propagates the correlation ID from the triggering reconciliation event.
Observability-only: consumed by the commentator's statusInsight; no business-logic subscriber reacts to it.
func NewStatusUpdateCompletedEvent ¶
func NewStatusUpdateCompletedEvent( phase StatusPatchPhase, appliedCount int, skippedCount int, durationMs int64, opts ...CorrelationOption, ) *StatusUpdateCompletedEvent
NewStatusUpdateCompletedEvent creates a new StatusUpdateCompletedEvent.
func (*StatusUpdateCompletedEvent) EventType ¶
func (e *StatusUpdateCompletedEvent) EventType() string
type StatusUpdateFailedEvent ¶
type StatusUpdateFailedEvent struct {
// Namespace is the namespace of the target Kubernetes resource.
Namespace string
// Name is the name of the target Kubernetes resource.
Name string
// GVR is the GroupVersionResource string of the target resource (e.g., "networking.k8s.io/v1/ingresses").
GVR string
// Error is the error message from the failed SSA patch.
Error string
// Retriable indicates whether the failure is transient and can be retried.
Retriable bool
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
StatusUpdateFailedEvent is published when a status patch application fails for a resource.
This event propagates the correlation ID from the triggering reconciliation event.
Observability-only: consumed by the commentator's statusInsight; no business-logic subscriber reacts to it.
func NewStatusUpdateFailedEvent ¶
func NewStatusUpdateFailedEvent( namespace string, name string, gvr string, err string, retriable bool, opts ...CorrelationOption, ) *StatusUpdateFailedEvent
NewStatusUpdateFailedEvent creates a new StatusUpdateFailedEvent.
func (*StatusUpdateFailedEvent) EventType ¶
func (e *StatusUpdateFailedEvent) EventType() string
type SyncMetadata ¶
type SyncMetadata struct {
// ReloadTriggered indicates whether HAProxy was reloaded during this sync.
// Reload path triggers a reload; runtime path doesn't.
ReloadTriggered bool
// ReloadID is the reload identifier from HAProxy dataplane API.
// Only populated when ReloadTriggered is true.
ReloadID string
// SyncDuration is how long the sync operation took.
SyncDuration time.Duration
// OperationCounts provides a breakdown of operations performed.
OperationCounts OperationCounts
// Error contains the error message if sync failed.
// Empty string indicates success.
Error string
}
SyncMetadata contains detailed information about a sync operation.
type TemplateRenderFailedEvent ¶
type TemplateRenderFailedEvent struct {
// TemplateName is the name of the template that failed to render.
TemplateName string
// Error is the error message.
Error string
// StackTrace provides additional debugging context.
StackTrace string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
TemplateRenderFailedEvent is published when template rendering fails.
This event propagates the correlation ID from ReconciliationTriggeredEvent.
func NewTemplateRenderFailedEvent ¶
func NewTemplateRenderFailedEvent(templateName, err, stackTrace string, opts ...CorrelationOption) *TemplateRenderFailedEvent
NewTemplateRenderFailedEvent creates a new TemplateRenderFailedEvent.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewTemplateRenderFailedEvent(name, err, stackTrace,
events.PropagateCorrelation(triggeredEvent))
func (*TemplateRenderFailedEvent) EventType ¶
func (e *TemplateRenderFailedEvent) EventType() string
type TemplateRenderedEvent ¶
type TemplateRenderedEvent struct {
// HAProxyConfig is the rendered main HAProxy configuration.
// Uses relative paths (maps/, ssl/, files/) that work with HAProxy's `default-path origin`.
HAProxyConfig string
// AuxiliaryFiles contains all rendered auxiliary files (maps, certificates, general files).
AuxiliaryFiles *dataplane.AuxiliaryFiles
// StatusPatches contains status patches registered by templates during rendering.
// Each patch targets a Kubernetes resource and contains outcome-keyed variants
// for different pipeline lifecycle phases (rendered, deployed, renderFailed, deployFailed).
StatusPatches []templating.StatusPatch
// RenderedResources contains full Kubernetes resources the templates declared
// the controller should own and reconcile (e.g. an auxiliary Service or other
// object a template emits alongside the HAProxy config). The applier compares
// each against the last-applied checksum and skips unchanged entries to avoid
// hammering the API server.
RenderedResources []templating.RenderedResource
// ContentChecksum is the pre-computed content checksum covering config + aux files.
// Computed once in the pipeline and propagated to downstream consumers to avoid
// redundant hashing in config publisher and deployment scheduler.
ContentChecksum string
// Metrics for observability
ConfigBytes int // Size of HAProxyConfig
AuxiliaryFileCount int // Number of auxiliary files
DurationMs int64 // Total rendering duration
// TriggerReason is the reason that triggered this reconciliation.
// Propagated from ReconciliationTriggeredEvent.Reason.
// Examples: "config_change", "debounce_timer", "drift_prevention"
// Used by downstream components (e.g., DeploymentScheduler) to determine fallback behavior.
TriggerReason string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
TemplateRenderedEvent is published when template rendering completes successfully.
This event carries a single rendered HAProxy configuration using relative paths (maps/, ssl/, files/) that work with HAProxy's `default-path origin` directive. The same config works in any directory where the config file is placed.
This event propagates the correlation ID from ReconciliationTriggeredEvent.
This event implements CoalescibleEvent. The coalescible flag is propagated from ReconciliationTriggeredEvent to enable coalescing throughout the reconciliation pipeline.
func NewTemplateRenderedEvent ¶
func NewTemplateRenderedEvent( haproxyConfig string, auxiliaryFiles *dataplane.AuxiliaryFiles, statusPatches []templating.StatusPatch, renderedResources []templating.RenderedResource, auxFileCount int, durationMs int64, triggerReason string, contentChecksum string, coalescible bool, opts ...CorrelationOption, ) *TemplateRenderedEvent
NewTemplateRenderedEvent creates a new TemplateRenderedEvent.
The coalescible parameter should be propagated from ReconciliationTriggeredEvent.Coalescible() to enable coalescing throughout the reconciliation pipeline.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewTemplateRenderedEvent(..., triggerReason, trigger.Coalescible(),
events.PropagateCorrelation(triggeredEvent))
func (*TemplateRenderedEvent) Coalescible ¶
func (e *TemplateRenderedEvent) Coalescible() bool
Coalescible returns true if this event can be safely skipped when a newer event of the same type is available. This implements the CoalescibleEvent interface.
func (*TemplateRenderedEvent) EventType ¶
func (e *TemplateRenderedEvent) EventType() string
type ValidationCompletedEvent ¶
type ValidationCompletedEvent struct {
Warnings []string // Non-fatal warnings from HAProxy validation
DurationMs int64
// TriggerReason is the reason that triggered this reconciliation.
// Propagated from TemplateRenderedEvent.TriggerReason.
// Examples: "config_change", "debounce_timer", "drift_prevention"
// Used by DeploymentScheduler to determine fallback behavior on validation failure.
TriggerReason string
// ParsedConfig is the pre-parsed desired configuration from syntax validation.
// May be nil if validation cache was used.
// When non-nil, can be passed to downstream sync operations to avoid re-parsing.
ParsedConfig *parser.StructuredConfig
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ValidationCompletedEvent is published when local configuration validation succeeds.
Validation is performed locally using the HAProxy binary. Endpoints are not involved.
This event propagates the correlation ID from TemplateRenderedEvent.
This event implements CoalescibleEvent. The coalescible flag is propagated from TemplateRenderedEvent to enable coalescing throughout the reconciliation pipeline.
func NewValidationCompletedEvent ¶
func NewValidationCompletedEvent(warnings []string, durationMs int64, triggerReason string, parsedConfig *parser.StructuredConfig, coalescible bool, opts ...CorrelationOption) *ValidationCompletedEvent
NewValidationCompletedEvent creates a new ValidationCompletedEvent. Performs defensive copy of the warnings slice.
The coalescible parameter should be propagated from TemplateRenderedEvent.Coalescible() to enable coalescing throughout the reconciliation pipeline.
The parsedConfig parameter contains the pre-parsed desired configuration from syntax validation. Pass nil if validation cache was used or if the parsed config is not available.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewValidationCompletedEvent(warnings, durationMs, triggerReason, parsedConfig, coalescible,
events.PropagateCorrelation(startedEvent))
func (*ValidationCompletedEvent) Coalescible ¶
func (e *ValidationCompletedEvent) Coalescible() bool
Coalescible returns true if this event can be safely skipped when a newer event of the same type is available. This implements the CoalescibleEvent interface.
func (*ValidationCompletedEvent) EventType ¶
func (e *ValidationCompletedEvent) EventType() string
type ValidationFailedEvent ¶
type ValidationFailedEvent struct {
Errors []string // Validation errors from HAProxy
DurationMs int64
// TriggerReason is the reason that triggered this reconciliation.
// Propagated from TemplateRenderedEvent.TriggerReason.
// Examples: "config_change", "debounce_timer", "drift_prevention"
// Used by DeploymentScheduler to determine fallback behavior (deploy cached config on drift prevention).
TriggerReason string
// Correlation embeds correlation tracking for event tracing.
Correlation
// contains filtered or unexported fields
}
ValidationFailedEvent is published when local configuration validation fails.
Validation is performed locally using the HAProxy binary. Endpoints are not involved.
This event propagates the correlation ID from TemplateRenderedEvent.
func NewValidationFailedEvent ¶
func NewValidationFailedEvent(errors []string, durationMs int64, triggerReason string, opts ...CorrelationOption) *ValidationFailedEvent
NewValidationFailedEvent creates a new ValidationFailedEvent. Performs defensive copy of the errors slice.
Use PropagateCorrelation() to propagate correlation from the triggering event:
event := events.NewValidationFailedEvent(errors, durationMs, triggerReason,
events.PropagateCorrelation(startedEvent))
func (*ValidationFailedEvent) EventType ¶
func (e *ValidationFailedEvent) EventType() string