Preserve resource field presence in lists
This commit is contained in:
@@ -247,8 +247,8 @@ func load(main configkit.Input, underlays []configkit.Underlay) (*loaded, error)
|
||||
Sensitive: secretProviderPath,
|
||||
Resolve: func(config *document, resolution *configkit.Resolution) error {
|
||||
for _, resources := range resourceSets(config) {
|
||||
captureFields(resources.backends, resources.bases.backends, resources.namespace, backendFields, resolution, state.backends)
|
||||
captureFields(resources.profiles, resources.bases.profiles, resources.namespace, profileFields, resolution, state.profiles)
|
||||
captureFields(resources.backends, func(v backendConfig) string { return v.ID }, resources.bases.backends, resources.namespace, backendFields, resolution, state.backends)
|
||||
captureFields(resources.profiles, func(v profileConfig) string { return v.ID }, resources.bases.profiles, resources.namespace, profileFields, resolution, state.profiles)
|
||||
capturePromptMetadata(resources.prompts, resources.bases.prompts, resources.namespace, resolution, state.promptMetadata)
|
||||
resolveBackends(resources.backends, resources.bases.backends, resolution)
|
||||
resolveProfiles(resources.profiles, resources.bases.profiles, resolution)
|
||||
@@ -351,11 +351,11 @@ func captureFieldState(path configkit.Path, resolution *configkit.Resolution) fi
|
||||
}
|
||||
}
|
||||
|
||||
func captureFields[T any](entries map[string]T, basePath configkit.Path, namespace string, fields []string, resolution *configkit.Resolution, destination map[string]map[string]fieldState) {
|
||||
for id := range entries {
|
||||
func captureFields[T any](entries []T, identity func(T) string, basePath configkit.Path, namespace string, fields []string, resolution *configkit.Resolution, destination map[string]map[string]fieldState) {
|
||||
for index, entry := range entries {
|
||||
states := make(map[string]fieldState, len(fields))
|
||||
for _, field := range fields {
|
||||
info, exists := resolution.EntryInfo(basePath.Key(id).Key(field))
|
||||
info, exists := resolution.EntryInfo(basePath.Index(index).Key(field))
|
||||
switch {
|
||||
case !exists || !info.Explicit:
|
||||
states[field] = fieldAbsent
|
||||
@@ -365,7 +365,7 @@ func captureFields[T any](entries map[string]T, basePath configkit.Path, namespa
|
||||
states[field] = fieldValue
|
||||
}
|
||||
}
|
||||
destination[indexedResourceID(namespace, id)] = states
|
||||
destination[indexedResourceID(namespace, identity(entry))] = states
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,10 +386,10 @@ func normalizeString(value **string, path configkit.Path, resolution *configkit.
|
||||
return false
|
||||
}
|
||||
|
||||
func resolveBackends(backends map[string]backendConfig, basePath configkit.Path, resolution *configkit.Resolution) {
|
||||
for _, id := range sortedKeys(backends) {
|
||||
backend := backends[id]
|
||||
base := basePath.Key(id)
|
||||
func resolveBackends(backends []backendConfig, basePath configkit.Path, resolution *configkit.Resolution) {
|
||||
for index := range backends {
|
||||
backend := &backends[index]
|
||||
base := basePath.Index(index)
|
||||
if backend.Endpoint != nil {
|
||||
endpoint, err := domain.NormalizeOpenAICompatibleBaseEndpoint(*backend.Endpoint)
|
||||
if err != nil {
|
||||
@@ -424,7 +424,6 @@ func resolveBackends(backends map[string]backendConfig, basePath configkit.Path,
|
||||
configkit.Default(resolution, base.Key("queue_capacity"), &backend.QueueCapacity, &capacity, "select default queue capacity")
|
||||
}
|
||||
}
|
||||
backends[id] = backend
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,10 +442,10 @@ func normalizeDiagnosticEndpoint(value **string, path configkit.Path, resolution
|
||||
normalizeString(value, path, resolution, normalized)
|
||||
}
|
||||
|
||||
func resolveProfiles(profiles map[string]profileConfig, basePath configkit.Path, resolution *configkit.Resolution) {
|
||||
for _, id := range sortedKeys(profiles) {
|
||||
profile := profiles[id]
|
||||
base := basePath.Key(id)
|
||||
func resolveProfiles(profiles []profileConfig, basePath configkit.Path, resolution *configkit.Resolution) {
|
||||
for index := range profiles {
|
||||
profile := &profiles[index]
|
||||
base := basePath.Index(index)
|
||||
if profile.Endpoint != nil && *profile.Endpoint != "" {
|
||||
endpoint, err := domain.NormalizeOpenAICompatibleBaseEndpoint(*profile.Endpoint)
|
||||
if err != nil {
|
||||
@@ -467,7 +466,6 @@ func resolveProfiles(profiles map[string]profileConfig, basePath configkit.Path,
|
||||
normalizeString(field.value, base.Key(field.name), resolution, strings.TrimSpace(**field.value))
|
||||
}
|
||||
}
|
||||
profiles[id] = profile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,14 +230,14 @@ func TestLoadRejectsInvalidCollectionAndResourceKeys(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadRecordsBackendNormalizationAndNullDefault(t *testing.T) {
|
||||
loaded, err := load(mapping("backend", map[string]any{"backends": map[string]any{
|
||||
"local": map[string]any{"endpoint": " HTTP://localhost:8080/v1 ", "api_key_env": " TOKEN_NAME ",
|
||||
loaded, err := load(mapping("backend", map[string]any{"backends": []any{
|
||||
map[string]any{"id": "local", "endpoint": " HTTP://localhost:8080/v1 ", "api_key_env": " TOKEN_NAME ",
|
||||
"concurrency_limit": 2, "queue_capacity": nil},
|
||||
}}), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := loaded.result.Config.Backends["local"]
|
||||
backend := loaded.result.Config.Backends[0]
|
||||
if backend.Endpoint == nil || *backend.Endpoint != "http://localhost:8080/v1" ||
|
||||
backend.APIKeyEnv == nil || *backend.APIKeyEnv != "TOKEN_NAME" ||
|
||||
backend.QueueCapacity == nil || *backend.QueueCapacity != 1024 {
|
||||
@@ -246,6 +246,10 @@ func TestLoadRecordsBackendNormalizationAndNullDefault(t *testing.T) {
|
||||
if loaded.backends["local"]["queue_capacity"] != fieldNull {
|
||||
t.Fatalf("explicit null was not retained: %+v", loaded.backends["local"])
|
||||
}
|
||||
field, found := loaded.result.Metadata().Lookup(configkit.Keys("backends").Index(0).Key("endpoint"))
|
||||
if !found || field.Origin.Operation != configkit.ChangeNormalization {
|
||||
t.Fatalf("endpoint normalization was not recorded at the list entry: %+v", field)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBackendSmokeTestsOmissionAndNull(t *testing.T) {
|
||||
@@ -402,15 +406,35 @@ func TestLoadRejectsInvalidFinalBackendSmokeTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadDefaultsAbsentQueueCapacity(t *testing.T) {
|
||||
loaded, err := load(mapping("backend", map[string]any{"backends": map[string]any{
|
||||
"local": map[string]any{"endpoint": "http://localhost:8080/v1", "concurrency_limit": 1},
|
||||
underlay := mapping("defaults", map[string]any{"backends": []any{
|
||||
map[string]any{"id": "local", "endpoint": "http://localhost:8080/v1", "api_key_env": "OLD_KEY"},
|
||||
}})
|
||||
loaded, err := load(mapping("backend", map[string]any{"backends": []any{
|
||||
map[string]any{"id": "local", "endpoint": "http://localhost:8080/v1", "concurrency_limit": 1},
|
||||
}}), []configkit.Underlay{{Inputs: []configkit.Input{underlay}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := loaded.result.Config.Backends[0]
|
||||
if backend.APIKeyEnv != nil || backend.QueueCapacity == nil || *backend.QueueCapacity != 1024 || loaded.backends["local"]["queue_capacity"] != fieldAbsent {
|
||||
t.Fatalf("absent queue capacity did not receive its default: %+v", backend)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadCapturesProfilePresence(t *testing.T) {
|
||||
loaded, err := load(mapping("profile", map[string]any{"profiles": []any{
|
||||
map[string]any{"id": "local", "temperature": 0, "top_p": nil, "api_key_required": false},
|
||||
}}), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := loaded.result.Config.Backends["local"]
|
||||
if backend.QueueCapacity == nil || *backend.QueueCapacity != 1024 || loaded.backends["local"]["queue_capacity"] != fieldAbsent {
|
||||
t.Fatalf("absent queue capacity did not receive its default: %+v", backend)
|
||||
profile := loaded.result.Config.Profiles[0]
|
||||
if profile.Temperature == nil || *profile.Temperature != 0 || profile.TopP != nil || profile.APIKeyRequired == nil || *profile.APIKeyRequired {
|
||||
t.Fatalf("profile values were not preserved: %+v", profile)
|
||||
}
|
||||
fields := loaded.profiles["local"]
|
||||
if fields["temperature"] != fieldValue || fields["top_p"] != fieldNull || fields["api_key_required"] != fieldValue || fields["model"] != fieldAbsent {
|
||||
t.Fatalf("profile presence was not preserved: %+v", fields)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user