Improve basic example to showcase all resolver types
- Replace simple ENV-only example with diverse resolver showcase - Add GCP Secret Manager, AWS Secrets Manager, Vault examples in main config - Add JSON resolver example for loading service configs and feature flags - Add Consul, K8S, and FILE resolvers for different config aspects - Include example JSON files to show what JSON resolver references - Update Go code to demonstrate accessing the various config types - Move away from env-centric example to show full power upfront
This commit is contained in:
parent
81eddf2b38
commit
e6db26d2c4
135
README.md
135
README.md
@ -40,33 +40,49 @@ go get git.eeqj.de/sneak/smartconfig
|
||||
|
||||
```yaml
|
||||
# config.yaml
|
||||
# Example with top-level values for easy access
|
||||
# Showcase the power of multiple resolver types
|
||||
app_name: ${ENV:APP_NAME}
|
||||
port: ${ENV:PORT} # Becomes number 8080 if PORT="8080"
|
||||
debug_mode: ${ENV:DEBUG_MODE} # Becomes boolean true if DEBUG_MODE="true"
|
||||
cache_size_bytes: ${ENV:CACHE_SIZE} # Human-readable: "100MB", "1.5GB"
|
||||
version: ${FILE:/app/VERSION} # Read from file
|
||||
port: ${ENV:PORT} # Number if PORT="8080"
|
||||
debug_mode: ${ENV:DEBUG_MODE} # Boolean if "true"/"false"
|
||||
|
||||
# Nested configuration for organization
|
||||
server:
|
||||
host: localhost
|
||||
port: ${ENV:SERVER_PORT}
|
||||
name: "server-${ENV:INSTANCE_ID}" # Always a string due to mixed content
|
||||
# External service configuration from JSON config file
|
||||
services: ${JSON:/etc/config/services.json:production} # Load entire object
|
||||
|
||||
# API credentials from cloud secret managers
|
||||
api_keys:
|
||||
stripe: ${GCPSM:projects/myproject/secrets/stripe-api-key}
|
||||
sendgrid: ${AWSSM:prod/sendgrid-api-key}
|
||||
twilio: ${VAULT:secret/data/api:twilio_key}
|
||||
datadog: ${ENV:DD_API_KEY} # Fallback to env for local dev
|
||||
|
||||
# Database configuration with mixed sources
|
||||
database:
|
||||
host: ${ENV:DB_HOST}
|
||||
port: ${ENV:DB_PORT}
|
||||
host: ${CONSUL:service/postgres/address}
|
||||
port: ${CONSUL:service/postgres/port}
|
||||
name: ${ENV:DB_NAME}
|
||||
username: ${ENV:DB_USER}
|
||||
password: ${VAULT:secret/data/myapp:db_password}
|
||||
password: ${GCPSM:projects/myproject/secrets/db-password}
|
||||
|
||||
features:
|
||||
cache_enabled: ${ENV:CACHE_ENABLED} # Boolean if "true"/"false"
|
||||
max_connections: ${ENV:MAX_CONN} # Number if numeric string
|
||||
debug: ${ENV:FEATURES_DEBUG}
|
||||
# SSL configuration from multiple sources
|
||||
ssl:
|
||||
enabled: ${ENV:DB_SSL_ENABLED}
|
||||
ca_cert: ${FILE:/etc/ssl/db-ca.crt}
|
||||
client_cert: ${K8SS:default/db-certs:client.crt}
|
||||
|
||||
# Feature flags from JSON file
|
||||
features: ${JSON:/etc/config/features.json:${ENV:ENVIRONMENT}}
|
||||
|
||||
# Server configuration
|
||||
server:
|
||||
listen: "0.0.0.0:${ENV:PORT}"
|
||||
workers: ${EXEC:nproc} # Dynamic based on CPU cores
|
||||
hostname: ${EXEC:hostname -f}
|
||||
|
||||
env:
|
||||
# These will be exported as environment variables
|
||||
API_TOKEN: ${AWSSM:api-token}
|
||||
SLACK_WEBHOOK: ${FILE:/etc/secrets/slack_webhook.txt}
|
||||
# Export these as environment variables for child processes
|
||||
DATABASE_URL: "postgres://${ENV:DB_USER}:${GCPSM:projects/myproject/secrets/db-password}@${CONSUL:service/postgres/address}:5432/${ENV:DB_NAME}"
|
||||
NEW_RELIC_LICENSE: ${AWSSM:monitoring/newrelic-license}
|
||||
```
|
||||
|
||||
### Go Code
|
||||
@ -77,6 +93,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"git.eeqj.de/sneak/smartconfig"
|
||||
)
|
||||
@ -88,29 +105,77 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Access typed values (top-level keys only)
|
||||
port, err := config.GetInt("port")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Access typed values
|
||||
appName, _ := config.GetString("app_name")
|
||||
port, _ := config.GetInt("port")
|
||||
debugMode, _ := config.GetBool("debug_mode")
|
||||
|
||||
// For nested values, navigate manually
|
||||
fmt.Printf("Starting %s on port %d (debug: %v)\n", appName, port, debugMode)
|
||||
|
||||
// Access nested values
|
||||
data := config.Data()
|
||||
var debugMode bool
|
||||
if features, ok := data["features"].(map[string]interface{}); ok {
|
||||
if debug, ok := features["debug"].(bool); ok {
|
||||
debugMode = debug
|
||||
|
||||
// API keys configuration
|
||||
if apiKeys, ok := data["api_keys"].(map[string]interface{}); ok {
|
||||
if stripe, ok := apiKeys["stripe"].(string); ok {
|
||||
fmt.Printf("Stripe API key loaded: %s...\n", stripe[:8])
|
||||
}
|
||||
}
|
||||
|
||||
// Human-readable byte sizes (top-level)
|
||||
cacheSize, err := config.GetBytes("cache_size_bytes")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
// Database configuration
|
||||
if db, ok := data["database"].(map[string]interface{}); ok {
|
||||
host, _ := db["host"].(string)
|
||||
port, _ := db["port"].(int)
|
||||
fmt.Printf("Database: %s:%d\n", host, port)
|
||||
}
|
||||
|
||||
fmt.Printf("Server running on port %d (debug: %v)\n", port, debugMode)
|
||||
fmt.Printf("Cache size: %d bytes\n", cacheSize)
|
||||
// Check loaded services from JSON file
|
||||
if services, ok := data["services"].(map[string]interface{}); ok {
|
||||
fmt.Printf("Loaded %d services from JSON config\n", len(services))
|
||||
}
|
||||
|
||||
// Environment variables are now available
|
||||
fmt.Printf("DATABASE_URL env var: %s\n", os.Getenv("DATABASE_URL"))
|
||||
}
|
||||
```
|
||||
|
||||
Example JSON files referenced above:
|
||||
|
||||
```json
|
||||
// /etc/config/services.json
|
||||
{
|
||||
"production": {
|
||||
"api": {
|
||||
"endpoint": "https://api.example.com",
|
||||
"timeout": 30,
|
||||
"retries": 3
|
||||
},
|
||||
"cache": {
|
||||
"provider": "redis",
|
||||
"ttl": 3600
|
||||
}
|
||||
},
|
||||
"staging": {
|
||||
"api": {
|
||||
"endpoint": "https://api-staging.example.com",
|
||||
"timeout": 60,
|
||||
"retries": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /etc/config/features.json
|
||||
{
|
||||
"production": {
|
||||
"new_ui": false,
|
||||
"rate_limiting": true,
|
||||
"analytics": true
|
||||
},
|
||||
"staging": {
|
||||
"new_ui": true,
|
||||
"rate_limiting": true,
|
||||
"analytics": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user