config

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2025 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package config provides comprehensive configuration management for Go applications using CUE (cuelang.org) for schema definition and validation.

This package implements configuration-driven development principles where application behavior is primarily driven by configuration rather than hardcoded logic. It provides CUE-based schema validation, hot reload capabilities, and type-safe configuration access.

Basic Usage

Initialize with a CUE schema file and configuration file:

manager, err := config.NewManager(config.Options{
	SchemaPath: "schema.cue",
	ConfigPath: "config.yaml",
})
if err != nil {
	log.Fatal(err)
}
defer manager.Close()

// Access configuration values
host, _ := manager.GetString("server.host")
port, _ := manager.GetInt("server.port")

Using Embedded Schema Content

Initialize with embedded CUE schema content (useful for embedded schemas):

//go:embed schema.cue
var schemaContent []byte

manager, err := config.NewManager(config.Options{
	SchemaContent: schemaContent,
	ConfigPath:    "config.yaml",
})
if err != nil {
	log.Fatal(err)
}
defer manager.Close()

Hot Reload

Enable automatic configuration reloading:

ctx := context.Background()
if err := manager.StartHotReload(ctx); err != nil {
	log.Fatal(err)
}

manager.OnConfigChange(func(err error) {
	if err != nil {
		log.Printf("Config reload failed: %v", err)
	} else {
		log.Println("Configuration reloaded")
	}
})

Configuration-Driven Development

Use configuration to dynamically create application components:

components, _ := manager.GetMap("components")
for name, config := range components {
	component := factory.Create(name, config)
	app.Register(component)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChangeNotifier

type ChangeNotifier interface {
	// OnChange registers a callback that is invoked when configuration changes.
	// The callback receives any error that occurred during the change detection.
	OnChange(callback func(error))

	// NotifyChange triggers all registered change callbacks with the given error.
	// If err is nil, it indicates a successful configuration change.
	NotifyChange(err error)
}

ChangeNotifier defines the interface for configuration change notifications.

ChangeNotifier provides a way to register callbacks that are invoked when configuration changes are detected, typically during hot reload.

type Manager

type Manager interface {
	Provider

	// StartHotReload enables automatic configuration reloading when files change.
	// The provided context controls the hot reload lifecycle and can be used to stop it.
	StartHotReload(ctx context.Context) error

	// StopHotReload disables automatic configuration reloading.
	StopHotReload()

	// OnConfigChange registers a callback function that is invoked
	// when configuration changes are detected. The callback receives
	// any error that occurred during reload.
	OnConfigChange(callback func(error))

	// Reload manually reloads the configuration from files.
	// It validates the new configuration before applying it.
	Reload() error

	// Close releases all resources and stops hot reload if active.
	Close() error
}

Manager defines the interface for configuration lifecycle management.

Manager extends Provider with hot reload capabilities, change notifications, and resource cleanup. It orchestrates the complete configuration lifecycle from loading to cleanup.

Example:

manager, err := config.NewManager(options)
if err != nil {
	return err
}
defer manager.Close()

// Enable hot reload
ctx := context.Background()
manager.StartHotReload(ctx)
manager.OnConfigChange(func(err error) {
	if err != nil {
		log.Printf("Reload failed: %v", err)
	}
})

func NewManager

func NewManager(options Options) (Manager, error)

NewManager creates a new configuration manager with the specified options.

NewManager is the main entry point for creating a configuration manager. It loads the CUE schema, parses the configuration file, performs validation, and optionally enables hot reload functionality.

The manager must be closed when no longer needed to release resources:

manager, err := config.NewManager(config.Options{
	SchemaPath: "./schema/config.cue",
	ConfigPath: "./config.yaml",
})
if err != nil {
	return err
}
defer manager.Close()

host, _ := manager.GetString("server.host")
port, _ := manager.GetInt("server.port")

Returns an error if the schema cannot be loaded, configuration cannot be parsed, or hot reload cannot be initialized.

type Options

type Options struct {
	// SchemaPath specifies the path to the CUE schema file or directory.
	// Either SchemaPath or SchemaContent must be provided, but not both.
	// If both are provided, SchemaContent takes precedence.
	SchemaPath string

	// SchemaContent specifies the CUE schema content directly as bytes.
	// This is useful when the schema is embedded in the binary or loaded
	// from a non-file source. Either SchemaPath or SchemaContent must be
	// provided, but not both. If both are provided, SchemaContent takes precedence.
	// Note: Hot reload is not supported when using SchemaContent.
	SchemaContent []byte

	// ConfigPath specifies the path to the configuration file (YAML or JSON).
	// If empty, only schema defaults will be used and no user configuration
	// will be loaded.
	ConfigPath string

	// EnableHotReload determines whether hot reload should be enabled by default.
	// When true, the manager will automatically watch for file changes and
	// reload configuration when they occur.
	// Note: Hot reload is only supported when using SchemaPath, not SchemaContent.
	EnableHotReload bool

	// HotReloadContext provides the context for hot reload operations.
	// If nil, a background context will be used when hot reload is enabled.
	// The context can be used to cancel hot reload operations.
	HotReloadContext context.Context
}

Options defines configuration options for creating a Manager.

Options contains all settings needed to initialize a configuration manager with schema and configuration file paths, hot reload behavior, and other operational parameters.

Example with schema file path:

options := config.Options{
	SchemaPath:      "./schema/config.cue",
	ConfigPath:      "./config.yaml",
	EnableHotReload: true,
}
manager, err := config.NewManager(options)

Example with embedded schema content:

options := config.Options{
	SchemaContent:   []byte(`server: host: string | *"localhost"`),
	ConfigPath:      "./config.yaml",
	EnableHotReload: false, // Hot reload not supported with schema content
}
manager, err := config.NewManager(options)

type Provider

type Provider interface {
	// GetString returns the string value at the specified path.
	// It uses dot notation (e.g., "server.host") for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetString(path string, defaultValue ...string) (string, error)

	// GetInt returns the integer value at the specified path.
	// It uses dot notation (e.g., "server.port") for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetInt(path string, defaultValue ...int) (int, error)

	// GetFloat returns the float64 value at the specified path.
	// It uses dot notation (e.g., "metrics.threshold") for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetFloat(path string, defaultValue ...float64) (float64, error)

	// GetBool returns the boolean value at the specified path.
	// It uses dot notation (e.g., "features.enabled") for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetBool(path string, defaultValue ...bool) (bool, error)

	// GetDuration returns the time.Duration value at the specified path.
	// The underlying value should be a string parseable by time.ParseDuration.
	// It uses dot notation for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetDuration(path string, defaultValue ...time.Duration) (time.Duration, error)

	// GetStringSlice returns the string slice value at the specified path.
	// It uses dot notation (e.g., "server.allowedHosts") for nested access.
	// If the path doesn't exist, it returns the first defaultValue if provided,
	// otherwise it returns an error.
	GetStringSlice(path string, defaultValue ...[]string) ([]string, error)

	// GetMap returns the map value at the specified path.
	// This is useful for accessing complex nested structures.
	// It uses dot notation for nested access.
	GetMap(path string) (map[string]any, error)

	// Exists reports whether the specified configuration path exists.
	// It uses dot notation for path specification.
	Exists(path string) bool

	// Validate validates the current configuration against the CUE schema.
	// It returns an error if validation fails.
	Validate() error
}

Provider defines the interface for accessing configuration values.

Provider provides type-safe access to configuration data with support for dot-notation paths and default values. All methods return typed values extracted from the merged configuration (schema defaults + user config).

Example:

host, err := provider.GetString("server.host")
port, err := provider.GetInt("server.port", 8080)
enabled, err := provider.GetBool("features.auth")

The defaultValue parameters are optional and are used when the path does not exist in the configuration.

type SchemaLoader

type SchemaLoader interface {
	// LoadSchema loads a CUE schema from the specified file or directory path.
	// It validates the schema and prepares it for use in validation and
	// default value extraction.
	LoadSchema(schemaPath string) error

	// LoadSchemaContent loads a CUE schema from the provided content bytes.
	// It validates the schema and prepares it for use in validation and
	// default value extraction. This is useful for embedded schemas or
	// schemas loaded from non-file sources.
	LoadSchemaContent(content []byte) error

	// GetDefaults extracts default values from the loaded schema.
	// It returns a map containing all default values defined in the schema.
	GetDefaults() (map[string]any, error)

	// GetValidator returns a validator for the loaded schema.
	// The validator can be used to validate configurations against the schema.
	GetValidator() (Validator, error)
}

SchemaLoader defines the interface for loading and managing CUE schemas.

SchemaLoader handles loading CUE schema files from the filesystem or from direct content, validating them, and providing schema information for validation and default value extraction.

Example with file path:

loader := NewSchemaLoader()
err := loader.LoadSchema("./schema/config.cue")
if err != nil {
	log.Fatal(err)
}
defaults, err := loader.GetDefaults()
validator, err := loader.GetValidator()

Example with content:

loader := NewSchemaLoader()
err := loader.LoadSchemaContent([]byte(`server: host: string | *"localhost"`))
if err != nil {
	log.Fatal(err)
}
defaults, err := loader.GetDefaults()

func NewSchemaLoader

func NewSchemaLoader() SchemaLoader

NewSchemaLoader creates a new CUE-based schema loader.

The returned loader can load CUE schemas from files or directories, validate them, and extract default values for configuration.

Example:

loader := config.NewSchemaLoader()
err := loader.LoadSchema("./schema/config.cue")
if err != nil {
	log.Fatal(err)
}
defaults, err := loader.GetDefaults()

type Validator

type Validator interface {
	// ValidateConfig validates a complete configuration against the schema.
	// It returns an error if the configuration does not conform to the schema.
	ValidateConfig(config map[string]any) error

	// ValidateValue validates a specific value at a path against the schema.
	// It returns an error if the value does not conform to the schema at that path.
	ValidateValue(path string, value any) error

	// ValidateFile validates a configuration file without loading it.
	// It returns an error if the file does not conform to the schema.
	ValidateFile(configPath string) error
}

Validator defines the interface for configuration validation.

Validator provides methods for validating configuration data against CUE schemas, supporting both complete configurations and individual values.

Jump to

Keyboard shortcuts

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