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

sync

package
v0.5.1 Latest Latest
Warning

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

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

Documentation

Overview

Package sync maintains the agent's single persistent stream to the control plane and applies versioned desired-state updates in order (ADR-0002, ADR-0015). Every stream starts with Hello and receives a snapshot; deltas follow on the same stream. Each update is applied atomically through the enforce.PolicyStore and acknowledged; a failed apply leaves the last good policy installed and is acknowledged FAILED, after which the control plane sends a fresh snapshot. Reconnects use exponential backoff with full jitter. Persistence of the last applied policy to disk, which makes the agent fail static across restarts (ADR-0011), lands with enforcement behind the same store interface.

Index

Constants

This section is empty.

Variables

View Source
var ErrReconnectDirected = errors.New("sync: reconnect directed")

ErrReconnectDirected is returned when the control plane directs the agent to reconnect immediately.

View Source
var ErrReenrollRequired = errors.New("sync: control plane directed re-enrollment; enroll again with a new provisioning token")

ErrReenrollRequired is returned by Run when the control plane directs the workload to re-enroll. The daemon cannot do that itself: enrollment needs a provisioning token delivered out of band (ADR-0016).

Functions

func Backoff

func Backoff(attempt int, base, limit time.Duration, rng *rand.Rand) time.Duration

Backoff returns the wait before reconnect attempt number attempt (1 for the first retry): a random duration in [0, min(cap, base × 2^attempt)], so that a control-plane restart produces a smooth trickle of handshakes rather than a synchronized wave (ADR-0002).

func DialGRPC

DialGRPC is the production dialer: mutual TLS with the holder's current credential, refreshed at each handshake. The flow reporter dials with it too, on its own connection.

Types

type Config

type Config struct {
	// Server is the control-plane address, host:port.
	Server string
	// Holder presents the workload credential.
	Holder *credential.Holder
	// Store receives each complete policy.
	Store enforce.PolicyStore
	// AgentVersion and Capabilities are reported in Hello.
	AgentVersion string
	Capabilities []string
	// Facts and ListeningServices are collected for Hello and for every
	// inventory report. Either may be nil.
	Facts             func() *innerwallv1.HostFacts
	ListeningServices func() []*innerwallv1.ListeningService
	Log               *slog.Logger
	// BackoffBase and BackoffCap bound the reconnect wait: one second and
	// five minutes when zero.
	BackoffBase time.Duration
	BackoffCap  time.Duration
	// HelloTimeout bounds the wait for HelloAck; 30 seconds when zero.
	HelloTimeout time.Duration
	// Dial replaces the default dialer.
	Dial Dialer
	// Uptime reports the daemon's uptime for heartbeats; measured from
	// New when nil.
	Uptime func() time.Duration
	// DroppedFlowRecords reports the flow records the collection loop has
	// dropped to buffer pressure, carried on every heartbeat. Zero when nil.
	DroppedFlowRecords func() uint64
	// SourceOverruns reports the kernel-side overruns of the flow sources
	// since the agent started, carried on every heartbeat. Zero when nil.
	SourceOverruns func() uint64
	// RenewalError reports the reason the last automatic credential
	// renewal failed, or empty, carried on every heartbeat. Empty when nil.
	RenewalError func() string
	// OwnedTable reads whether the owned firewall table is in the kernel,
	// carried on every heartbeat, so a table removed behind the daemon's
	// back (the local kill switch) is reported within one heartbeat.
	// Unspecified when nil.
	OwnedTable func(ctx context.Context) innerwallv1.OwnedTableState
	// OnSyncConfig is called with the configuration in every HelloAck, so
	// the other loops adopt the control plane's parameters.
	OnSyncConfig func(*innerwallv1.SyncConfig)
	// OnReconnect reports reconnect attempts and their scheduled wait; nil
	// when unused.
	OnReconnect func(attempt int, wait time.Duration)
}

Config configures a Daemon.

type Daemon

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

Daemon is the agent's sync loop.

func New

func New(cfg Config) *Daemon

New builds a daemon.

func (*Daemon) Run

func (d *Daemon) Run(ctx context.Context) error

Run maintains the stream until ctx ends, reconnecting with backoff after failures, and immediately upon directed reconnects. Every reconnect is a fresh Hello and snapshot. It returns ErrReenrollRequired when the control plane says so; every other stream error is a reason to reconnect, not to stop.

type Dialer

type Dialer func(ctx context.Context, server string, holder *credential.Holder) (innerwallv1.AgentServiceClient, io.Closer, error)

Dialer opens a connection to the control plane. The default dials gRPC over the holder's TLS configuration; tests substitute a loopback.

Jump to

Keyboard shortcuts

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