package embedded import ( "archive/tar" "compress/gzip" "fmt" "io" "net/http" "os" "os/exec" "path/filepath" "runtime" "github.com/rs/zerolog/log" ) const cacheDir = ".cache/anthropic-proxy/bin" var downloads = map[string]struct { urlTemplate string version string extractName string }{ "victoria-metrics": { urlTemplate: "https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v%s/victoria-metrics-%s-v%s.tar.gz", version: "1.118.0", extractName: "victoria-metrics-prod", }, "perses": { urlTemplate: "https://github.com/perses/perses/releases/download/v%s/perses_%s_%s_%s.tar.gz", version: "0.53.1", }, } func ensureBinary(name, configPath, configBinDir string) (string, error) { if configPath != "" { if p, err := exec.LookPath(configPath); err == nil { return p, nil } } if p, err := exec.LookPath(name); err == nil { return p, nil } binDir := configBinDir if binDir == "" { home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("get home dir: %w", err) } binDir = filepath.Join(home, cacheDir) } cachedPath := filepath.Join(binDir, name) if _, err := os.Stat(cachedPath); err == nil { return cachedPath, nil } log.Info().Str("binary", name).Msg("downloading binary (first run)") if err := os.MkdirAll(binDir, 0o755); err != nil { return "", fmt.Errorf("create cache dir: %w", err) } url, err := downloadURL(name) if err != nil { return "", err } if err := extractAll(url, binDir); err != nil { return "", fmt.Errorf("download %s: %w", name, err) } d := downloads[name] if d.extractName != "" { oldPath := filepath.Join(binDir, d.extractName) if _, err := os.Stat(oldPath); err == nil { os.Rename(oldPath, cachedPath) } } if _, err := os.Stat(cachedPath); err != nil { return "", fmt.Errorf("binary %s not found after extraction", name) } log.Info().Str("binary", name).Str("path", cachedPath).Msg("binary downloaded") return cachedPath, nil } func downloadURL(name string) (string, error) { goarch := runtime.GOARCH goos := runtime.GOOS d, ok := downloads[name] if !ok { return "", fmt.Errorf("unknown binary: %s", name) } switch name { case "victoria-metrics": vmOS := fmt.Sprintf("%s-%s", goos, goarch) return fmt.Sprintf(d.urlTemplate, d.version, vmOS, d.version), nil case "perses": return fmt.Sprintf(d.urlTemplate, d.version, d.version, goos, goarch), nil } return "", fmt.Errorf("unknown binary: %s", name) } func extractAll(url, destDir string) error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("download failed: HTTP %d from %s", resp.StatusCode, url) } gz, err := gzip.NewReader(resp.Body) if err != nil { return fmt.Errorf("gzip reader: %w", err) } defer gz.Close() tr := tar.NewReader(gz) for { hdr, err := tr.Next() if err == io.EOF { return nil } if err != nil { return fmt.Errorf("read tar: %w", err) } target := filepath.Join(destDir, hdr.Name) switch hdr.Typeflag { case tar.TypeDir: os.MkdirAll(target, 0o755) case tar.TypeReg: os.MkdirAll(filepath.Dir(target), 0o755) mode := os.FileMode(hdr.Mode) if mode == 0 { mode = 0o644 } out, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) if err != nil { return err } io.Copy(out, tr) out.Close() } } }