config

package
v0.0.34 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package config provides a small, embeddable base configuration shared by ToolHive-ecosystem services, plus a strict YAML loader for it.

Scope

This package only owns fields that are truly universal across services: service identity, logging, and deployment environment. It does not define per-service schema (database DSNs, upstream URLs, feature flags, etc.) — those belong in each consuming service's own config struct. It also does not impose a fixed vocabulary for values that vary by deployment, such as Environment — those stay freeform strings.

Env-var interpolation (e.g. expanding "${VAR}" in YAML values) is deliberately out of scope for now. Several open questions (syntax, missing-variable behavior, which fields are eligible, whether it should take an env.Reader for testability) are better decided against the actual loader this package is meant to absorb than designed speculatively here.

Basic Usage

A service defines its own config struct and embeds BaseConfig inline so the base fields decode at the top level of the YAML document alongside the service's own fields:

type Config struct {
	config.BaseConfig `yaml:",inline"`

	Gateway GatewayConfig `yaml:"gateway"`
}

type GatewayConfig struct {
	ID string `yaml:"id"`
}

var cfg Config
if err := config.Load("service.yaml", &cfg); err != nil {
	// handle error
}

Validation

BaseConfig.Validate checks only the base fields. Each service should call it from its own Validate method, then add its own cross-field checks:

func (c *Config) Validate() error {
	if err := c.BaseConfig.Validate(); err != nil {
		return err
	}
	if c.Gateway.ID == "" {
		return errors.New("gateway.id is required")
	}
	return nil
}

Stability

This package is Alpha stability. The API may change without notice. See the toolhive-core README for stability level definitions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode[T any](r io.Reader, cfg *T, opts ...Option) error

Decode reads YAML from r and decodes it into cfg. By default, decoding is strict: unknown fields anywhere in the document are rejected, including fields under a service's own sections. This is the same behavior consuming services get by hand-rolling yaml.NewDecoder(...).KnownFields(true); Decode exists so every service gets it uniformly. Pass AllowUnknownFields to relax this.

Use Decode directly (rather than Load) when the config doesn't come from a plain file path — an embedded FS, a remote fetch, or an in-memory byte slice in a test.

func Load

func Load[T any](path string, cfg *T, opts ...Option) error

Load reads the YAML file at path and decodes it into cfg. See Decode for the decoding behavior.

Load does not call Validate — callers validate explicitly after loading, since only the caller's concrete config type knows its own required fields.

Types

type BaseConfig

type BaseConfig struct {
	// ServiceName identifies the service in logs, metrics, and traces.
	// Required.
	ServiceName string `yaml:"serviceName"`

	// LogLevel is the minimum log level: "debug", "info", "warn", or
	// "error". Defaults to "info" when empty.
	LogLevel string `yaml:"logLevel"`

	// Environment identifies the deployment tier a service is running in
	// (e.g. "dev", "staging", "prod"). Deployments name their environments
	// differently, so this is a freeform string with no fixed set of
	// values and no validation.
	Environment string `yaml:"env"`
}

BaseConfig holds configuration fields common to every ToolHive-ecosystem service. Consuming services embed it inline in their own config struct rather than referencing it as a nested field, so the fields decode at the top level of the YAML document:

type Config struct {
	config.BaseConfig `yaml:",inline"`
	// service-specific fields below
}

func (*BaseConfig) Validate

func (c *BaseConfig) Validate() error

Validate checks the base fields and returns the first violation encountered. It does not know about, and does not validate, any fields a consuming service adds alongside it.

type Option

type Option func(*decodeOptions)

Option configures Load and Decode.

func AllowUnknownFields

func AllowUnknownFields() Option

AllowUnknownFields disables strict decoding, so unknown fields in the YAML document are silently ignored instead of rejected. The default behavior (no options) is strict.

Prefer leaving decoding strict where possible — it catches typos in field names that would otherwise fail silently. Use this only when a consumer genuinely needs to tolerate fields it doesn't know about yet (e.g. a rolling deploy reading a config written by a newer version).

Jump to

Keyboard shortcuts

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