Skip to content

Commit bcbead3

Browse files
committed
proxy/config: create config package and migrate configuration
The configuration is become more complex as llama-swap adds more advanced features. This commit moves config to its own package so it can be developed independently of the proxy package. Additionally, enforcing a public API for a configuration will allow downstream usage to be more decoupled.
1 parent 9e3d491 commit bcbead3

14 files changed

+107
-96
lines changed

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ proxy/ui_dist/placeholder.txt:
2424
touch $@
2525

2626
test: proxy/ui_dist/placeholder.txt
27-
go test -short -v -count=1 ./proxy
27+
go test -short ./config ./proxy
2828

29+
# for CI - full test (takes longer)
2930
test-all: proxy/ui_dist/placeholder.txt
30-
go test -v -count=1 ./proxy
31+
go test -v -count=1 ./config && go test -v -count=1 ./proxy
3132

3233
ui/node_modules:
3334
cd ui && npm install
@@ -81,4 +82,4 @@ release:
8182
git tag "$$new_tag";
8283

8384
# Phony targets
84-
.PHONY: all clean ui mac linux windows simple-responder
85+
.PHONY: all clean ui mac linux windows simple-responder test test-all

proxy/config.go renamed to config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package proxy
1+
package config
22

33
import (
44
"fmt"

proxy/config_posix_test.go renamed to config/config_posix_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//go:build !windows
22

3-
package proxy
3+
package config
44

55
import (
66
"os"

proxy/config_test.go renamed to config/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package proxy
1+
package config
22

33
import (
44
"slices"
File renamed without changes.

llama-swap.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/fsnotify/fsnotify"
1616
"github.com/gin-gonic/gin"
17+
"github.com/mostlygeek/llama-swap/config"
1718
"github.com/mostlygeek/llama-swap/event"
1819
"github.com/mostlygeek/llama-swap/proxy"
1920
)
@@ -38,13 +39,13 @@ func main() {
3839
os.Exit(0)
3940
}
4041

41-
config, err := proxy.LoadConfig(*configPath)
42+
conf, err := config.LoadConfig(*configPath)
4243
if err != nil {
4344
fmt.Printf("Error loading config: %v\n", err)
4445
os.Exit(1)
4546
}
4647

47-
if len(config.Profiles) > 0 {
48+
if len(conf.Profiles) > 0 {
4849
fmt.Println("WARNING: Profile functionality has been removed in favor of Groups. See the README for more information.")
4950
}
5051

@@ -67,15 +68,15 @@ func main() {
6768
// Support for watching config and reloading when it changes
6869
reloadProxyManager := func() {
6970
if currentPM, ok := srv.Handler.(*proxy.ProxyManager); ok {
70-
config, err = proxy.LoadConfig(*configPath)
71+
conf, err = config.LoadConfig(*configPath)
7172
if err != nil {
7273
fmt.Printf("Warning, unable to reload configuration: %v\n", err)
7374
return
7475
}
7576

7677
fmt.Println("Configuration Changed")
7778
currentPM.Shutdown()
78-
srv.Handler = proxy.New(config)
79+
srv.Handler = proxy.New(conf)
7980
fmt.Println("Configuration Reloaded")
8081

8182
// wait a few seconds and tell any UI to reload
@@ -85,12 +86,12 @@ func main() {
8586
})
8687
})
8788
} else {
88-
config, err = proxy.LoadConfig(*configPath)
89+
conf, err = config.LoadConfig(*configPath)
8990
if err != nil {
9091
fmt.Printf("Error, unable to load configuration: %v\n", err)
9192
os.Exit(1)
9293
}
93-
srv.Handler = proxy.New(config)
94+
srv.Handler = proxy.New(conf)
9495
}
9596
}
9697

proxy/helpers_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
"github.com/gin-gonic/gin"
12+
"github.com/mostlygeek/llama-swap/config"
1213
"gopkg.in/yaml.v3"
1314
)
1415

@@ -65,18 +66,18 @@ func getTestPort() int {
6566
return port
6667
}
6768

68-
func getTestSimpleResponderConfig(expectedMessage string) ModelConfig {
69+
func getTestSimpleResponderConfig(expectedMessage string) config.ModelConfig {
6970
return getTestSimpleResponderConfigPort(expectedMessage, getTestPort())
7071
}
7172

72-
func getTestSimpleResponderConfigPort(expectedMessage string, port int) ModelConfig {
73+
func getTestSimpleResponderConfigPort(expectedMessage string, port int) config.ModelConfig {
7374
// Create a YAML string with just the values we want to set
7475
yamlStr := fmt.Sprintf(`
7576
cmd: '%s --port %d --silent --respond %s'
7677
proxy: "http://127.0.0.1:%d"
7778
`, simpleResponderPath, port, expectedMessage, port)
7879

79-
var cfg ModelConfig
80+
var cfg config.ModelConfig
8081
if err := yaml.Unmarshal([]byte(yamlStr), &cfg); err != nil {
8182
panic(fmt.Sprintf("failed to unmarshal test config: %v in [%s]", err, yamlStr))
8283
}

proxy/metrics_monitor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"sync"
66
"time"
77

8+
"github.com/mostlygeek/llama-swap/config"
89
"github.com/mostlygeek/llama-swap/event"
910
)
1011

@@ -38,7 +39,7 @@ type MetricsMonitor struct {
3839
nextID int
3940
}
4041

41-
func NewMetricsMonitor(config *Config) *MetricsMonitor {
42+
func NewMetricsMonitor(config *config.Config) *MetricsMonitor {
4243
maxMetrics := config.MetricsMaxInMemory
4344
if maxMetrics <= 0 {
4445
maxMetrics = 1000 // Default fallback

proxy/process.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"syscall"
1616
"time"
1717

18+
"github.com/mostlygeek/llama-swap/config"
1819
"github.com/mostlygeek/llama-swap/event"
1920
)
2021

@@ -39,7 +40,7 @@ const (
3940

4041
type Process struct {
4142
ID string
42-
config ModelConfig
43+
config config.ModelConfig
4344
cmd *exec.Cmd
4445

4546
// PR #155 called to cancel the upstream process
@@ -74,7 +75,7 @@ type Process struct {
7475
failedStartCount int
7576
}
7677

77-
func NewProcess(ID string, healthCheckTimeout int, config ModelConfig, processLogger *LogMonitor, proxyLogger *LogMonitor) *Process {
78+
func NewProcess(ID string, healthCheckTimeout int, config config.ModelConfig, processLogger *LogMonitor, proxyLogger *LogMonitor) *Process {
7879
concurrentLimit := 10
7980
if config.ConcurrencyLimit > 0 {
8081
concurrentLimit = config.ConcurrencyLimit
@@ -539,7 +540,7 @@ func (p *Process) cmdStopUpstreamProcess() error {
539540

540541
if p.config.CmdStop != "" {
541542
// replace ${PID} with the pid of the process
542-
stopArgs, err := SanitizeCommand(strings.ReplaceAll(p.config.CmdStop, "${PID}", fmt.Sprintf("%d", p.cmd.Process.Pid)))
543+
stopArgs, err := config.SanitizeCommand(strings.ReplaceAll(p.config.CmdStop, "${PID}", fmt.Sprintf("%d", p.cmd.Process.Pid)))
543544
if err != nil {
544545
p.proxyLogger.Errorf("<%s> Failed to sanitize stop command: %v", p.ID, err)
545546
return err

proxy/process_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"testing"
1111
"time"
1212

13+
"github.com/mostlygeek/llama-swap/config"
1314
"github.com/stretchr/testify/assert"
1415
)
1516

@@ -90,7 +91,7 @@ func TestProcess_WaitOnMultipleStarts(t *testing.T) {
9091
// test that the automatic start returns the expected error type
9192
func TestProcess_BrokenModelConfig(t *testing.T) {
9293
// Create a process configuration
93-
config := ModelConfig{
94+
config := config.ModelConfig{
9495
Cmd: "nonexistent-command",
9596
Proxy: "http://127.0.0.1:9913",
9697
CheckEndpoint: "/health",
@@ -325,7 +326,7 @@ func TestProcess_ExitInterruptsHealthCheck(t *testing.T) {
325326

326327
// should run and exit but interrupt the long checkHealthTimeout
327328
checkHealthTimeout := 5
328-
config := ModelConfig{
329+
config := config.ModelConfig{
329330
Cmd: "sleep 1",
330331
Proxy: "http://127.0.0.1:9913",
331332
CheckEndpoint: "/health",
@@ -402,15 +403,15 @@ func TestProcess_ForceStopWithKill(t *testing.T) {
402403
binaryPath := getSimpleResponderPath()
403404
port := getTestPort()
404405

405-
config := ModelConfig{
406+
conf := config.ModelConfig{
406407
// note --ignore-sig-term which ignores the SIGTERM signal so a SIGKILL must be sent
407408
// to force the process to exit
408409
Cmd: fmt.Sprintf("%s --port %d --respond %s --silent --ignore-sig-term", binaryPath, port, expectedMessage),
409410
Proxy: fmt.Sprintf("http://127.0.0.1:%d", port),
410411
CheckEndpoint: "/health",
411412
}
412413

413-
process := NewProcess("stop_immediate", 2, config, debugLogger, debugLogger)
414+
process := NewProcess("stop_immediate", 2, conf, debugLogger, debugLogger)
414415
defer process.Stop()
415416

416417
// reduce to make testing go faster
@@ -450,15 +451,15 @@ func TestProcess_ForceStopWithKill(t *testing.T) {
450451
}
451452

452453
func TestProcess_StopCmd(t *testing.T) {
453-
config := getTestSimpleResponderConfig("test_stop_cmd")
454+
conf := getTestSimpleResponderConfig("test_stop_cmd")
454455

455456
if runtime.GOOS == "windows" {
456-
config.CmdStop = "taskkill /f /t /pid ${PID}"
457+
conf.CmdStop = "taskkill /f /t /pid ${PID}"
457458
} else {
458-
config.CmdStop = "kill -TERM ${PID}"
459+
conf.CmdStop = "kill -TERM ${PID}"
459460
}
460461

461-
process := NewProcess("testStopCmd", 2, config, debugLogger, debugLogger)
462+
process := NewProcess("testStopCmd", 2, conf, debugLogger, debugLogger)
462463
defer process.Stop()
463464

464465
err := process.start()
@@ -470,15 +471,15 @@ func TestProcess_StopCmd(t *testing.T) {
470471

471472
func TestProcess_EnvironmentSetCorrectly(t *testing.T) {
472473
expectedMessage := "test_env_not_emptied"
473-
config := getTestSimpleResponderConfig(expectedMessage)
474+
conf := getTestSimpleResponderConfig(expectedMessage)
474475

475476
// ensure that the the default config does not blank out the inherited environment
476-
configWEnv := config
477+
configWEnv := conf
477478

478479
// ensure the additiona variables are appended to the process' environment
479480
configWEnv.Env = append(configWEnv.Env, "TEST_ENV1=1", "TEST_ENV2=2")
480481

481-
process1 := NewProcess("env_test", 2, config, debugLogger, debugLogger)
482+
process1 := NewProcess("env_test", 2, conf, debugLogger, debugLogger)
482483
process2 := NewProcess("env_test", 2, configWEnv, debugLogger, debugLogger)
483484

484485
process1.start()

0 commit comments

Comments
 (0)