Refuse config keys that no setting has (closes #419)
check / check (push) Failing after 21m21s

config.Parse walks the file as written and fails on the first key that
matches no setting, naming its dotted path and line, so a typo in
exclude or prune_grace_period no longer falls back silently. ${...}
references and YAML merge keys still load. config set refuses such a key
before writing. The key-to-field lookup moves from internal/cli to
config.SettingType so both use it.

Model: opus-5-5
This commit is contained in:
sneak committed 2026-11-11 00:26:47 +00:00
1 parent aae7fa17ae
commit ba343c30e2
6 files changed
+283 -47

No files matched your search

+86
View File
@@ -0,0 +1,86 @@
package config //nolint:testpackage // checks the unexported errUnknownKey
import (
"errors"
"os"
"path/filepath"
"strings"
"testing"
)
// keysTestConfig loads; each case below adds one line to it.
const keysTestConfig = "storage_url: file:///tmp/vaultik-test-storage\n" +
"s3:\n" +
" region: us-east-1\n" +
"snapshots:\n" +
" test:\n" +
" paths: [/tmp/vaultik-test-source]\n"
// TestParseRefusesUnknownKey checks that a key no setting has, at any
// depth, fails the parse with an error naming the key and its line.
func TestParseRefusesUnknownKey(t *testing.T) {
t.Parallel()
tests := []struct {
name string
yaml string
want string
}{
{"top level", keysTestConfig + "compression_lvl: 9\n",
`unknown config key "compression_lvl" on line 7`},
{"in a snapshot", keysTestConfig + " exlude: [/tmp/cache]\n",
`unknown config key "snapshots.test.exlude" on line 7`},
{"in s3", strings.Replace(keysTestConfig, " region:",
" bukcet: b\n region:", 1),
`unknown config key "s3.bukcet" on line 3`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
_, err := Parse([]byte(tt.yaml))
if !errors.Is(err, errUnknownKey) {
t.Fatalf("Parse() error = %v, want errUnknownKey", err)
}
if err.Error() != tt.want {
t.Errorf("Parse() error = %q, want %q", err.Error(), tt.want)
}
})
}
}
// TestParseAcceptsKnownKeys checks that a config with a ${...} reference
// and a YAML merge key (<<) still parses.
func TestParseAcceptsKnownKeys(t *testing.T) {
t.Parallel()
levelPath := filepath.Join(t.TempDir(), "level")
err := os.WriteFile(levelPath, []byte("9"), 0o600)
if err != nil {
t.Fatalf("write level: %v", err)
}
data := strings.Replace(keysTestConfig, " test:", " test: &test", 1) +
" other:\n" +
" <<: *test\n" +
" exclude: [/tmp/vaultik-test-source/cache]\n" +
"compression_level: ${FILE:" + levelPath + "}\n"
cfg, err := Parse([]byte(data))
if err != nil {
t.Fatalf("Parse() unexpected error: %v", err)
}
if cfg.CompressionLevel != 9 {
t.Errorf("compression_level = %d, want 9", cfg.CompressionLevel)
}
other := cfg.Snapshots["other"]
if len(other.Paths) != 1 || len(other.Exclude) != 1 {
t.Errorf("snapshot other = %+v, want the paths of test and one exclude",
other)
}
}