aboutsummaryrefslogtreecommitdiff
path: root/internal/config
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-28 05:39:38 -0800
committerFuwn <[email protected]>2026-02-28 05:39:38 -0800
commit2525861018ccd4db2f683a8778e5784a9e2942f5 (patch)
tree6232a03b8ff0633adf920bafdcb946b2c1b62928 /internal/config
parentchore(compose): add thin mode override (diff)
downloadplutia-test-2525861018ccd4db2f683a8778e5784a9e2942f5.tar.xz
plutia-test-2525861018ccd4db2f683a8778e5784a9e2942f5.zip
feat(config): allow optional config file with default fallback
Diffstat (limited to 'internal/config')
-rw-r--r--internal/config/config.go12
-rw-r--r--internal/config/config_load_test.go82
2 files changed, 89 insertions, 5 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index 69173fd..47f5842 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -89,11 +89,13 @@ func Load(path string) (Config, error) {
b, err := os.ReadFile(path)
if err != nil {
- return Config{}, fmt.Errorf("read config: %w", err)
- }
-
- if err := yaml.Unmarshal(b, &cfg); err != nil {
- return Config{}, fmt.Errorf("parse config: %w", err)
+ if !errors.Is(err, os.ErrNotExist) {
+ return Config{}, fmt.Errorf("read config: %w", err)
+ }
+ } else {
+ if err := yaml.Unmarshal(b, &cfg); err != nil {
+ return Config{}, fmt.Errorf("parse config: %w", err)
+ }
}
}
diff --git a/internal/config/config_load_test.go b/internal/config/config_load_test.go
new file mode 100644
index 0000000..516dd93
--- /dev/null
+++ b/internal/config/config_load_test.go
@@ -0,0 +1,82 @@
+package config
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+)
+
+func TestLoadMissingConfigFileFallsBackToDefaults(t *testing.T) {
+ cfg, err := Load(filepath.Join(t.TempDir(), "missing.yaml"))
+ if err != nil {
+ t.Fatalf("load missing config: %v", err)
+ }
+
+ def := Default()
+ if cfg.Mode != def.Mode {
+ t.Fatalf("mode mismatch: got %q want %q", cfg.Mode, def.Mode)
+ }
+ if cfg.VerifyPolicy != def.VerifyPolicy {
+ t.Fatalf("verify policy mismatch: got %q want %q", cfg.VerifyPolicy, def.VerifyPolicy)
+ }
+ if cfg.CheckpointInterval != def.CheckpointInterval {
+ t.Fatalf("checkpoint interval mismatch: got %d want %d", cfg.CheckpointInterval, def.CheckpointInterval)
+ }
+ if cfg.VerifyWorkers != def.VerifyWorkers {
+ t.Fatalf("verify workers mismatch: got %d want %d", cfg.VerifyWorkers, def.VerifyWorkers)
+ }
+}
+
+func TestLoadPartialConfigRetainsDefaultValues(t *testing.T) {
+ configPath := filepath.Join(t.TempDir(), "partial.yaml")
+ content := []byte("mode: thin\nverify: full\n")
+
+ if err := os.WriteFile(configPath, content, 0o644); err != nil {
+ t.Fatalf("write partial config: %v", err)
+ }
+
+ cfg, err := Load(configPath)
+ if err != nil {
+ t.Fatalf("load partial config: %v", err)
+ }
+
+ if cfg.Mode != ModeThin {
+ t.Fatalf("mode mismatch: got %q want %q", cfg.Mode, ModeThin)
+ }
+ if cfg.VerifyPolicy != VerifyFull {
+ t.Fatalf("verify policy mismatch: got %q want %q", cfg.VerifyPolicy, VerifyFull)
+ }
+
+ def := Default()
+ if cfg.PLCSource != def.PLCSource {
+ t.Fatalf("plc_source mismatch: got %q want %q", cfg.PLCSource, def.PLCSource)
+ }
+ if cfg.RequestTimeout != 10*time.Second {
+ t.Fatalf("request_timeout mismatch: got %s want 10s", cfg.RequestTimeout)
+ }
+ if cfg.CommitBatchSize != def.CommitBatchSize {
+ t.Fatalf("commit_batch_size mismatch: got %d want %d", cfg.CommitBatchSize, def.CommitBatchSize)
+ }
+}
+
+func TestLoadMissingConfigFileAppliesEnvOverrides(t *testing.T) {
+ t.Setenv("PLUTIA_MODE", ModeThin)
+ t.Setenv("PLUTIA_VERIFY", VerifyFull)
+ t.Setenv("PLUTIA_REQUEST_TIMEOUT", "15s")
+
+ cfg, err := Load(filepath.Join(t.TempDir(), "missing.yaml"))
+ if err != nil {
+ t.Fatalf("load missing config with env overrides: %v", err)
+ }
+
+ if cfg.Mode != ModeThin {
+ t.Fatalf("mode mismatch: got %q want %q", cfg.Mode, ModeThin)
+ }
+ if cfg.VerifyPolicy != VerifyFull {
+ t.Fatalf("verify policy mismatch: got %q want %q", cfg.VerifyPolicy, VerifyFull)
+ }
+ if cfg.RequestTimeout != 15*time.Second {
+ t.Fatalf("request_timeout mismatch: got %s want 15s", cfg.RequestTimeout)
+ }
+}