config

package
v0.0.0-...-6ed2b60 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package config holds the agent's runtime configuration as nested sections — one Go file per section, each owning its type, defaults and Validate; this file aggregates them.

Sources override in order: built-in defaults → YAML file → env vars → CLI flags. The YAML file is the only source that moves at runtime, re-read on SIGHUP.

A new section needs four things: its own file with type + defaults + Validate, a field on Config and Defaults, its env vars and flags registered in load.go, and its Validate call added to Config.Validate.

Index

Constants

View Source
const DefaultEnvPrefix = "LACHESIS"

DefaultEnvPrefix is used when Options.EnvPrefix is empty.

View Source
const Version = "1"

Version is the configuration schema version this binary understands. Bumped only on breaking schema changes; consumers gate on it.

Variables

This section is empty.

Functions

func FindConfigPath

func FindConfigPath(opts Options, args []string) string

FindConfigPath returns the YAML config-file path that Load would resolve from args and the environment. Exposed so callers can pass the same path to runtime.New for SIGHUP reload.

Argument order matches Load (opts first, args second) so the two functions read consistently at call sites.

Invariant: this MUST return the same path Load actually reads YAML from. SIGHUP reload watches this result while Load loaded its own internally-resolved path, so any divergence would make reload re-read a different file than the one that booted the agent. Both delegate to findConfigPath; keep it that way. Pinned by TestFindConfigPathMatchesLoad.

Types

type BPFConfig

type BPFConfig struct {
	// PinPath is the BPF FS directory under which maps and programs are
	// pinned. Must be absolute.
	PinPath string `yaml:"pin_path"`
	// AttachPrefixes is the list of interface-name prefixes the
	// netlink subscriber treats as eligible for attach. A new
	// interface matches when its name starts with any prefix here.
	// Default: ["tap"] — the OVN/Neutron convention for VM ports.
	AttachPrefixes []string `yaml:"attach_prefixes"`
	// AttachInterfaces is an explicit allowlist of interface names
	// the netlink subscriber will attach to even when they do not
	// match a prefix. Empty by default. Use for outliers such as a
	// dedicated test interface.
	AttachInterfaces []string `yaml:"attach_interfaces"`
	// UnsafeAllowUnpinnedMaps lets the agent boot when the
	// counter-bearing maps cannot be pinned, degrading crash recovery
	// from zero-loss to the ≤60s WAL-bounded path. Default false is
	// strict: no pinning, no start.
	//
	// It only ever permits UNPINNED operation. An incompatible pin is
	// never adopted — it is removed and recreated fresh.
	//
	// docs/architecture/boot-and-recovery.md#agent-crash-process-killed-kernel-intact
	UnsafeAllowUnpinnedMaps bool `yaml:"unsafe_allow_unpinned_maps"`
}

BPFConfig groups settings for the eBPF subsystem.

func (BPFConfig) Validate

func (c BPFConfig) Validate() error

Validate checks the pin path is absolute and rejects empty entries in the attach allowlists. None of the three attach knobs is checked against the host's interface list — the agent's attach step does that and reports a more precise error. An entirely empty allowlist is allowed on purpose: it is the "attach managed out-of-band" mode the integration tests and some hosts rely on, and the agent logs that no attach source is configured at boot.

type Config

type Config struct {
	Version    string           `yaml:"version"`
	HTTP       HTTPConfig       `yaml:"http"`
	BPF        BPFConfig        `yaml:"bpf"`
	Scrape     ScrapeConfig     `yaml:"scrape"`
	Logging    LoggingConfig    `yaml:"logging"`
	WAL        WALConfig        `yaml:"wal"`
	Neutron    NeutronConfig    `yaml:"neutron"`
	GC         GCConfig         `yaml:"gc"`
	Kafka      KafkaConfig      `yaml:"kafka"`
	Reconcile  ReconcileConfig  `yaml:"reconcile"`
	Unresolved UnresolvedConfig `yaml:"unresolved"`
}

Config is the agent's complete runtime configuration.

func Defaults

func Defaults() Config

Defaults returns the production-ready configuration baseline. Each section's defaults helper lives in its own file.

func Load

func Load(opts Options, args []string) (Config, error)

Load resolves the configuration from defaults, an optional YAML file, environment variables (prefixed with opts.EnvPrefix), and CLI flags, in that order; later sources override earlier.

Pass Options{} for the production-default behaviour; tests and forks supply a custom EnvPrefix or Getenv via the same struct.

The YAML file path is sourced from the -config flag if present in args, otherwise from <prefix>_CONFIG. If neither is set, the YAML layer is skipped.

The returned Config has already been validated; callers can use it without further checks.

func LoadYAML

func LoadYAML(path string) (Config, error)

LoadYAML reads and parses a YAML config file, starting from Defaults and overlaying any fields the file specifies. Unknown YAML keys are rejected as typos. Used by Load and by SIGHUP reload.

func (Config) Tunables

func (c Config) Tunables() tunables.Values

Tunables projects the hot-reloadable subset of the (validated) config into the snapshot shape consumers read live. The projection is the single place that decides WHICH fields are hot — a field absent here is load-time by construction.

func (Config) Validate

func (c Config) Validate() error

Validate aggregates per-section validation. Each section's Validate method lives with its type. Subsection errors are wrapped with the section name for clarity.

type GCConfig

type GCConfig struct {
	// PressureHighWatermark is the telemetry_map fill ratio that starts
	// a relief cycle. Must be < 1.0: relief has to begin before the map
	// is full, because a full PERCPU_HASH makes the kernel drop counter
	// updates on its own — the silent byte loss pressure-relief exists
	// to prevent.
	PressureHighWatermark float64 `yaml:"pressure_high_watermark"`
	// PressureLowWatermark is the fill ratio that ends a relief cycle.
	// Eviction continues every scrape until fill falls below it, so the
	// map settles near this mark rather than oscillating around the high
	// one. Must satisfy 0 < low < high.
	PressureLowWatermark float64 `yaml:"pressure_low_watermark"`
	// PressureMaxPerPass caps how many entries a single scrape evicts.
	// It bounds the worst-case per-scrape stall — roughly 50 µs per
	// kernel delete, so the default 1000 is about 50 ms — which is why
	// draining from the high watermark down to the low one takes a few
	// successive scrapes rather than one long pause. Raising it drains
	// faster at the cost of a longer stall on each scrape that evicts.
	PressureMaxPerPass int `yaml:"pressure_max_per_pass"`
	// GhostGrace is the Lingering-Ghost TTL: how long a deleted port's
	// metadata survives so dying FIN/RST packets
	// still attribute. Shorter = less MAC-reuse exposure; longer =
	// better teardown-tail attribution. Hot-reloadable; applies to
	// ghosts marked after the change.
	GhostGrace time.Duration `yaml:"ghost_grace"`
	// GhostSweepInterval is the ghost-sweep cadence. Hot-reloadable
	// (takes effect at the sweeper's next tick).
	GhostSweepInterval time.Duration `yaml:"ghost_sweep_interval"`
}

GCConfig groups the tunables for pressure-relief eviction of the kernel telemetry_map. All three are hot-reloadable on SIGHUP: the GC reads them through an atomic snapshot, so an operator can retune eviction without an agent restart (a restart briefly stops counting and re-derives the kernel maps).

Kernel maps: docs/architecture/data-structures.md#kernel-side-bpf-maps

They are deliberately YAML-only — no env var or CLI flag. Env and flags are resolved once at boot and cannot hot-reload, so binding these there would imply a liveness those sources can't deliver.

func (GCConfig) Validate

func (c GCConfig) Validate() error

Validate enforces the ordering the eviction hysteresis depends on and the bound that keeps relief from ever disabling itself. A reload that fails here is rejected and the running config is kept (see runtime.Manager.Reload), so a bad edit can never silently switch pressure relief off.

type HTTPConfig

type HTTPConfig struct {
	// Listen is the address to bind, in net.Listen syntax (host:port).
	//
	// The default ":9090" binds all interfaces so Prometheus can scrape
	// /metrics, and the server is unauthenticated — including the
	// /debug endpoints (pprof, runtime tuning; secrets are redacted
	// from /debug/config). On untrusted networks, bind to localhost
	// (e.g. "127.0.0.1:9090") or firewall the port.
	Listen string `yaml:"listen"`
}

HTTPConfig groups settings for the agent's HTTP server, which serves the Prometheus /metrics endpoint and the /debug runtime-tuning endpoints.

func (HTTPConfig) Validate

func (c HTTPConfig) Validate() error

Validate checks the listen address is a parseable host:port.

type KafkaConfig

type KafkaConfig struct {
	// Enabled gates the consumer. When false the agent relies solely on
	// the periodic Neutron reconcile for metadata freshness.
	Enabled bool `yaml:"enabled"`
	// Brokers is the bootstrap broker list (host:port). Required when
	// Enabled.
	Brokers []string `yaml:"brokers"`
	// Topic is the oslo notification topic. The CubeCOS default is
	// "notifications.info" (the INFO-priority topic oslo's Kafka driver
	// writes); override only for a non-standard notification_topics.
	Topic string `yaml:"topic"`
	// GroupID is the consumer-group PREFIX — the effective id is
	// per-agent (see [KafkaConfig.EffectiveGroupID]). The stream must
	// fan out: every agent needs every event, but Kafka delivers a
	// message to only ONE group member, so a shared group starves all
	// but one agent of reconcile kicks.
	GroupID string `yaml:"group_id"`
}

KafkaConfig groups the settings for the consumer that turns OpenStack notifications into reconcile kicks, so metadata refreshes within a pass instead of waiting for the 5-minute safety net.

Enabled defaults to false so the agent runs without a broker.

docs/architecture/trie-construction.md#incremental-updates

func (KafkaConfig) EffectiveGroupID

func (c KafkaConfig) EffectiveGroupID(host, randomFallback string) string

EffectiveGroupID suffixes GroupID with a per-agent token so each agent reads the whole stream rather than load-balancing it away from its peers. Prefers the hostname (stable across restarts, so offsets survive); never falls back to the bare GroupID, which would reintroduce the fanout bug.

func (KafkaConfig) Validate

func (c KafkaConfig) Validate() error

Validate requires a broker list when enabled; Topic and GroupID always carry defaults, so it only guards against an operator blanking them.

type LoggingConfig

type LoggingConfig struct {
	// Level is the minimum severity emitted. One of: debug, info, warn,
	// error. Hot-reloadable via SIGHUP and the /debug/log-level endpoint.
	Level string `yaml:"level"`
	// Format selects the output encoder. One of: json, text.
	// Load-time; restart required to change.
	Format string `yaml:"format"`
}

LoggingConfig groups settings for the logging subsystem.

func (LoggingConfig) Validate

func (c LoggingConfig) Validate() error

Validate checks the level and format are recognized values.

type NeutronConfig

type NeutronConfig struct {
	// Enabled gates the entire Neutron subsystem. When false, the
	// agent boots without metadata; the metrics Collector emits
	// `tenant_id="unknown"` for every flow. Operators must flip
	// this to true in production.
	Enabled bool `yaml:"enabled"`

	// CredentialsFile is an absolute path to a shell file containing
	// `export OS_AUTH_URL=...`, `export OS_USERNAME=...` etc. Mutually
	// exclusive with the inline credential fields below.
	CredentialsFile string `yaml:"credentials_file"`

	// AuthURL is the Keystone v3 endpoint (e.g.
	// "http://keystone.example:5000/v3"). Inline mode only.
	AuthURL string `yaml:"auth_url"`
	// Username is the Keystone user. Inline mode only.
	Username string `yaml:"username"`
	// Password is the Keystone user's password. Inline mode only —
	// prefer CredentialsFile for production, which keeps the
	// secret out of the agent's YAML.
	Password string `yaml:"password"`
	// ProjectName is the Keystone project this agent authenticates
	// against. Inline mode only.
	ProjectName string `yaml:"project_name"`
	// UserDomain is the Keystone domain holding the user (typical
	// "default"). Inline mode only.
	UserDomain string `yaml:"user_domain"`
	// ProjectDomain is the Keystone domain holding the project
	// (typical "default"). Inline mode only.
	ProjectDomain string `yaml:"project_domain"`
	// Region is the Keystone region the Neutron endpoint is served
	// from. Empty means "any" — Keystone returns the first endpoint
	// matching service=network. Inline mode only.
	Region string `yaml:"region"`
	// Interface selects which endpoint-catalog interface the
	// Authenticator uses to discover the Neutron URL: "public",
	// "internal", or "admin". Empty falls through to the agent's
	// "internal" default. Inline mode only.
	Interface string `yaml:"interface"`

	// RequestTimeout caps a single HTTP call (Keystone auth, Neutron
	// list page). The boot-time retry loop is the unit of total
	// patience, not this timeout.
	RequestTimeout time.Duration `yaml:"request_timeout"`
	// RefreshLead is the amount of time before token expiry at which
	// the agent proactively re-authenticates. 5m is safe for the
	// typical 1h Keystone token; tighten only if your deployment
	// issues shorter-lived tokens.
	RefreshLead time.Duration `yaml:"refresh_lead"`

	// UnsafeAllowAmbiguousRoutes lets the agent boot despite
	// static-route ambiguities, which then classify EXTERNAL. Default
	// false is strict. Set true only with informed consent: ambiguous
	// routes systematically mis-bill the CIDR they cover.
	//
	// docs/architecture/trie-construction.md#ambiguity-after-scoping
	UnsafeAllowAmbiguousRoutes bool `yaml:"unsafe_allow_ambiguous_routes"`

	// MaxStaticRouteHops bounds the resolver's trace before it gives up
	// and classifies EXTERNAL. Real deployments rarely exceed 3–4 hops.
	// Hot-reloadable: read only when the trie rebuilds, never on the
	// packet path.
	//
	// docs/architecture/trie-construction.md#the-static-route-resolver
	MaxStaticRouteHops int `yaml:"max_static_route_hops"`
}

NeutronConfig groups the Keystone/Neutron settings behind cold start.

Exactly one credential mode must be set when Enabled: CredentialsFile (an admin-openrc-style file, the system of record for secrets) or the inline fields (convenient for tests, not for production).

Enabled defaults to false so the agent still starts without Keystone reachable.

func (NeutronConfig) MarshalJSON

func (c NeutronConfig) MarshalJSON() ([]byte, error)

MarshalJSON renders the config with Password replaced by the redactedSecret placeholder when set. JSON is the wire format of the unauthenticated GET /debug/config endpoint, so the secret must never reach it; the YAML encoding (the on-disk system of record) is unaffected. An empty Password stays empty so operators can tell "no inline password configured" from "configured but redacted".

func (NeutronConfig) Validate

func (c NeutronConfig) Validate() error

Validate enforces the two-credential-modes contract and the presence of required fields in each mode. When Enabled is false, every other field is permitted to be unset.

type Options

type Options struct {
	// EnvPrefix is prepended to every env var name (e.g. "LACHESIS" yields
	// LACHESIS_HTTP_LISTEN). Empty means [DefaultEnvPrefix].
	EnvPrefix string
	// Getenv is the env-var lookup function. Empty means os.Getenv;
	// tests typically inject their own.
	Getenv func(string) string
}

Options customizes how Load resolves the configuration. The zero value is acceptable; missing fields are filled in with defaults.

type ReconcileConfig

type ReconcileConfig struct {
	// Interval is the periodic full-reconcile cadence — the ceiling on
	// metadata staleness when Kafka is down (Kafka kicks reconcile
	// within seconds when healthy). The /debug sync-stale badge derives
	// from this value. Takes effect at the loop's next tick.
	Interval time.Duration `yaml:"interval"`
}

ReconcileConfig tunes the metadata reconcile loop. Hot-reloadable on SIGHUP: the loop reads it through the tunables snapshot, so an operator can tighten the no-Kafka freshness ceiling live — e.g. during a Kafka outage, when the periodic pass is the only thing bounding how long a new port's traffic misclassifies as `miss`.

func (ReconcileConfig) Validate

func (c ReconcileConfig) Validate() error

Validate bounds the cadence: sub-second periodic full Neutron syncs would hammer the API for no attribution benefit.

type ScrapeConfig

type ScrapeConfig struct {
	// Interval is the cadence at which the scraper drains the BPF map
	// and applies deltas to GlobalState. Minimum 1 second.
	Interval time.Duration `yaml:"interval"`
}

ScrapeConfig groups settings for the BPF map scraper.

func (ScrapeConfig) Validate

func (c ScrapeConfig) Validate() error

Validate ensures the scrape interval is at least one second. Sub-second scraping isn't useful at our timescale and amplifies bench-gate noise.

type UnresolvedConfig

type UnresolvedConfig struct {
	// Cap is the buffer's entry bound. Its EXISTENCE is Contract 1 —
	// an unbounded buffer OOMs under a Kafka outage; only the value
	// is tunable.
	//
	// Contract 1: docs/architecture/contracts.md#required-contracts
	Cap int `yaml:"cap"`
	// TTL is the late-binding window: how long a buffered flow waits
	// for its MAC to resolve before folding to the "unknown" tenant.
	TTL time.Duration `yaml:"ttl"`
}

UnresolvedConfig bounds the late-binding buffer for flows whose VM MAC the metadata layer hasn't learned yet. Both fields are hot-reloadable on SIGHUP; a cap shrink simply triggers the buffer's normal LRU eviction on the next admission.

Lingering Ghost: docs/architecture/data-structures.md#lingering-ghost

func (UnresolvedConfig) Validate

func (c UnresolvedConfig) Validate() error

Validate enforces Contract 1's floor — the cap must exist — and a non-degenerate window.

type WALConfig

type WALConfig struct {
	Path          string        `yaml:"path"`
	FlushInterval time.Duration `yaml:"flush_interval"`
	Enabled       bool          `yaml:"enabled"`
}

WALConfig groups settings for the write-ahead log.

Enabled=false disables both the boot-time restore and the periodic flush goroutine; intended for ephemeral test runs and for hosts where the BPF map is the only state of record.

func (WALConfig) Validate

func (c WALConfig) Validate() error

Validate skips path / interval checks when the WAL is disabled — a disabled WAL is intentionally a no-op subsystem.

Jump to

Keyboard shortcuts

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