Files
LocalAI/core/config/proxy_credentials_test.go
T
mudler-agentandEttore Di Giacinto 3a02f29edc fix(proxy): propagate model env and accept direct keys (#12940)
* feat(proxy): accept direct upstream API keys

Support direct credentials for models created in the UI. Keep env and
file references as mutually exclusive alternatives. Use model env for
frontend probes and omit credentials from structured config logs.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* feat(distributed): isolate model environments in worker processes

Forward complete model environment snapshots through backend installation.
Restart worker children when overrides change or are removed, and include
keyed snapshot identities in frontend install coalescing.

Cover wire compatibility, routing, real worker children, and option copying;
document rollout requirements and control-transport security.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(worker): serialize installs by model replica

Different backend names can target the same process slot. Hold a slot
lock through startup, readiness, and operation attachment so concurrent
installs cannot reuse another configuration or an unready child.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* test(nodes): update endpoint stub for model env

Keep the endpoint command stub aligned with the environment-aware install
interface. Assert interface conformance so future changes fail at the
stub declaration rather than at endpoint call sites.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-10-27 10:27:45 +01:00

45 lines
1.6 KiB
Go

// SPDX-License-Identifier: MIT
package config
import (
"bytes"
"encoding/json"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"gopkg.in/yaml.v3"
"log/slog"
)
var _ = Describe("Proxy credentials", func() {
It("preserves and resolves a direct admin credential", func() {
var p ProxyConfig
Expect(json.Unmarshal([]byte(`{"api_key":"fake-direct-key"}`), &p)).To(Succeed())
key, err := p.ResolveAPIKey(nil)
Expect(err).NotTo(HaveOccurred())
Expect(key).To(Equal("fake-direct-key"))
encoded, err := json.Marshal(p)
Expect(err).NotTo(HaveOccurred())
Expect(string(encoded)).To(ContainSubstring(`"api_key":"fake-direct-key"`))
})
It("rejects direct credentials combined with another source", func() {
var c ModelConfig
Expect(json.Unmarshal([]byte(`{"proxy":{"api_key":"fake-key","api_key_env":"OTHER"}}`), &c)).To(Succeed())
_, err := c.Validate()
Expect(err).To(HaveOccurred())
})
})
var _ = Describe("Proxy credential logging", func() {
It("keeps secrets out of structured config logs without changing storage", func() {
var output bytes.Buffer
logger := slog.New(slog.NewJSONHandler(&output, nil))
c := ModelConfig{Proxy: ProxyConfig{APIKey: "fake-direct-secret"}, Environment: map[string]string{"KEY": "fake-env-secret"}}
logger.Info("config", "config", c, "proxy", c.Proxy)
Expect(output.String()).NotTo(ContainSubstring("fake-direct-secret"))
Expect(output.String()).NotTo(ContainSubstring("fake-env-secret"))
data, err := yaml.Marshal(c)
Expect(err).NotTo(HaveOccurred())
Expect(string(data)).To(ContainSubstring("fake-direct-secret"))
})
})