config

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2025 License: Apache-2.0 Imports: 10 Imported by: 1

README

Test

Config Module

A flexible configuration management module for Go applications with support for YAML/JSON files, environment variables, and type-safe access to configuration values.

Installation

go get github.com/inovacc/config

Features

  • Load configuration from YAML or JSON files
  • Type-safe access to service-specific configuration using generics
  • Support for environment variable overrides with custom prefixes
  • Secure handling of sensitive configuration values
  • Automatic generation of default configuration files with sensible defaults
  • Built-in validation for configuration values
  • Structured logging integration
  • Based on a customized version of Viper for configuration management

Quick Start

Loading and Using Configuration
package main

import (
	"fmt"
	"log"

	"github.com/inovacc/config"
)

type ServiceConfig struct {
	Port int    `yaml:"port"`
	Host string `yaml:"host"`
}

func main() {
	// Initialize with default values
	svc := &ServiceConfig{
		Port: 8080,
		Host: "localhost",
	}

	// Load configuration from file, applying defaults if needed
	if err := config.InitServiceConfig(svc, "config.yaml"); err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}

	// Get the loaded configuration with type safety
	cfg, err := config.GetServiceConfig[*ServiceConfig]()
	if err != nil {
		log.Fatalf("Failed to get service config: %v", err)
	}

	fmt.Printf("Service running on %s:%d\n", cfg.Host, cfg.Port)

	// Access base configuration
	baseCfg := config.GetBaseConfig()
	fmt.Printf("Application ID: %s\n", baseCfg.AppID)
}

Advanced Features

Validation Rules and Default Values

The config module includes built-in validation for configuration values:

  • AppID: Must be at least 8 characters long. If not provided, a UUID is automatically generated.
  • AppSecret: Must be at least 12 characters long. If not provided, a UUID is automatically generated.
  • Logger.LogLevel: Must be one of "DEBUG", "INFO", "WARN", "WARNING", or "ERROR" (case-insensitive).
Creating Default Configuration

You can generate a default configuration file with random credentials using the DefaultConfig function:

// Generate a default config file with a zeroed MyServiceConfig
err := config.DefaultConfig[*MyServiceConfig]("config.yaml")
if err != nil {
    log.Fatal(err)
}
Environment Variable Overrides

You can override configuration values using environment variables:

// Set a prefix for environment variables
config.SetEnvPrefix("APP")

// Now environment variables like APP_PORT will override config values
// For example, setting APP_LOGGER_LOGLEVEL=INFO will override logger.logLevel
Secure Handling of Sensitive Values

The base configuration includes built-in masking for the AppSecret field. You can mark additional fields as sensitive with the sensitive:"true" tag (though note that currently only the base AppSecret field is automatically masked):

type MyConfig struct {
    Username string `yaml:"username"`
    Password string `yaml:"password" sensitive:"true"`
}

// Get a copy with sensitive values masked
secureCfg := config.GetSecureCopy()

// Log configuration safely
config.LogConfig()

Note: Currently, only the AppSecret field in the base configuration is automatically masked. Support for automatically masking custom fields marked with sensitive:"true" is planned for a future release. See IMPROVEMENTS.md for more details.

Project Structure

github.com/inovacc/config/
├── config.go         # Main implementation
├── config_test.go    # Tests
├── go.mod            # Module definition
├── go.sum            # Dependencies
├── internal/         # Internal packages
│   └── viper/        # Customized version of Viper
├── LICENSE           # License information
├── README.md         # Documentation
├── IMPROVEMENTS.md   # Improvement suggestions and future plans
├── Taskfile.yml      # Task runner configuration
└── testdata/         # Test data
    └── config.yaml   # Sample configuration

Future Improvements

The module has several planned improvements documented in the IMPROVEMENTS.md file, including:

  • Configuration reloading: Support for watching configuration files for changes
  • Reflection-based sensitive value handling: Enhance GetSecureCopy to mask all fields with the sensitive:"true" tag
  • Custom validation rules: Support for custom validation of configuration values
  • Configuration versioning: Support for versioning and migration
  • Configuration encryption: Support for encrypting sensitive values
  • Configuration profiles: Support for different environments (dev, test, prod)
  • Comprehensive testing: More tests for edge cases

For more details, see the IMPROVEMENTS.md file.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultConfig

func DefaultConfig[T any](configPath string) error

DefaultConfig generates a base configuration file with random credentials and zeroed service configuration for a given type.

It should be used to bootstrap a config.yaml with sensible defaults.

Example:

err := config.DefaultConfig[*MyServiceConfig]("config.yaml")
if err != nil {
    log.Fatal(err)
}

func GetServiceConfig

func GetServiceConfig[T any]() (T, error)

GetServiceConfig returns the previously registered service-specific configuration with type safety using generics.

If the type does not match what was stored, an error is returned.

Example:

cfg, err := config.GetServiceConfig[*MyServiceConfig]()
if err != nil {
    log.Fatal(err)
}

func InitServiceConfig

func InitServiceConfig(v any, configPath string) error

InitServiceConfig loads a configuration file and binds a service-specific struct to the `Service` field in the global config.

It must be called before accessing the service configuration via GetServiceConfig.

If the configuration file does not exist, a default one will be created. Default values from the provided service config struct will be used if corresponding values are not found in the configuration file.

Example:

type MyServiceConfig struct {
    Port int
    Mode string
}

svc := &MyServiceConfig{
    Port: 8080,  // Default value
    Mode: "dev", // Default value
}

err := config.InitServiceConfig(svc, "config.yaml")
if err != nil {
    log.Fatal(err)
}

func LogConfig

func LogConfig()

LogConfig logs the configuration at debug level, masking sensitive values.

This is a convenience method for safely logging the configuration.

Example:

config.LogConfig()

func SetEnvPrefix

func SetEnvPrefix(prefix string)

SetEnvPrefix sets a prefix for environment variables.

Environment variables that match the pattern {prefix}_* will override the corresponding configuration values. The matching is case-insensitive.

For example, if the prefix is "APP", then the environment variable "APP_LOGGER_LOGLEVEL" will override the value of "logger.logLevel" in the configuration file.

Example:

config.SetEnvPrefix("APP")

Types

type Config

type Config struct {
	ConfigFile string `yaml:"-" mapstructure:"-"`
	Init       bool   `yaml:"-" mapstructure:"-"`
	AppID      string `yaml:"appID" mapstructure:"appID"`
	AppSecret  string `yaml:"appSecret" mapstructure:"appSecret" sensitive:"true"`
	Logger     Logger `yaml:"logger" mapstructure:"logger"`
	Service    any    `yaml:"service" mapstructure:"service"`
	// contains filtered or unexported fields
}

Config represents the global application configuration, including base metadata and a generic field for service-specific configuration.

func GetBaseConfig

func GetBaseConfig() *Config

GetBaseConfig returns a pointer to the global configuration base object.

This allows access to common fields like AppID, Logger, and AppSecret.

Example:

cfg := config.GetBaseConfig()
fmt.Println("AppID:", cfg.AppID)

func GetSecureCopy

func GetSecureCopy() Config

GetSecureCopy returns a copy of the configuration with sensitive values masked.

This is useful for logging or displaying the configuration without exposing sensitive information like secrets or passwords.

Example:

secureCfg := config.GetSecureCopy()
fmt.Printf("%+v\n", secureCfg)

type Logger

type Logger struct {
	LogLevel string `yaml:"logLevel" mapstructure:"logLevel"`
}

Logger defines the configuration for structured logging.

Jump to

Keyboard shortcuts

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