Enable explicit configuration imports and overlays
This commit is contained in:
@@ -21,8 +21,10 @@ type LoadOptions struct {
|
||||
// Load resolves one ConfigKit document and retains its inspection snapshot.
|
||||
func Load(options LoadOptions) (*configkit.Result[Document], error) {
|
||||
var source configkit.Source
|
||||
fileBacked := false
|
||||
if options.Explicit {
|
||||
source = configkit.File(options.Path)
|
||||
fileBacked = true
|
||||
} else {
|
||||
selected := ""
|
||||
for _, candidate := range defaultConfigSearchPaths {
|
||||
@@ -41,11 +43,14 @@ func Load(options LoadOptions) (*configkit.Result[Document], error) {
|
||||
source = configkit.NoSource()
|
||||
} else {
|
||||
source = configkit.File(selected)
|
||||
fileBacked = true
|
||||
}
|
||||
}
|
||||
|
||||
result, err := configkit.Load(source, configkit.Options[Document]{
|
||||
Definition: documentDefinition(),
|
||||
Imports: fileBacked,
|
||||
Overlay: options.Overlay,
|
||||
Overrides: options.Overrides,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -174,3 +174,56 @@ func TestLoadDiscoveryErrorQuotesPath(t *testing.T) {
|
||||
t.Fatalf("discovery error did not quote path safely: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadComposesExplicitImportsAndSelectedOverlay(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := os.MkdirAll(filepath.Join(dir, "fragments"), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(dir, "overlays"), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
base := filepath.Join(dir, "config.yml")
|
||||
writeApplicationFile(t, base, "configkit:\n imports:\n - glob: fragments/*.yml\nprompt_dir: ./base-prompts\nserver:\n addr: :8081\n")
|
||||
writeApplicationFile(t, filepath.Join(dir, "fragments", "a.yml"), "backends:\n alpha:\n endpoint: http://alpha.invalid/v1\n")
|
||||
writeApplicationFile(t, filepath.Join(dir, "fragments", "b.yml"), "backends:\n beta:\n endpoint: http://beta.invalid/v1\n")
|
||||
writeApplicationFile(t, filepath.Join(dir, "overlays", "local.yml"), "prompt_dir: ./overlay-prompts\nserver:\n addr: :9090\n")
|
||||
|
||||
result, err := Load(LoadOptions{Path: base, Explicit: true})
|
||||
if err != nil || result.Config.PromptDir != "base-prompts" || len(result.Config.Backends) != 2 || len(result.Sources()) != 3 {
|
||||
t.Fatalf("disjoint imports did not compose: result=%+v err=%v", result, err)
|
||||
}
|
||||
result, err = Load(LoadOptions{Path: base, Explicit: true, Overlay: "local", Overrides: []configkit.Override{{
|
||||
Path: configkit.Keys("server", "addr"), Value: ":7070", Flag: "--addr",
|
||||
}}})
|
||||
if err != nil || result.Config.PromptDir != "overlay-prompts" || result.Config.Server.Addr != ":7070" || len(result.Sources()) != 5 {
|
||||
t.Fatalf("overlay or explicit override changed: result=%+v err=%v", result, err)
|
||||
}
|
||||
if _, err := Load(LoadOptions{Path: base, Explicit: true, Overlay: "missing"}); err == nil {
|
||||
t.Fatal("missing selected overlay accepted")
|
||||
}
|
||||
writeApplicationFile(t, filepath.Join(dir, "fragments", "b.yml"), "backends:\n alpha:\n endpoint: http://conflict.invalid/v1\n")
|
||||
if _, err := Load(LoadOptions{Path: base, Explicit: true}); err == nil {
|
||||
t.Fatal("conflicting import accepted")
|
||||
} else {
|
||||
var loadError *configkit.LoadError
|
||||
if !errors.As(err, &loadError) {
|
||||
t.Fatalf("conflict lost structured diagnostic: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadRejectsOverlayWithoutBase(t *testing.T) {
|
||||
useConfigSearchPaths(t, filepath.Join(t.TempDir(), "absent.yml"))
|
||||
if _, err := Load(LoadOptions{Overlay: "local"}); err == nil {
|
||||
t.Fatal("overlay without base accepted")
|
||||
} else {
|
||||
var loadError *configkit.LoadError
|
||||
if !errors.As(err, &loadError) {
|
||||
t.Fatalf("no-base overlay lost structured diagnostic: %v", err)
|
||||
}
|
||||
}
|
||||
if _, err := Load(LoadOptions{Overlay: "default"}); err != nil {
|
||||
t.Fatalf("default must select no overlay: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user