Help us shape the future of Go! Take the 2026 Go Developer Survey

discovery

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

README

pkg/controller/discovery

HAProxy pod discovery component.

Overview

Tracks the current set of HAProxy pods and the agent endpoints reachable on them. The component does not watch pods directly — it consumes the pod store filled by the resource watcher (via ResourceIndexUpdatedEvent for the configured haproxy-pods resource type) and emits HAProxyPodsDiscoveredEvent with the endpoints it admitted. A removed or replaced endpoint authority causes a HAProxyPodTerminatedEvent carrying the predecessor pod UID before the new fleet publication.

Admission is one rule: the pod has an IP, its agent container is running, and GET /v1/state answers. Neither the container's ready flag nor pod Ready is consulted — HAProxy's /ready only turns 200 after the first apply lands, so requiring it would never admit a fresh pod. The HAProxy version the agent reports travels with the endpoint; the deploy side derives the fleet's template capabilities and each pod's runtime capabilities from it.

The admission cache is keyed on an exact pod namespace, name, UID, container execution epoch and URL, so a replacement pod, a container restart, an image change or a changed URL is probed again while an unchanged pod costs no round trip — discovery re-runs on every drift tick. Every discovery rebuilds the endpoint from the current pod and credentials, so a rotated credential reaches the deployer without another probe. Probes run concurrently (16 at a time): a hung agent must not delay the pass that retires a dead endpoint. Publications are serialized with credential, port and store-reference updates, so a pass that started earlier cannot replace newer endpoint state.

This component runs on all replicas — discovery is a read-only probe and there's no reason to gate it on leadership. It caches the most recent HAProxyPodsDiscoveredEvent via leadership.StateReplayer and re-publishes it on BecameLeaderEvent, so a freshly-elected leader's (leader-only) deployer/scheduler get current pod state without waiting for the next pod-watcher tick.

Quick Start

import "github.com/haproxy-haptic/HAPTIC/pkg/controller/discovery"

component := discovery.New(bus, logger)
go component.Start(ctx)

The component's effective configuration (pod-selector labels, agent port, basic-auth credentials) is provided through the events it subscribes to, not via constructor arguments.

Events

  • Subscribes: ConfigValidatedEvent (agent port + selector), CredentialsUpdatedEvent, ResourceIndexUpdatedEvent (haproxy-pods), ResourceSyncCompleteEvent, BecameLeaderEvent, DriftPreventionTriggeredEvent
  • Publishes: HAProxyPodsDiscoveredEvent, HAProxyPodTerminatedEvent, HAProxyPodRejectedEvent (one per pod that fails admission, labelled agent_container_not_running or agent_unreachable — the metrics component turns these into haptic_haproxy_pods_rejected_total)

License

Apache-2.0 — see root LICENSE.

Documentation

Overview

Package discovery provides the Discovery event adapter component.

It tracks the set of HAProxy pods reported by the resource watcher (via the auto-injected haproxy-pods watcher), admits the ones whose agent answers /v1/state — carrying the HAProxy version it reports — and publishes HAProxyPodsDiscoveredEvent / HAProxyPodTerminatedEvent so the deployer and other consumers know which endpoints to talk to.

Package discovery provides HAProxy pod discovery functionality.

This package implements pure business logic for discovering HAProxy pod endpoints from pod resources: it extracts pod IPs, checks that the agent container is running, and constructs agent endpoints with credentials. Whether the agent answers is the event adapter's half of the rule.

This is a pure component with no event bus dependency - event coordination is handled by the adapter in pkg/controller/discovery.

Index

Constants

View Source
const (
	// ComponentName is the unique identifier for this component.
	ComponentName = "discovery"

	// EventBufferSize is the buffer size for event subscriptions.
	// High-volume to absorb pod churn bursts during scaling and rolling updates.
	EventBufferSize = busevents.HighVolumeSubscriberBuffer
)
View Source
const (
	RejectionAgentNotRunning  = "agent_container_not_running"
	RejectionAgentUnreachable = "agent_unreachable"
)

Rejection reasons, reported as haptic_haproxy_pods_rejected_total{reason}.

Variables

This section is empty.

Functions

This section is empty.

Types

type Candidate

type Candidate struct {
	Endpoint dataplane.Endpoint
	Reason   string // empty when the pod is a candidate
}

Candidate is one pod's verdict: an endpoint the adapter should probe, or the reason the pod is not one.

type Component

type Component struct {
	*component.Base
	// contains filtered or unexported fields
}

Component is the Discovery event adapter.

This component:

  • Subscribes to ConfigValidatedEvent, CredentialsUpdatedEvent, ResourceIndexUpdatedEvent, and BecameLeaderEvent
  • Maintains current state (dataplanePort, credentials, podStore)
  • Calls Discovery.DiscoverEndpoints() when relevant events occur
  • Publishes HAProxyPodsDiscoveredEvent with discovered endpoints
  • Publishes HAProxyPodTerminatedEvent when pods are removed

Event Flow:

  1. ConfigValidatedEvent → Update dataplanePort → Trigger discovery
  2. CredentialsUpdatedEvent → Update credentials → Trigger discovery
  3. ResourceIndexUpdatedEvent (haproxy-pods) → Trigger discovery
  4. BecameLeaderEvent → Re-trigger discovery for new leader's DeploymentScheduler
  5. Discovery completes → Compare with previous endpoints → Publish HAProxyPodTerminatedEvent for removed pods → Publish HAProxyPodsDiscoveredEvent

func New

func New(eventBus *busevents.EventBus, logger *slog.Logger, options ...Option) *Component

New creates a new Discovery event adapter component.

Parameters:

  • eventBus: The event bus for subscribing to and publishing events
  • logger: Structured logger for observability

Returns a configured Component ready to be started.

Note: The Discovery pure component is created lazily when the dataplane port is configured via ConfigValidatedEvent.

func (*Component) HandleEvent

func (c *Component) HandleEvent(event busevents.Event)

HandleEvent implements component.EventHandler: it processes incoming events and triggers discovery as needed.

func (*Component) SetPodStore

func (c *Component) SetPodStore(store types.Store)

SetPodStore sets the pod store reference.

This is called by the controller after creating the haproxy-pods resource watcher. It allows the Discovery component to access pod resources for endpoint discovery.

Thread-safe.

func (*Component) Start

func (c *Component) Start(ctx context.Context) error

Start runs the embedded component.Base event loop until the context is cancelled.

Note: Event subscription occurs in the constructor (New()) to ensure proper startup synchronization. ResourceSyncCompleteEvent is buffered until EventBus.Start() is called, so no events are missed.

type Discovery

type Discovery struct {
	// contains filtered or unexported fields
}

Discovery discovers HAProxy pod endpoints from Kubernetes resources.

This is a pure component that takes a pod store and credentials and returns the pods worth probing. It has no knowledge of events or the event bus - that coordination is handled by the event adapter.

func (*Discovery) DiscoverEndpoints

func (d *Discovery) DiscoverEndpoints(
	podStore types.Store,
	credentials coreconfig.Credentials,
) ([]Candidate, error)

DiscoverEndpoints returns the candidate endpoints from pod resources.

It lists every pod in the store, keeps the ones with an IP whose agent container is running, and builds the agent endpoint from the pod IP, the configured port and the credentials. Whether the agent answers is decided by the caller, which owns the HTTP client.

func (*Discovery) DiscoverEndpointsWithLogger

func (d *Discovery) DiscoverEndpointsWithLogger(
	podStore types.Store,
	credentials coreconfig.Credentials,
	logger *slog.Logger,
) ([]Candidate, error)

DiscoverEndpointsWithLogger is like DiscoverEndpoints but accepts an optional logger for debugging.

type Option

type Option func(*Component)

Option configures discovery's operational connections before startup.

func WithTLS

func WithTLS(source *transportsecurity.Source) Option

WithTLS makes discovery use authenticated HTTPS without a plaintext fallback.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL