diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..edc4b2a --- /dev/null +++ b/config/config.go @@ -0,0 +1,94 @@ +package config + +import ( + "fmt" + "os" + "path/filepath" + + "kvs/types" + "gopkg.in/yaml.v3" +) + +// Default configuration +func Default() *types.Config { + hostname, _ := os.Hostname() + return &types.Config{ + NodeID: hostname, + BindAddress: "127.0.0.1", + Port: 8080, + DataDir: "./data", + SeedNodes: []string{}, + ReadOnly: false, + LogLevel: "info", + GossipIntervalMin: 60, // 1 minute + GossipIntervalMax: 120, // 2 minutes + SyncInterval: 300, // 5 minutes + CatchupInterval: 120, // 2 minutes + BootstrapMaxAgeHours: 720, // 30 days + ThrottleDelayMs: 100, + FetchDelayMs: 50, + + // Phase 2: Default compression settings + CompressionEnabled: true, + CompressionLevel: 3, // Balance between performance and compression ratio + + // Phase 2: Default TTL and size limit settings + DefaultTTL: "0", // No default TTL + MaxJSONSize: 1048576, // 1MB default max JSON size + + // Phase 2: Default rate limiting settings + RateLimitRequests: 100, // 100 requests per window + RateLimitWindow: "1m", // 1 minute window + + // Phase 2: Default tamper-evident logging settings + TamperLogActions: []string{"data_write", "user_create", "auth_failure"}, + + // Phase 2: Default backup system settings + BackupEnabled: true, + BackupSchedule: "0 0 * * *", // Daily at midnight + BackupPath: "./backups", + BackupRetention: 7, // Keep backups for 7 days + + // Default feature toggle settings (all enabled by default) + AuthEnabled: true, + TamperLoggingEnabled: true, + ClusteringEnabled: true, + RateLimitingEnabled: true, + RevisionHistoryEnabled: true, + } +} + +// Load configuration from file or create default +func Load(configPath string) (*types.Config, error) { + config := Default() + + if _, err := os.Stat(configPath); os.IsNotExist(err) { + // Create default config file + if err := os.MkdirAll(filepath.Dir(configPath), 0755); err != nil { + return nil, fmt.Errorf("failed to create config directory: %v", err) + } + + data, err := yaml.Marshal(config) + if err != nil { + return nil, fmt.Errorf("failed to marshal default config: %v", err) + } + + if err := os.WriteFile(configPath, data, 0644); err != nil { + return nil, fmt.Errorf("failed to write default config: %v", err) + } + + fmt.Printf("Created default configuration at %s\n", configPath) + return config, nil + } + + data, err := os.ReadFile(configPath) + if err != nil { + return nil, fmt.Errorf("failed to read config file: %v", err) + } + + if err := yaml.Unmarshal(data, config); err != nil { + return nil, fmt.Errorf("failed to parse config file: %v", err) + } + + return config, nil +} \ No newline at end of file diff --git a/main.go b/main.go index 3655873..41a0dd5 100644 --- a/main.go +++ b/main.go @@ -27,8 +27,8 @@ import ( "github.com/klauspost/compress/zstd" "github.com/robfig/cron/v3" "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" + "kvs/config" "kvs/types" "kvs/utils" ) @@ -1179,89 +1179,6 @@ func (s *Server) getBackupStatus() types.BackupStatus { return status } -// Default configuration -func defaultConfig() *types.Config { - hostname, _ := os.Hostname() - return &types.Config{ - NodeID: hostname, - BindAddress: "127.0.0.1", - Port: 8080, - DataDir: "./data", - SeedNodes: []string{}, - ReadOnly: false, - LogLevel: "info", - GossipIntervalMin: 60, // 1 minute - GossipIntervalMax: 120, // 2 minutes - SyncInterval: 300, // 5 minutes - CatchupInterval: 120, // 2 minutes - BootstrapMaxAgeHours: 720, // 30 days - ThrottleDelayMs: 100, - FetchDelayMs: 50, - - // Phase 2: Default compression settings - CompressionEnabled: true, - CompressionLevel: 3, // Balance between performance and compression ratio - - // Phase 2: Default TTL and size limit settings - DefaultTTL: "0", // No default TTL - MaxJSONSize: 1048576, // 1MB default max JSON size - - // Phase 2: Default rate limiting settings - RateLimitRequests: 100, // 100 requests per window - RateLimitWindow: "1m", // 1 minute window - - // Phase 2: Default tamper-evident logging settings - TamperLogActions: []string{"data_write", "user_create", "auth_failure"}, - - // Phase 2: Default backup system settings - BackupEnabled: true, - BackupSchedule: "0 0 * * *", // Daily at midnight - BackupPath: "./backups", - BackupRetention: 7, // Keep backups for 7 days - - // Default feature toggle settings (all enabled by default) - AuthEnabled: true, - TamperLoggingEnabled: true, - ClusteringEnabled: true, - RateLimitingEnabled: true, - RevisionHistoryEnabled: true, - } -} - -// Load configuration from file or create default -func loadConfig(configPath string) (*types.Config, error) { - config := defaultConfig() - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - // Create default config file - if err := os.MkdirAll(filepath.Dir(configPath), 0755); err != nil { - return nil, fmt.Errorf("failed to create config directory: %v", err) - } - - data, err := yaml.Marshal(config) - if err != nil { - return nil, fmt.Errorf("failed to marshal default config: %v", err) - } - - if err := os.WriteFile(configPath, data, 0644); err != nil { - return nil, fmt.Errorf("failed to write default config: %v", err) - } - - fmt.Printf("Created default configuration at %s\n", configPath) - return config, nil - } - - data, err := os.ReadFile(configPath) - if err != nil { - return nil, fmt.Errorf("failed to read config file: %v", err) - } - - if err := yaml.Unmarshal(data, config); err != nil { - return nil, fmt.Errorf("failed to parse config file: %v", err) - } - - return config, nil -} // Initialize server func NewServer(config *types.Config) (*Server, error) { @@ -3675,13 +3592,13 @@ func main() { configPath = os.Args[1] } - config, err := loadConfig(configPath) + cfg, err := config.Load(configPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to load configuration: %v\n", err) os.Exit(1) } - server, err := NewServer(config) + server, err := NewServer(cfg) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create server: %v\n", err) os.Exit(1)