clavitor/clavis/clavis-vault/edition/config.go

80 lines
2.2 KiB
Go

//go:build commercial
// Package edition - Commercial replication configuration loading.
// This file is built ONLY when the "commercial" build tag is specified.
//
// YAML config loading for /etc/clavitor/replication.yaml
// Community Edition does not load replication config.
package edition
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// LoadReplicationConfig loads and validates /etc/clavitor/replication.yaml
// Returns error if file missing, invalid, or primary role lacks backup config.
// This is MANDATORY for Commercial Edition - vault refuses to start without it.
func LoadReplicationConfig(path string) (*ReplicationConfig, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("cannot read replication config: %w", err)
}
var cfg ReplicationConfig
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("invalid replication config YAML: %w", err)
}
// Validation
if cfg.POPID == "" {
return nil, fmt.Errorf("pop_id is required")
}
if cfg.Region == "" {
return nil, fmt.Errorf("region is required")
}
if cfg.Role != "primary" && cfg.Role != "backup" {
return nil, fmt.Errorf("role must be 'primary' or 'backup', got: %s", cfg.Role)
}
// Primary role requires backup_pop configuration
if cfg.Role == "primary" {
if cfg.BackupPOP.URL == "" {
return nil, fmt.Errorf("primary role requires backup_pop.url")
}
if cfg.BackupPOP.ID == "" {
return nil, fmt.Errorf("primary role requires backup_pop.id")
}
// Check auth token file exists
tokenFile := cfg.Auth.TokenFile
if tokenFile == "" {
tokenFile = cfg.BackupPOP.AuthTokenFile
}
if tokenFile == "" {
return nil, fmt.Errorf("primary role requires auth.token_file or backup_pop.auth_token_file")
}
if _, err := os.Stat(tokenFile); err != nil {
return nil, fmt.Errorf("auth token file not found: %s", tokenFile)
}
}
// Backup role checks
if cfg.Role == "backup" {
if cfg.BackupPOP.URL != "" {
return nil, fmt.Errorf("backup role should not have backup_pop configured (it receives replication)")
}
}
// Set defaults
if cfg.Replication.BatchSize == 0 {
cfg.Replication.BatchSize = 100
}
if cfg.Replication.MaxRetries == 0 {
cfg.Replication.MaxRetries = 5
}
return &cfg, nil
}