Add package declarations across the Go scaffold, YAML configuration loading and validation, and a minimal API entry point. Add development and production Compose files, a multi-stage Docker image, configuration template, and Make targets. Remove the directory scaffolding script.
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
const defaultConfigPath = "configs/config.example.yaml"
|
|
|
|
// Config contains the settings required to start the application.
|
|
type Config struct {
|
|
Environment string `yaml:"environment"`
|
|
HTTP HTTPConfig `yaml:"http"`
|
|
Database DatabaseConfig `yaml:"database"`
|
|
}
|
|
|
|
type HTTPConfig struct {
|
|
Address string `yaml:"address"`
|
|
}
|
|
|
|
type DatabaseConfig struct {
|
|
URL string `yaml:"url"`
|
|
}
|
|
|
|
// LoadConfig reads configuration from YAML, applies environment overrides,
|
|
// and validates the result. An empty path uses CONFIG_FILE when set.
|
|
func LoadConfig(path string) (Config, error) {
|
|
if path == "" {
|
|
path = os.Getenv("CONFIG_FILE")
|
|
}
|
|
if path == "" {
|
|
path = defaultConfigPath
|
|
}
|
|
|
|
contents, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return Config{}, fmt.Errorf("read config %q: %w", path, err)
|
|
}
|
|
|
|
var config Config
|
|
if err := yaml.Unmarshal(contents, &config); err != nil {
|
|
return Config{}, fmt.Errorf("parse config %q: %w", path, err)
|
|
}
|
|
|
|
applyEnvironment(&config)
|
|
if err := config.Validate(); err != nil {
|
|
return Config{}, fmt.Errorf("validate config: %w", err)
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
func (config Config) Validate() error {
|
|
var missing []string
|
|
if strings.TrimSpace(config.Environment) == "" {
|
|
missing = append(missing, "environment")
|
|
}
|
|
if strings.TrimSpace(config.HTTP.Address) == "" {
|
|
missing = append(missing, "http.address")
|
|
}
|
|
if strings.TrimSpace(config.Database.URL) == "" {
|
|
missing = append(missing, "database.url")
|
|
}
|
|
if len(missing) > 0 {
|
|
return errors.New("missing required values: " + strings.Join(missing, ", "))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func applyEnvironment(config *Config) {
|
|
if value := os.Getenv("APP_ENVIRONMENT"); value != "" {
|
|
config.Environment = value
|
|
}
|
|
if value := os.Getenv("APP_HTTP_ADDRESS"); value != "" {
|
|
config.HTTP.Address = value
|
|
}
|
|
if value := os.Getenv("APP_DATABASE_URL"); value != "" {
|
|
config.Database.URL = value
|
|
}
|
|
}
|