config

package
v0.26.0 Latest Latest
Warning

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

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

Documentation

Overview

Package config is the single source of truth for every operator-tunable knob the Gantry agent exposes.

The design docs enumerate configuration in many places (the design doc cache, the design doc direct-origin-fallback / DHT health, the design doc origin-failure circuit breaker, the design doc hosts.toml / upstream registries, the design doc open questions). This package collects them into a single Config struct with field-level documentation pointing at the design-doc citation.

Sources, in increasing precedence:

1. Built-in defaults from NewDefault. 2. YAML file at --config=PATH (optional). 3. Environment variables prefixed GANTRY_. 4. Command-line flags.

Later sources win. Validate runs after all sources have been merged and returns an aggregate of every problem found, not just the first.

Index

Constants

View Source
const (
	// StorageModeContainerd routes reads/writes through the local
	// containerd content store (plan). This is the only
	// accepted storage mode; the legacy hostPath "gantry-cache" mode
	// was removed in plan .
	StorageModeContainerd = "containerd"
)

Recognized StorageMode values.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// RacerEnabled is an environment-only opt-in (GANTRY_RACER_ENABLED).
	// The Racer cache name is fixed to gantry.
	RacerEnabled bool `yaml:"-"`

	// Zero resource limits select SDK defaults. Negative values are invalid.
	RacerMaxConnections           int `yaml:"racer_max_connections"`
	RacerOriginConcurrentRequests int `yaml:"racer_origin_concurrent_requests"`

	// RacerRetryBudget bounds the total backoff one mirror request may spend
	// retrying transient Racer failures, including resuming a response body
	// after a mid-stream failure. Zero disables retries; negative is invalid.
	RacerRetryBudget time.Duration `yaml:"racer_retry_budget"`

	// MirrorListen is the loopback address for containerd's mirror endpoint
	// (the design doc). MUST be loopback-only unless
	// MirrorBindAllowNonLoopback is true (operator opt-in: e.g. when the
	// pod is reached via a hostPort with hostIP=127.0.0.1 DNAT'ing into
	// the pod network - see deploy/gantry/daemonset.yaml).
	MirrorListen string `yaml:"mirror_listen"`

	// MirrorBindAllowNonLoopback relaxes the loopback-only validation on
	// MirrorListen. Set to true ONLY when the deployment guarantees the
	// mirror is unreachable from off-node by some other mechanism - the
	// shipped DaemonSet uses hostPort with hostIP=127.0.0.1, which DNATs
	// the node's loopback into the pod so containerd reaches the mirror
	// over 127.0.0.1 even though the pod itself binds 0.0.0.0. Equivalent
	// alternatives: a host-level firewall blocking the mirror port on
	// non-loopback interfaces, or running the agent in the host network
	// namespace bound to 127.0.0.1. The default (false) is the safe value
	// for any non-Kubernetes deployment. See README.md "Security model"
	// for the full opt-in checklist.
	MirrorBindAllowNonLoopback bool `yaml:"mirror_bind_allow_non_loopback"`

	// ArtifactStreamingEnabled enables the node-local OverlayBD range endpoint
	// on /blobs/ under MirrorListen.
	ArtifactStreamingEnabled bool `yaml:"artifact_streaming_enabled"`

	// ArtifactStreamingAllowedHostSuffixes limits signed-origin requests to
	// approved Azure data endpoints. A leading dot denotes a DNS suffix; values
	// without a leading dot are exact hosts.
	ArtifactStreamingAllowedHostSuffixes []string `yaml:"artifact_streaming_allowed_host_suffixes"`

	// TransferListen is the peer-facing HTTP/2 endpoint (the design doc). The bind is
	// typically 0.0.0.0; cluster-internal isolation comes from
	// NetworkPolicy + the `Gantry-Mirrored: 1` request-header gate +
	// digestpipe integrity verification, not from the bind address. See
	// README.md "Security model" for the full threat model - in
	// particular, the endpoint is plaintext h2c by design and assumes
	// the cluster network is trusted. Operators that need on-the-wire
	// confidentiality should layer a service mesh (Istio / Linkerd /
	// Cilium mTLS) above Gantry.
	TransferListen string `yaml:"transfer_listen"`

	// MetricsListen is the Prometheus scrape endpoint and /readyz /livez
	// kubelet-probe target (the design doc). Default is 0.0.0.0:9095 because both
	// Prometheus (off-node) and the kubelet (off-pod, node-IP source)
	// need to reach it - a loopback default would silently break the
	// DaemonSet's readiness gate. Access control belongs in NetworkPolicy
	// and pod ports, not in the bind address.
	MetricsListen string `yaml:"metrics_listen"`

	// PprofListen is an optional Go runtime profiling endpoint. Empty disables
	// profiling. When enabled it must bind loopback so profiles, command lines,
	// and runtime state are reachable only through local access such as
	// `kubectl port-forward`.
	PprofListen string `yaml:"pprof_listen"`

	// Libp2pListen is the multiaddr(s) the libp2p host advertises (the design doc).
	// Empty means "use libp2p defaults" and pick at random.
	Libp2pListen []string `yaml:"libp2p_listen"`

	// Libp2pIdentityPath is the on-disk path of the persisted libp2p key
	// (the design doc). Lost identity is not catastrophic; old DHT records age out.
	Libp2pIdentityPath string `yaml:"libp2p_identity_path"`

	// Libp2pBootstrapPeers is an optional list of static multiaddrs to seed
	// the libp2p host's connection set on startup. Chair Lease holder addresses
	// provide the dynamic production bootstrap pool.
	Libp2pBootstrapPeers []string `yaml:"libp2p_bootstrap_peers"`

	// Libp2pConnManagerHigh is the connection count above which libp2p trims
	// idle connections back to Libp2pConnManagerLow, and the ceiling the
	// resource manager's connection and file-descriptor limits are sized
	// against.
	//
	// This bounds the DHT's connection appetite, which is otherwise unbounded:
	// a lookup opens a connection to every peer it walks and nothing reclaims
	// them, so a large cluster tends toward a full mesh. The watermark must
	// therefore exceed the working set rather than the fleet size. The working
	// set is the kad-dht routing table (k*log2(N), already Protect()ed by the
	// DHT) plus peers with an in-flight transfer, which grows logarithmically
	// in cluster size; the default leaves roughly a factor of two of headroom
	// at 100k nodes.
	Libp2pConnManagerHigh int `yaml:"libp2p_conn_manager_high"`

	// Libp2pConnManagerLow is the connection count trimming settles at once
	// Libp2pConnManagerHigh is exceeded.
	Libp2pConnManagerLow int `yaml:"libp2p_conn_manager_low"`

	// Libp2pConnManagerGrace is the minimum age a connection must reach
	// before it becomes a trim candidate.
	Libp2pConnManagerGrace time.Duration `yaml:"libp2p_conn_manager_grace"`

	DHTProviderValidity  time.Duration `yaml:"dht_provider_validity"`
	DHTReprovideInterval time.Duration `yaml:"dht_reprovide_interval"`
	DHTMaxReprovideDelay time.Duration `yaml:"dht_max_reprovide_delay"`

	// ChairListen binds the HTTPS listener that serves cold-start please_pull.
	// Keeping the RPC off libp2p puts it on a connection pool the libp2p
	// connection and resource managers do not govern, so a trimmed DHT
	// connection can no longer evict a chair mid-recruitment. Agents share this
	// port by convention, the same way they share the transfer port.
	ChairListen string `yaml:"chair_listen"`

	// NodeName is retained for configuration compatibility. Chair selection
	// uses the persistent libp2p peer ID instead.
	NodeName string `yaml:"node_name"`

	// PodIP rewrites wildcard listeners into the addresses stored in chair
	// Leases.
	PodIP string `yaml:"pod_ip"`

	// MembersKubeconfig is retained by name for compatibility and is used by
	// the chair Lease client. Empty selects in-cluster credentials.
	MembersKubeconfig string `yaml:"members_kubeconfig"`

	ChairNamespace           string        `yaml:"chair_namespace"`
	ChairLeaseDuration       time.Duration `yaml:"chair_lease_duration"`
	ChairRenewPeriod         time.Duration `yaml:"chair_renew_period"`
	ChairRotationPeriod      time.Duration `yaml:"chair_rotation_period"`
	ChairRotationLead        time.Duration `yaml:"chair_rotation_lead"`
	ChairStartupJitter       time.Duration `yaml:"chair_startup_jitter"`
	ChairClaimRoundPeriod    time.Duration `yaml:"chair_claim_round_period"`
	ChairClaimJitter         time.Duration `yaml:"chair_claim_jitter"`
	ChairClaimInitialDivisor int           `yaml:"chair_claim_initial_divisor"`
	ChairClusterSizeEstimate int           `yaml:"chair_cluster_size_estimate"`
	// ChairCapacityDaemonSet supplies actual Gantry scheduling capacity.
	ChairCapacityDaemonSet string `yaml:"chair_capacity_daemonset"`
	// ChairCount caps the number of agents holding fixed chair Leases.
	ChairCount int `yaml:"chair_count"`
	// ChairHolderCount is the deprecated name for ChairCount.
	ChairHolderCount *int `yaml:"chair_holder_count,omitempty"`
	// ChairSeedCount is the per-digest replica count at a full holder pool.
	ChairSeedCount int `yaml:"chair_seed_count"`
	// ChairSeedPercentage is accepted for compatibility with the short-lived
	// capacity-coupled configuration. Holder and seed sizing ignore it.
	ChairSeedPercentage int           `yaml:"chair_seed_percentage,omitempty"`
	ChairAPITimeout     time.Duration `yaml:"chair_api_timeout"`

	// StorageMode selects which backend the agent uses as the read/write
	// content store. Only "containerd" is supported - the legacy
	// "gantry-cache" hostPath backend was removed. The field is
	// retained so existing ConfigMaps that still set it to "containerd"
	// continue to parse, and so a clear migration error surfaces for
	// any operator still on "gantry-cache". It is not exposed as a
	// CLI flag or env var because there is no other valid value to
	// select.
	//
	// Default is "containerd". Exposed via the
	// gantry_storage_mode_info metric for observability.
	StorageMode string `yaml:"storage_mode"`

	// LegacyDeprecated captures YAML fields that used to live on
	// Config but are no longer consumed by any code path. They are
	// kept here purely so existing ConfigMaps that still set
	// `cache_dir`, `cache_budget_bytes`, etc. continue to parse
	// (LoadYAML uses KnownFields=true). New deployments should not
	// set them. A future major version will remove the struct.
	LegacyDeprecated LegacyDeprecatedConfig `yaml:",inline"`

	// ContainerdSocket is the path to the containerd gRPC API socket
	// that the cdsub subsystem dials to discover locally-cached images
	// and announce them on the DHT (the design doc image-event -> Provide loop),
	// that the transfer endpoint reads from on cache miss to serve
	// peers without a re-download, and that the puller writes into on
	// background origin pulls (storage_mode=containerd is the only
	// supported mode; see).
	//
	// REQUIRED in legacy mode. Racer mode does not use containerd.
	// Validate rejects an empty value in legacy mode when
	// storage_mode=containerd (the only accepted storage_mode), which
	// is enforced at startup. The default deploy manifests set it to
	// "/run/containerd/containerd.sock"; operators on non-default
	// socket paths override via `containerd_socket` in the ConfigMap
	// or GANTRY_CONTAINERD_SOCKET in the environment. The agent will
	// fail to start (and readyz will stay 503) if the socket cannot
	// be reached.
	ContainerdSocket string `yaml:"containerd_socket"`

	// ContainerdNamespace is the containerd namespace cdsub watches.
	// Kubelet uses "k8s.io" for pod containers - the default. Set to
	// "moby" for Docker-managed images, or any custom namespace.
	ContainerdNamespace string `yaml:"containerd_namespace"`

	// ContainerdLeaseTTL is the lifetime of containerd content-store
	// leases that Gantry attaches when ingesting blobs. Containerd's
	// garbage collector will not delete content while at least one
	// lease references it, so the TTL governs how long a Gantry-pulled
	// blob is protected before the pod it was pulled for is
	// responsible for keeping it alive via its own image reference.
	// Plan range: 30m–120m. Default 60m.
	ContainerdLeaseTTL time.Duration `yaml:"containerd_lease_ttl"`

	// ContainerdLeaseCleanupInterval is the period at which the agent
	// scans containerd's lease catalog and deletes expired
	// Gantry-owned leases. Defaults to ContainerdLeaseTTL/2 if zero.
	ContainerdLeaseCleanupInterval time.Duration `yaml:"containerd_lease_cleanup_interval"`

	// UpstreamRegistries enumerates every OCI registry the agent mirrors
	// (the design doc, the design doc). The agent rejects requests whose ?ns= does not match
	// one of these once more than one is configured.
	UpstreamRegistries []UpstreamRegistry `yaml:"upstream_registries"`

	// HRWK is the top-K size for HRW probe (the step 3 default 3; the design doc
	// open question).
	HRWK int `yaml:"hrw_k"`

	// PrefetchPullerReplicas is how many distinct HRW-ranked pullers each
	// prefetched layer digest is dispatched to. 1 designates a single origin
	// puller per layer (tightest dedup), but the whole swarm then fans out
	// from ONE initial seed, which bottlenecks a cold thundering-herd (peer
	// transfers pile onto the lone seed and stall). N>1 asks the top-N pullers
	// to origin-pull the layer in parallel, giving N initial seeds so peer
	// transfers fan out N-fold, at the cost of up to N origin copies of each
	// layer. The default is 8.
	PrefetchPullerReplicas int `yaml:"prefetch_puller_replicas"`

	// PrefetchPullerFraction dynamically sizes the initial puller set from the
	// eligible HRW candidate count. Values are fractions in (0, 1], so 0.02
	// selects ceil(nodes * 0.02) pullers. Zero disables dynamic sizing and uses
	// PrefetchPullerReplicas for backward compatibility. Selection is uncapped
	// except by the number of eligible nodes.
	PrefetchPullerFraction float64 `yaml:"prefetch_puller_fraction"`

	// PrefetchCoordinatorReplicas limits Artifact Streaming convergence
	// dispatch to a deterministic HRW-ranked subset of manifest consumers.
	// The default is 3.
	PrefetchCoordinatorReplicas int `yaml:"prefetch_coordinator_replicas"`

	// PrefetchMaxConcurrentGroups caps simultaneous outbound Artifact Streaming
	// prefetch groups per manifest. Dispatch is best effort and target-side
	// deduplicated.
	PrefetchMaxConcurrentGroups int `yaml:"prefetch_max_concurrent_groups"`

	// PrefetchDispatchJitter spreads Artifact Streaming prefetch across
	// requesters. Each node derives a stable delay in [0, jitter) from itself
	// and the manifest.
	PrefetchDispatchJitter time.Duration `yaml:"prefetch_dispatch_jitter"`

	// LayerSeedConcurrency caps simultaneous local layer downloads started by
	// Artifact Streaming reconciliation.
	LayerSeedConcurrency int `yaml:"layer_seed_concurrency"`

	// LayerSeedPeerPatience is how long a seeding node waits for a peer to
	// advertise a layer before falling back to origin. It exists so a large
	// rollout does not convert into one origin pull per node.
	LayerSeedPeerPatience time.Duration `yaml:"layer_seed_peer_patience"`

	// LayerSeedBudget bounds total local seeding time for one manifest.
	LayerSeedBudget time.Duration `yaml:"layer_seed_budget"`

	// HRWTopologyScope selects "cluster" (HRW over all nodes) or "zone"
	// (HRW within the requester's zone) - the design doc / the design doc open question.
	HRWTopologyScope string `yaml:"hrw_topology_scope"`

	// ZoneLabelKey is the Kubernetes node label that identifies the zone
	// when HRWTopologyScope == "zone". Default
	// `topology.kubernetes.io/zone` (the design doc).
	ZoneLabelKey string `yaml:"zone_label_key"`

	// CoordPeerAuthzEnforce is retained so existing ConfigMaps parse, but
	// coord peer authorization was removed with the membership view it
	// compared against. Validate rejects true rather than accepting a
	// setting that would silently do nothing.
	CoordPeerAuthzEnforce bool `yaml:"coord_peer_authz_enforce"`

	// CoordRequireChairAssignment rejects legacy please_pull requests that do
	// not carry a Lease chair generation. Keep false during a mixed-version
	// rollout, then enable it after every agent supports chair metadata.
	CoordRequireChairAssignment bool `yaml:"coord_require_chair_assignment"`

	// CoordMaxDigestsPerRequest caps a single please_pull batch. The default
	// 256 is intentionally far above normal manifest child counts while staying
	// well below the 1 MiB coord envelope budget.
	CoordMaxDigestsPerRequest int `yaml:"coord_max_digests_per_request"`

	// CoordMaxConcurrentPulls caps background origin pulls started by inbound
	// please_pull. Each pull holds an HTTP response body, a containerd writer,
	// goroutine state, and a lease, so this protects the node from fan-out.
	CoordMaxConcurrentPulls int `yaml:"coord_max_concurrent_pulls"`

	// OriginPullProgressTimeout is the maximum time a detached chair origin
	// pull may make no observable progress. It resets whenever response-body
	// bytes arrive. Zero disables Gantry's progress timeout; caller cancellation
	// and origin transport phase timeouts still apply.
	OriginPullProgressTimeout time.Duration `yaml:"origin_pull_progress_timeout"`

	// PeerFetchTimeout caps the complete peer request, including streaming and
	// committing the response body. The default is 15m so progressing large
	// layers are not forced to switch providers at a size-dependent throughput
	// threshold. The HTTP/2 transport separately probes connections after 10s
	// without reads, so dead connections are detected before this safety ceiling.
	// Live stream-through still preserves a verified prefix if the ceiling fires.
	PeerFetchTimeout time.Duration `yaml:"peer_fetch_timeout"`

	// PeerRediscoverBudget bounds the total wall-clock time the mirror keeps
	// re-running DHT FindProviders and retrying peer fetches on a cache miss
	// before it gives up and falls to origin. Re-discovery lets a node pick up
	// finisher-seeds that advertise mid-swarm (the cascade) instead of
	// exhausting a fixed provider set and going to origin. Zero disables
	// re-discovery, restoring the historical single-shot provider attempt.
	// The default is 5m: paired with the strict containerd hosts.toml (shipped
	// in deploy/gantry/node-config.yaml) and TransferMaxConcurrentServes, this
	// drives the validated cold-start cascade.
	PeerRediscoverBudget time.Duration `yaml:"peer_rediscover_budget"`

	// PeerRediscoverBackoff is the pause between re-discovery rounds. It gives
	// newly-finished seeds time to advertise into the DHT before the next
	// FindProviders. It also bounds how long an accepted peer may withhold its
	// first body byte. Zero uses a built-in default of one second.
	PeerRediscoverBackoff time.Duration `yaml:"peer_rediscover_backoff"`

	// TransferMaxConcurrentServes caps concurrent peer blob-body serves on the
	// transfer endpoint. Requests over the cap receive 429 with a Retry-After
	// hint so the requester re-discovers another provider instead of queueing
	// behind a saturated seed. This load-shedding is what lets the first
	// finishers complete early and seed the swarm. Zero means unlimited; the
	// default is 10. Shedding only preserves dedup with the strict containerd
	// hosts.toml (mirror-only, no origin fall-through), where a shed request
	// retries Gantry rather than falling through to origin.
	TransferMaxConcurrentServes int `yaml:"transfer_max_concurrent_serves"`

	// TransferMaxConcurrentRangeServes caps concurrent serves of small bounded
	// ranges, admitted separately from full blob streams. Artifact Streaming
	// reads OverlayBD indexes as a few KiB at a time; those reads are on the
	// container-start critical path and cost almost no bandwidth, so they must
	// not consume the scarce slots that TransferMaxConcurrentServes reserves
	// for large-layer streams. Zero leaves ranges on the blob cap.
	TransferMaxConcurrentRangeServes int `yaml:"transfer_max_concurrent_range_serves"`

	// LayerSeedOriginFallback lets a seeding node pull a layer straight from
	// origin when no peer has it. Leave this off at fleet scale: every node
	// seeds every layer, so an origin fallback turns one cold image into
	// nodes x layers concurrent origin pulls, which saturates the registry and
	// starves the latency-critical range reads that gate container start.
	// Bootstrap is the chair prefetch path's job.
	LayerSeedOriginFallback bool `yaml:"layer_seed_origin_fallback"`

	// RangeCacheDir holds Artifact Streaming ranges fetched from peers or origin.
	// It defaults to a subdirectory of the libp2p hostPath because that is the
	// only node-backed writable mount the agent already has; the container root
	// is read-only and /tmp is an emptyDir subject to ephemeral-storage eviction.
	// Empty disables range caching.
	RangeCacheDir string `yaml:"range_cache_dir"`

	// RangeCacheMaxBytes caps the on-disk range cache. Once reached the cache
	// stops admitting new blobs rather than evicting, so a steady read pattern
	// keeps its working set.
	RangeCacheMaxBytes int64 `yaml:"range_cache_max_bytes"`

	// MaxCachedRangeBytes is the largest single range worth caching. Index
	// reads are a few KiB; anything large is bulk layer traffic that would
	// evict the small reads that actually gate container start.
	MaxCachedRangeBytes int64 `yaml:"max_cached_range_bytes"`

	// IndexPrefetchHeadBytes and IndexPrefetchTailBytes bound the regions
	// warmed when a manifest is served. OverlayBD reads a layer's head and its
	// trailing index at mount time and nothing else, so these cover container
	// start at a fraction of a percent of the image.
	IndexPrefetchHeadBytes int64 `yaml:"index_prefetch_head_bytes"`
	IndexPrefetchTailBytes int64 `yaml:"index_prefetch_tail_bytes"`

	// IndexPrefetchConcurrency caps simultaneous layer warms per node.
	IndexPrefetchConcurrency int `yaml:"index_prefetch_concurrency"`

	// IndexPrefetchJitter spreads the fleet's first wave so a cold image does
	// not put every node on origin in the same instant.
	IndexPrefetchJitter time.Duration `yaml:"index_prefetch_jitter"`

	// AdvertiseReconcileInterval is the cadence of the background
	// advertiser's full inventory reconcile. Eager per-digest advertise on
	// stream completion is the fast path that makes finishers discoverable
	// within milliseconds; this reconcile is the backstop that catches
	// missed events and drives withdraws. Lower values converge faster
	// after a missed event at the cost of more periodic inventory scans.
	AdvertiseReconcileInterval time.Duration `yaml:"advertise_reconcile_interval"`

	// NF5JitterBase is the base delay in the direct-origin-fallback jitter window
	// `[0, base * ln(N))` (the design doc default 3 s).
	NF5JitterBase time.Duration `yaml:"nf5_jitter_base"`

	// NF5JitterCap is a hard ceiling on the computed jitter window.
	// Zero means no cap (original behavior). Set this to bound worst-case
	// cold-start latency on large clusters: at N=300 the uncapped window is
	// ~17s; a cap of 10s limits the maximum additional delay imposed by NF5
	// regardless of cluster size. The configured NF5JitterBase still
	// controls the shape of the distribution up to the cap.
	NF5JitterCap time.Duration `yaml:"nf5_jitter_cap"`

	// NF5PerNodeRateLimit is the per-node direct-origin fallback rate
	// (token bucket, fallbacks/minute; the design doc default 2).
	NF5PerNodeRateLimit int `yaml:"nf5_per_node_rate_limit"`

	// BootstrapWindow is the time after startup during which DHT-empty is
	// not trusted as cold-start evidence (the design doc default 30 s).
	BootstrapWindow time.Duration `yaml:"bootstrap_window"`

	// BootstrapRoutingTablePct is the routing-table-size threshold that
	// supersedes BootstrapWindow once met (the design doc default 25%).
	BootstrapRoutingTablePct int `yaml:"bootstrap_routing_table_pct"`

	// TopKExpansionFactorDegraded is the multiplier applied to HRWK when
	// expanding top-K under Degraded health (the step 5 / the design doc default 2).
	TopKExpansionFactorDegraded int `yaml:"topk_expansion_factor_degraded"`

	OriginFailureCooldownInitial    time.Duration `yaml:"origin_failure_cooldown_initial"`
	OriginFailureCooldownMax        time.Duration `yaml:"origin_failure_cooldown_max"`
	OriginFailureCooldownMultiplier int           `yaml:"origin_failure_cooldown_multiplier"`
	OriginFailureHonorWindowCap     time.Duration `yaml:"origin_failure_honor_window_cap"`

	// OriginFailureClassesTrustedClusterWide controls which the design doc failure
	// classes are propagated cluster-wide as 5xx-immediate (default
	// {auth, not_found, rate_limited}; `transient` is honored locally
	// only).
	OriginFailureClassesTrustedClusterWide []string `yaml:"origin_failure_classes_trusted_cluster_wide"`

	// LogLevel is one of "debug", "info", "warn", "error".
	LogLevel string `yaml:"log_level"`

	// LogFormat is "json" (production) or "text" (development).
	LogFormat string `yaml:"log_format"`
}

Config is the typed configuration surface.

Fields carry YAML tags matching the file names, except environment-only switches such as RacerEnabled. Defaults are set by NewDefault; see Validate for hard correctness constraints.

func Load

func Load(args []string, env func(string) string, configPath string) (*Config, *flag.FlagSet, error)

Load is the convenience composition of NewDefault -> LoadYAML(file) -> LoadEnv -> BindFlags -> fs.Parse(args). It returns the fully-merged Config and the FlagSet for callers that want to print -help text. Validate is the caller's responsibility - Load does not call it so callers can inspect partial configs (e.g., for `gantry version`).

func NewDefault

func NewDefault() *Config

NewDefault returns a Config populated with the design-doc defaults. All fields are set; Validate against this MUST pass.

func (*Config) BindFlags

func (c *Config) BindFlags(fs *flag.FlagSet)

BindFlags registers command-line flags on fs that overlay c. Call after LoadYAML / LoadEnv but before fs.Parse so flags win.

func (*Config) LoadEnv

func (c *Config) LoadEnv(env func(string) string) error

LoadEnv overlays environment variables of the form GANTRY_<UPPER_SNAKE>. Returns a multi-error of any parse failures encountered.

Only scalar fields are overlaid here; list fields (UpstreamRegistries, Libp2pListen, OriginFailureClassesTrustedClusterWide) are file-only by design - env vars are an awkward shape for them.

func (*Config) LoadYAML

func (c *Config) LoadYAML(r io.Reader) error

LoadYAML overlays a YAML document onto c. Unknown fields are an error so typos in config files don't silently no-op.

func (*Config) Redacted

func (c *Config) Redacted() *Config

Redacted returns a copy of c suitable for logging, without endpoint userinfo, queries, or fragments. Invalid endpoints are hidden because their credentials cannot be safely parsed.

func (*Config) ResolveUpstream

func (c *Config) ResolveUpstream(ns string) (UpstreamRegistry, bool)

ResolveUpstream returns the UpstreamRegistry whose Name (or NSAlias) equals ns. Returns false if ns does not match any configured registry.

func (*Config) Validate

func (c *Config) Validate() error

Validate runs hard-correctness checks on c. Returns nil if c is usable; otherwise returns a joined error listing every problem found.

type LegacyDeprecatedConfig

type LegacyDeprecatedConfig struct {
	CacheDir                       string        `yaml:"cache_dir,omitempty"`
	CacheBudgetBytes               int64         `yaml:"cache_budget_bytes,omitempty"`
	CacheForcedEvictionHeadroomPct int           `yaml:"cache_forced_eviction_headroom_pct,omitempty"`
	EvictionProviderCountThreshold int           `yaml:"eviction_provider_count_threshold,omitempty"`
	PodName                        string        `yaml:"pod_name,omitempty"`
	MembersNamespace               string        `yaml:"members_namespace,omitempty"`
	MembersLabelSelector           string        `yaml:"members_label_selector,omitempty"`
	MembersSyncTimeout             time.Duration `yaml:"members_sync_timeout,omitempty"`
}

LegacyDeprecatedConfig captures YAML field names that used to live on Config but no longer have any effect. They are accepted here purely so existing ConfigMaps that still set them parse without error under KnownFields=true. None of these fields are exposed via CLI flags or environment variables - setting them via env/flag is not supported, only YAML round-trips for back-compat. A future major version will remove this struct entirely.

Removal trail : - cache_dir / cache_budget_bytes / cache_forced_eviction_headroom_pct / eviction_provider_count_threshold: the hostPath cache backend was deleted; containerd's own GC owns blob lifetime now.

type UpstreamRegistry

type UpstreamRegistry struct {
	// Name is the canonical identifier (used as the ?ns= value from
	// containerd and as the lookup key for credentials).
	Name string `yaml:"name"`

	// Endpoint is the HTTPS URL of the registry, e.g.
	// "https://registry.example.com".
	Endpoint string `yaml:"endpoint"`

	// CredentialsPath is an optional fallback file containing registry
	// credentials. Format: "username:password" (or "_json_key:<json>" for
	// the well-known GCR pattern). A request-scoped Basic/Bearer credential
	// delegated by containerd takes precedence and is never cached. Setting
	// this file opts the registry into legacy shared-identity mode for requests
	// without delegated auth; leaving it empty enables containerd challenge
	// negotiation for private HTTPS registries.
	CredentialsPath string `yaml:"credentials_path"`

	// NSAlias lets containerd's ?ns= use a different name than Name.
	// Empty means ?ns= must equal Name.
	NSAlias string `yaml:"ns_alias"`
}

UpstreamRegistry describes one OCI registry the agent mirrors.

Jump to

Keyboard shortcuts

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