Configuration
Manage application configuration with Forge's flexible configuration system
Configuration
Forge provides a flexible configuration management system that supports multiple configuration sources, environment-specific settings, and dynamic configuration updates.
Configuration Manager Interface
The configuration manager provides a unified interface for accessing configuration values:
type ConfigManager interface {
// String values
GetString(key string, defaultValue ...string) string
// Numeric values
GetInt(key string, defaultValue ...int) int
GetInt64(key string, defaultValue ...int64) int64
GetFloat64(key string, defaultValue ...float64) float64
// Boolean values
GetBool(key string, defaultValue ...bool) bool
// Complex types
Unmarshal(key string, dest interface{}) error
// Configuration sources
AddSource(source ConfigSource) error
// Configuration management
Set(key string, value interface{}) error
SetDefault(key string, value interface{}) error
}Configuration Sources
File Sources
YAML Files
config := forge.NewConfigManager()
config.AddSource(forge.NewFileSource("config.yaml"))
config.AddSource(forge.NewFileSource("config.yml"))JSON Files
config := forge.NewConfigManager()
config.AddSource(forge.NewFileSource("config.json"))TOML Files
config := forge.NewConfigManager()
config.AddSource(forge.NewFileSource("config.toml"))Example YAML Configuration:
# config.yaml
app:
name: "my-app"
version: "1.0.0"
environment: "development"
server:
address: ":8080"
timeout: "30s"
database:
host: "localhost"
port: 5432
name: "myapp"
user: "user"
password: "password"
logging:
level: "info"
format: "json"
metrics:
enabled: true
path: "/_/metrics"Environment Variables
Basic Environment Variables
config := forge.NewConfigManager()
config.AddSource(forge.NewEnvSource())Environment Variable Mapping
// Environment variables are mapped to configuration keys
// APP_NAME -> app.name
// SERVER_ADDRESS -> server.address
// DATABASE_HOST -> database.host
export APP_NAME="my-app"
export SERVER_ADDRESS=":8080"
export DATABASE_HOST="localhost"Custom Environment Variable Prefix
config.AddSource(forge.NewEnvSource(forge.WithPrefix("MYAPP_")))
// MYAPP_NAME -> app.name
// MYAPP_SERVER_ADDRESS -> server.addressEnvironment Variable Override
// Environment variables override file configuration
// config.yaml: server.address: ":8080"
// SERVER_ADDRESS=":3000" -> server.address: ":3000"Command Line Arguments
Flag-based Configuration
config := forge.NewConfigManager()
config.AddSource(forge.NewFlagSource())Command Line Usage
# Set configuration values via command line
./my-app --server.address=:8080 --database.host=localhost
# Set boolean values
./my-app --metrics.enabled=true --debug=true
# Set numeric values
./my-app --server.timeout=30 --database.port=5432Custom Flag Names
config.AddSource(forge.NewFlagSource(forge.WithFlagMapping(map[string]string{
"port": "server.address",
"db-host": "database.host",
"db-port": "database.port",
})))Remote Sources
Consul Integration
config := forge.NewConfigManager()
config.AddSource(forge.NewConsulSource(forge.ConsulConfig{
Address: "localhost:8500",
Key: "my-app/config",
}))etcd Integration
config := forge.NewConfigManager()
config.AddSource(forge.NewEtcdSource(forge.EtcdConfig{
Endpoints: []string{"localhost:2379"},
Key: "/my-app/config",
}))Remote Configuration Updates
// Remote sources support dynamic updates
config.AddSource(forge.NewRemoteSource(forge.RemoteConfig{
URL: "https://config.example.com/my-app",
PollInterval: 30 * time.Second,
}))Configuration Access
Basic Value Access
// String values
appName := config.GetString("app.name", "default-app")
version := config.GetString("app.version", "1.0.0")
// Numeric values
port := config.GetInt("server.port", 8080)
timeout := config.GetInt("server.timeout", 30)
// Boolean values
debug := config.GetBool("debug", false)
metricsEnabled := config.GetBool("metrics.enabled", true)
// Float values
rate := config.GetFloat64("rate.limit", 100.0)Complex Type Access
// Unmarshal into struct
type DatabaseConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Name string `yaml:"name"`
User string `yaml:"user"`
Password string `yaml:"password"`
}
var dbConfig DatabaseConfig
config.Unmarshal("database", &dbConfig)Configuration Validation
// Validate configuration
func validateConfig(config ConfigManager) error {
// Required fields
if config.GetString("app.name") == "" {
return errors.New("app.name is required")
}
if config.GetString("database.host") == "" {
return errors.New("database.host is required")
}
// Value ranges
port := config.GetInt("server.port")
if port < 1 || port > 65535 {
return errors.New("server.port must be between 1 and 65535")
}
return nil
}Environment-Specific Configuration
Configuration Files by Environment
config/
├── base.yaml # Base configuration
├── development.yaml # Development overrides
├── staging.yaml # Staging overrides
├── production.yaml # Production overrides
└── testing.yaml # Testing overridesBase Configuration
# config/base.yaml
app:
name: "my-app"
version: "1.0.0"
server:
address: ":8080"
timeout: "30s"
database:
host: "localhost"
port: 5432
name: "myapp"
logging:
level: "info"
format: "json"Environment-Specific Overrides
# config/development.yaml
app:
environment: "development"
database:
host: "localhost"
name: "myapp_dev"
logging:
level: "debug"
format: "console"
debug:
enabled: true# config/production.yaml
app:
environment: "production"
database:
host: "${DB_HOST}"
name: "${DB_NAME}"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
logging:
level: "warn"
format: "json"
metrics:
enabled: true
path: "/_/metrics"Loading Environment-Specific Configuration
func loadConfig(environment string) ConfigManager {
config := forge.NewConfigManager()
// Load base configuration
config.AddSource(forge.NewFileSource("config/base.yaml"))
// Load environment-specific configuration
envConfig := fmt.Sprintf("config/%s.yaml", environment)
config.AddSource(forge.NewFileSource(envConfig))
// Load environment variables
config.AddSource(forge.NewEnvSource())
return config
}Dynamic Configuration
Configuration Updates
// Watch for configuration changes
config.Watch(func(key string, value interface{}) {
log.Printf("Configuration changed: %s = %v", key, value)
// Handle specific configuration changes
switch key {
case "server.address":
// Restart server with new address
restartServer(value.(string))
case "logging.level":
// Update logging level
updateLogLevel(value.(string))
}
})Hot Reload
// Enable hot reload for file sources
config.AddSource(forge.NewFileSource("config.yaml", forge.WithHotReload(true)))
// Handle configuration reload
config.OnReload(func() {
log.Println("Configuration reloaded")
// Update application configuration
updateApplicationConfig(config)
})Configuration Security
Secrets Management
// Use environment variables for secrets
config.AddSource(forge.NewEnvSource())
// Use external secrets management
config.AddSource(forge.NewSecretsSource(forge.SecretsConfig{
Provider: "aws-secrets-manager",
Region: "us-east-1",
Secrets: []string{"database-password", "api-key"},
}))Configuration Encryption
// Encrypt sensitive configuration values
config.AddSource(forge.NewEncryptedSource(forge.EncryptedConfig{
Key: "encryption-key",
Provider: "file",
Path: "config/encrypted.yaml",
}))Configuration Testing
Test Configuration
func TestWithTestConfig(t *testing.T) {
config := forge.NewConfigManager()
// Set test configuration
config.Set("app.name", "test-app")
config.Set("server.port", 8080)
config.Set("database.host", "localhost")
// Test configuration access
assert.Equal(t, "test-app", config.GetString("app.name"))
assert.Equal(t, 8080, config.GetInt("server.port"))
assert.Equal(t, "localhost", config.GetString("database.host"))
}Configuration Validation Testing
func TestConfigValidation(t *testing.T) {
config := forge.NewConfigManager()
// Test valid configuration
config.Set("app.name", "test-app")
config.Set("server.port", 8080)
err := validateConfig(config)
assert.NoError(t, err)
// Test invalid configuration
config.Set("app.name", "")
config.Set("server.port", 0)
err = validateConfig(config)
assert.Error(t, err)
}Best Practices
- Environment Separation: Use separate configuration files for different environments
- Secrets Management: Never commit secrets to version control
- Validation: Validate configuration values at startup
- Defaults: Provide sensible default values
- Documentation: Document all configuration options
- Testing: Test configuration loading and validation
- Security: Use secure methods for handling secrets
- Performance: Cache configuration values when appropriate
For more information about configuration in specific contexts, see the Environment Setup and Deployment guides.
How is this guide?
Last updated on