140 lines
4.0 KiB
Go
140 lines
4.0 KiB
Go
// Package config defines the application configuration schema and provides
|
|
// loading from YAML files with environment variable overrides.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Config is the root configuration struct. It is loaded once at startup in
|
|
// main.go and passed to subsystems via constructors.
|
|
type Config struct {
|
|
Source SourceConfig `mapstructure:"source"`
|
|
Backup BackupConfig `mapstructure:"backup"`
|
|
Sync SyncConfig `mapstructure:"sync"`
|
|
Server ServerConfig `mapstructure:"server"`
|
|
TLS TLSConfig `mapstructure:"tls"`
|
|
Log LogConfig `mapstructure:"logging"`
|
|
}
|
|
|
|
// SourceConfig identifies the ScoutFS mount to operate on.
|
|
type SourceConfig struct {
|
|
MountPath string `mapstructure:"mount_path"`
|
|
}
|
|
|
|
// BackupConfig controls backup behavior.
|
|
type BackupConfig struct {
|
|
OutputDir string `mapstructure:"output_dir"`
|
|
ShardMaxBytes int64 `mapstructure:"shard_max_bytes"`
|
|
Parallelism int `mapstructure:"parallelism"`
|
|
Compression string `mapstructure:"compression"`
|
|
CompressionLevel int `mapstructure:"compression_level"`
|
|
Retention RetentionConfig `mapstructure:"retention"`
|
|
}
|
|
|
|
// RetentionConfig controls how many backups to keep.
|
|
type RetentionConfig struct {
|
|
KeepFull int `mapstructure:"keep_full"`
|
|
KeepIncremental int `mapstructure:"keep_incremental"`
|
|
}
|
|
|
|
// SyncConfig controls metadata sync client behavior.
|
|
type SyncConfig struct {
|
|
Remote RemoteConfig `mapstructure:"remote"`
|
|
BatchSize int `mapstructure:"batch_size"`
|
|
Interval time.Duration `mapstructure:"interval"`
|
|
StateDir string `mapstructure:"state_dir"`
|
|
}
|
|
|
|
// RemoteConfig identifies the remote sync server.
|
|
type RemoteConfig struct {
|
|
Address string `mapstructure:"address"`
|
|
}
|
|
|
|
// ServerConfig controls the gRPC server for metadata sync.
|
|
type ServerConfig struct {
|
|
ListenAddress string `mapstructure:"listen_address"`
|
|
TargetMount string `mapstructure:"target_mount"`
|
|
}
|
|
|
|
// TLSConfig controls mTLS for gRPC connections.
|
|
type TLSConfig struct {
|
|
CACert string `mapstructure:"ca_cert"`
|
|
Cert string `mapstructure:"cert"`
|
|
Key string `mapstructure:"key"`
|
|
Mutual bool `mapstructure:"mutual"`
|
|
}
|
|
|
|
// LogConfig controls structured logging output.
|
|
type LogConfig struct {
|
|
Level string `mapstructure:"level"`
|
|
Format string `mapstructure:"format"`
|
|
Output string `mapstructure:"output"`
|
|
}
|
|
|
|
// Defaults returns a Config with sensible default values.
|
|
func Defaults() *Config {
|
|
return &Config{
|
|
Backup: BackupConfig{
|
|
ShardMaxBytes: 1 << 30, // 1 GiB
|
|
Parallelism: 8,
|
|
Compression: "zstd",
|
|
CompressionLevel: 3,
|
|
Retention: RetentionConfig{
|
|
KeepFull: 4,
|
|
KeepIncremental: 30,
|
|
},
|
|
},
|
|
Sync: SyncConfig{
|
|
BatchSize: 500,
|
|
Interval: 5 * time.Minute,
|
|
},
|
|
Server: ServerConfig{
|
|
ListenAddress: ":9443",
|
|
},
|
|
TLS: TLSConfig{
|
|
Mutual: true,
|
|
},
|
|
Log: LogConfig{
|
|
Level: "info",
|
|
Format: "json",
|
|
Output: "stderr",
|
|
},
|
|
}
|
|
}
|
|
|
|
// Validate checks that the config contains valid values for the fields that
|
|
// are populated. It does not require all fields to be set since different
|
|
// commands use different subsets.
|
|
func (c *Config) Validate() error {
|
|
if c.Backup.Parallelism < 1 {
|
|
return fmt.Errorf("backup.parallelism must be >= 1, got %d", c.Backup.Parallelism)
|
|
}
|
|
if c.Backup.ShardMaxBytes < 1024*1024 {
|
|
return fmt.Errorf("backup.shard_max_bytes must be >= 1 MiB, got %d", c.Backup.ShardMaxBytes)
|
|
}
|
|
if c.Sync.BatchSize < 1 {
|
|
return fmt.Errorf("sync.batch_size must be >= 1, got %d", c.Sync.BatchSize)
|
|
}
|
|
switch c.Backup.Compression {
|
|
case "zstd", "none", "":
|
|
// valid
|
|
default:
|
|
return fmt.Errorf("backup.compression must be \"zstd\" or \"none\", got %q", c.Backup.Compression)
|
|
}
|
|
switch c.Log.Level {
|
|
case "debug", "info", "warn", "error", "":
|
|
// valid
|
|
default:
|
|
return fmt.Errorf("logging.level must be debug|info|warn|error, got %q", c.Log.Level)
|
|
}
|
|
switch c.Log.Format {
|
|
case "json", "text", "":
|
|
// valid
|
|
default:
|
|
return fmt.Errorf("logging.format must be json|text, got %q", c.Log.Format)
|
|
}
|
|
return nil
|
|
}
|