config

package
v1.147.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package config provides a production-ready configuration bootstrap for Go services built on top of Viper.

The package solves a common problem in service development: keeping configuration loading predictable across local development, CI, and deployment, without repeating boilerplate in every application.

It centralizes:

  • default values
  • local file discovery
  • environment overrides
  • optional remote configuration providers
  • final schema validation

An application integrates by implementing Configuration:

  • SetDefaults(v Viper) to register application-specific defaults
  • Validate() error to enforce final constraints

This is a Viper-based implementation of the configuration model described in: Nicola Asuni, 2014-09-13, "Software Configuration" https://technick.net/guides/software/software_configuration/

Configuration load order

The effective configuration is built in this order (later steps override earlier ones):

  1. Built-in defaults from this package (log and shutdown settings), plus application defaults from SetDefaults.
  2. Local config file (default: config.json) searched in: ./, $HOME/.<cmdName>/, /etc/<cmdName>/ and optionally an explicit configDir (if provided).
  3. Environment variables for remote source selection: <PREFIX>_REMOTECONFIGPROVIDER, <PREFIX>_REMOTECONFIGENDPOINT, <PREFIX>_REMOTECONFIGPATH, <PREFIX>_REMOTECONFIGSECRETKEYRING, <PREFIX>_REMOTECONFIGDATA.
  4. Remote configuration loading, when configured: - provider "envvar": decodes base64 JSON from REMOTECONFIGDATA - other providers: uses Viper remote backends (for example consul, etcd, etcd3, firestore, nats), optionally with a secret keyring
  5. Environment variables are also applied on the final Viper instance, so they can override file/remote values (useful for secrets and runtime overrides). Only keys registered with a default (via SetDefaults) or present in the config file/remote source are candidates for environment overrides: a key that has no default and appears nowhere else is not populated from the environment. Register a default for every configurable key to make it reliably env-overridable.
  6. Validate() is called on the final decoded config struct.

Why this matters

Top features for developers:

  • Predictable precedence model: easy to reason about which value wins.
  • Remote provider support: move configuration out of local files when needed.
  • Sensible shared defaults: common log and shutdown settings are ready to use.
  • Validation hook: fail fast on invalid runtime configuration.
  • Testability: Viper is abstracted behind an interface for easy mocking.

Benefits

Using this package reduces startup/config code in each service, improves configuration consistency across environments, and keeps configuration behavior explicit and auditable.

For a complete implementation example, see: examples/service/internal/cli/config.go

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNilConfiguration is returned when a nil Configuration is passed to Load.
	ErrNilConfiguration = errors.New("configuration must not be nil")

	// ErrLocalConfig indicates a failure while loading the local configuration.
	ErrLocalConfig = errors.New("failed loading local configuration")

	// ErrRemoteConfig indicates a failure while loading the remote configuration.
	ErrRemoteConfig = errors.New("failed loading remote configuration")

	// ErrInvalidRemoteConfig indicates the remote-source selection settings are invalid.
	ErrInvalidRemoteConfig = errors.New("invalid remote source configuration")

	// ErrValidation indicates the final decoded configuration failed validation.
	ErrValidation = errors.New("failed validating configuration")

	// ErrMissingRemoteVar indicates a required remote-provider variable is not set.
	ErrMissingRemoteVar = errors.New("missing required remote configuration variable")
)

Sentinel errors returned by Load and its helpers. Callers can match these with errors.Is to distinguish configuration failure modes.

Functions

func Load

func Load(cmdName, configDir, envPrefix string, cfg Configuration) error

Load builds cfg from defaults, local config, environment, and optional remote sources.

It is the package entry point that standardizes startup configuration loading so applications avoid duplicating Viper wiring and precedence logic.

The function applies the documented merge order, unmarshals into cfg, and executes cfg.Validate before returning.

Types

type BaseConfig

type BaseConfig struct {
	// Log configuration.
	Log LogConfig `mapstructure:"log" validate:"required"`

	// ShutdownTimeout is the time in seconds to wait for graceful shutdown.
	ShutdownTimeout int64 `mapstructure:"shutdown_timeout" validate:"omitempty,min=1,max=3600"`
}

BaseConfig contains the default configuration options to be used in the application config struct.

type Configuration

type Configuration interface {
	// SetDefaults registers a default value for every configurable key.
	//
	// Registering a default for each key is required for environment-variable
	// overrides to work: viper only applies an environment override to a key it
	// already knows about (via a default, the config file, or a remote source).
	// A key with no default that is absent from the file/remote source will not
	// be populated from the environment. Use an empty value (e.g. "") when there
	// is no meaningful default.
	SetDefaults(v Viper)

	// Validate enforces final constraints on the fully decoded configuration.
	// It is invoked by Load after all sources have been merged.
	Validate() error
}

Configuration is the interface we need the application config struct to implement.

type LogConfig

type LogConfig struct {
	// Level is the standard syslog level: EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG.
	Level string `mapstructure:"level" validate:"required,oneof=EMERGENCY ALERT CRITICAL ERROR WARNING NOTICE INFO DEBUG"`

	// Format is the log output format: CONSOLE, JSON.
	Format string `mapstructure:"format" validate:"required,oneof=CONSOLE JSON"`

	// Network is the optional network protocol used to send logs via syslog: udp, tcp.
	Network string `mapstructure:"network" validate:"omitempty,oneof=udp tcp"`

	// Address is the optional remote syslog network address: (ip:port) or just (:port).
	Address string `mapstructure:"address" validate:"omitempty,hostname_port"`
}

LogConfig contains the configuration for the application logger.

type Viper

type Viper interface {
	AddConfigPath(in string)
	AddRemoteProvider(provider, endpoint, path string) error
	AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error
	AllKeys() []string
	AutomaticEnv()
	BindEnv(input ...string) error
	BindPFlag(key string, flag *pflag.Flag) error
	Get(key string) any
	ReadConfig(in io.Reader) error
	ReadInConfig() error
	ReadRemoteConfig() error
	SetConfigName(in string)
	SetConfigType(in string)
	SetDefault(key string, value any)
	SetEnvKeyReplacer(r *strings.Replacer)
	SetEnvPrefix(in string)
	Unmarshal(rawVal any, opts ...viper.DecoderConfigOption) error
}

Viper is the local interface to the actual viper to allow for mocking.

Jump to

Keyboard shortcuts

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