0df28e9dd8
- Unify duplicate uTLS transports into shared internal/transport package - Extract shared version constant into internal/version - Move LoadDefaultCredentials from config to auth (remove config→auth import) - Deduplicate handler.go: extract telemetry/error helpers (324→268 lines) - Break up main.go::run() into initCredential/initEmbedded - Eliminate logging.Config duplication (use config.LoggingConfig directly) - Extract logWriter to embedded/log.go, SSE fixtures to consts in sniff.go - Use uTLS client for usage polling (consistent TLS fingerprint) - Handle sjson.SetBytes errors in sanitize.go instead of silently swallowing - Document reverse-engineered magic values in billing.go - Unexport Credential.CooldownUntil (internal state) - Replace hardcoded auth bypass paths with map in server.go
134 lines
2.9 KiB
Go
134 lines
2.9 KiB
Go
package embedded
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/fujin/anthropic-proxy/internal/config"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type Perses struct {
|
|
cfg config.EmbeddedConfig
|
|
proxyPort int
|
|
cmd *exec.Cmd
|
|
tmpDir string
|
|
}
|
|
|
|
func NewPerses(cfg config.EmbeddedConfig, proxyPort int) *Perses {
|
|
return &Perses{cfg: cfg, proxyPort: proxyPort}
|
|
}
|
|
|
|
func (p *Perses) Start() error {
|
|
bin, err := ensureBinary("perses", p.cfg.PersesBinary, p.cfg.BinDir)
|
|
if err != nil {
|
|
return fmt.Errorf("perses: %w", err)
|
|
}
|
|
|
|
p.tmpDir, err = os.MkdirTemp("", "perses-*")
|
|
if err != nil {
|
|
return fmt.Errorf("create temp dir: %w", err)
|
|
}
|
|
|
|
if err := p.writeServerConfig(); err != nil {
|
|
return fmt.Errorf("write server config: %w", err)
|
|
}
|
|
if err := p.writeDatasourceProvision(); err != nil {
|
|
return fmt.Errorf("write datasource provision: %w", err)
|
|
}
|
|
if err := p.writeDashboardProvision(); err != nil {
|
|
return fmt.Errorf("write dashboard provision: %w", err)
|
|
}
|
|
|
|
p.cmd = exec.Command(bin,
|
|
"--config", filepath.Join(p.tmpDir, "config.yaml"),
|
|
"-web.listen-address", fmt.Sprintf(":%d", p.cfg.Port),
|
|
)
|
|
p.cmd.Dir = filepath.Dir(bin)
|
|
p.cmd.Stdout = &logWriter{level: "info", component: "perses"}
|
|
p.cmd.Stderr = &logWriter{level: "error", component: "perses"}
|
|
|
|
if err := p.cmd.Start(); err != nil {
|
|
return fmt.Errorf("start perses: %w", err)
|
|
}
|
|
|
|
log.Info().
|
|
Str("binary", bin).
|
|
Int("port", p.cfg.Port).
|
|
Str("config", p.tmpDir).
|
|
Msg("perses started")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Perses) Stop() {
|
|
if p.cmd != nil && p.cmd.Process != nil {
|
|
_ = p.cmd.Process.Kill()
|
|
_ = p.cmd.Wait()
|
|
}
|
|
if p.tmpDir != "" {
|
|
_ = os.RemoveAll(p.tmpDir)
|
|
}
|
|
}
|
|
|
|
func (p *Perses) Running() bool {
|
|
return p.cmd != nil && p.cmd.Process != nil && p.cmd.ProcessState == nil
|
|
}
|
|
|
|
func (p *Perses) writeServerConfig() error {
|
|
provisionDir := filepath.Join(p.tmpDir, "provisions")
|
|
if err := os.MkdirAll(filepath.Join(provisionDir, "datasources"), 0o755); err != nil {
|
|
return err
|
|
}
|
|
if err := os.MkdirAll(filepath.Join(provisionDir, "dashboards"), 0o755); err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg := fmt.Sprintf(`provisioning:
|
|
interval: 1m
|
|
folders:
|
|
- %s
|
|
database:
|
|
file:
|
|
folder: %s/data
|
|
extension: json
|
|
security:
|
|
readonly: false
|
|
enable_auth: false
|
|
`, provisionDir, p.tmpDir)
|
|
|
|
return os.WriteFile(filepath.Join(p.tmpDir, "config.yaml"), []byte(cfg), 0o644)
|
|
}
|
|
|
|
func (p *Perses) writeDatasourceProvision() error {
|
|
ds := fmt.Sprintf(`kind: Datasource
|
|
metadata:
|
|
name: victoria-metrics
|
|
project: anthropic-proxy
|
|
spec:
|
|
default: true
|
|
plugin:
|
|
kind: PrometheusDatasource
|
|
spec:
|
|
directUrl: http://localhost:%d
|
|
`, p.cfg.VMPort)
|
|
|
|
return os.WriteFile(
|
|
filepath.Join(p.tmpDir, "provisions", "datasources", "vm.yaml"),
|
|
[]byte(ds), 0o644,
|
|
)
|
|
}
|
|
|
|
func (p *Perses) writeDashboardProvision() error {
|
|
dashData, err := DashboardJSON()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(
|
|
filepath.Join(p.tmpDir, "provisions", "dashboards", "proxy.json"),
|
|
dashData, 0o644,
|
|
)
|
|
}
|