Files
goplt/docs/content/stories/epic0/0.2-configuration-management-system.md

5.4 KiB

Story 0.2: Configuration Management System

Metadata

  • Story ID: 0.2
  • Title: Configuration Management System
  • Epic: 0 - Project Setup & Foundation
  • Status: Pending
  • Priority: High
  • Estimated Time: 4-6 hours
  • Dependencies: 0.1

Goal

Implement a flexible configuration system that loads settings from YAML files, environment variables, and supports type-safe access. The system must be injectable via DI and usable by all modules.

Description

This story implements a complete configuration management system using Viper that provides a clean interface for accessing configuration values. The system supports multiple configuration sources (YAML files, environment variables) with proper precedence and type-safe accessors.

Deliverables

1. Configuration Interface (pkg/config/config.go)

Define ConfigProvider interface with:

  • Get(key string) any - Get any value
  • Unmarshal(v any) error - Unmarshal into struct
  • GetString(key string) string - Type-safe string getter
  • GetInt(key string) int - Type-safe int getter
  • GetBool(key string) bool - Type-safe bool getter
  • GetStringSlice(key string) []string - Type-safe slice getter
  • GetDuration(key string) time.Duration - Type-safe duration getter
  • IsSet(key string) bool - Check if key exists

2. Viper Implementation (internal/config/config.go)

Implement ConfigProvider using Viper:

  • Load config/default.yaml as baseline
  • Merge environment-specific YAML files (development/production)
  • Apply environment variable overrides (uppercase with underscores)
  • Support nested configuration keys (dot notation)
  • Provide all type-safe getters
  • Support unmarshaling into structs
  • Handle configuration validation errors

3. Configuration Loader (internal/config/loader.go)

  • LoadConfig(env string) (ConfigProvider, error) function
  • Environment detection (development/production)
  • Configuration file discovery
  • Validation of required configuration keys
  • Error handling and reporting

4. Configuration Files

Create configuration files:

config/default.yaml - Base configuration:

environment: development
server:
  port: 8080
  host: "0.0.0.0"
  read_timeout: 30s
  write_timeout: 30s
database:
  driver: "postgres"
  dsn: ""
  max_connections: 25
  max_idle_connections: 5
logging:
  level: "info"
  format: "json"
  output: "stdout"

config/development.yaml - Development overrides:

environment: development
logging:
  level: "debug"
  format: "console"

config/production.yaml - Production overrides:

environment: production
logging:
  level: "warn"
  format: "json"

5. DI Integration

  • Provider function for ConfigProvider
  • Register in DI container
  • Make configurable via FX

Implementation Steps

  1. Install Dependencies

    go get github.com/spf13/viper@v1.18.0
    go get github.com/spf13/cobra@v1.8.0
    
  2. Create Configuration Interface

    • Define ConfigProvider interface in pkg/config/config.go
    • Add package documentation
    • Export interface for use by modules
  3. Implement Viper Configuration

    • Create internal/config/config.go
    • Implement all interface methods
    • Handle configuration loading and merging
    • Support nested keys and environment variables
  4. Create Configuration Loader

    • Implement LoadConfig() function
    • Add environment detection logic
    • Add validation logic
    • Handle errors gracefully
  5. Create Configuration Files

    • Create config/default.yaml with base configuration
    • Create config/development.yaml with dev overrides
    • Create config/production.yaml with prod overrides
    • Ensure proper YAML structure
  6. Integrate with DI

    • Create provider function
    • Register in DI container
    • Test injection

Acceptance Criteria

  • ConfigProvider interface is defined and documented
  • Viper implementation loads YAML files successfully
  • Environment variables override YAML values
  • Type-safe getters work correctly (string, int, bool, etc.)
  • Configuration can be unmarshaled into structs
  • Nested keys work with dot notation
  • Configuration system is injectable via DI container
  • All modules can access configuration through interface
  • Configuration validation works
  • Error handling is comprehensive

Implementation Notes

  • Use Viper's automatic environment variable support (uppercase with underscores)
  • Support both single-level and nested configuration keys
  • Consider adding configuration schema validation in future
  • Environment variable format: SERVER_PORT, DATABASE_DSN, etc.
  • Configuration files should be in YAML for readability
  • Support secret manager integration placeholder (Epic 6)

Testing

# Test configuration loading
go test ./internal/config/...

# Test type-safe getters
go run -c "test config getters"

# Test environment variable overrides
export SERVER_PORT=9090
go run cmd/platform/main.go

Files to Create/Modify

  • pkg/config/config.go - Configuration interface
  • internal/config/config.go - Viper implementation
  • internal/config/loader.go - Configuration loader
  • config/default.yaml - Base configuration
  • config/development.yaml - Development configuration
  • config/production.yaml - Production configuration
  • internal/di/providers.go - Add config provider