blob: c6433b0400939cae618554b1164d99e788f48e2a [file] [log] [blame]
Philip Zeyligerd4be7a22025-06-15 09:39:00 -07001package dockerimg
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "net/http"
8 "os"
9 "path/filepath"
10 "runtime"
11)
12
13// downloadSubtrace downloads the subtrace binary for the given architecture
14// and caches it in ~/.cache/sketch/subtrace-{platform}-{arch}
15func downloadSubtrace(ctx context.Context, platform, arch string) (string, error) {
16 _ = ctx // ctx is reserved for future timeout/cancellation support
17 homeDir, err := os.UserHomeDir()
18 if err != nil {
19 return "", fmt.Errorf("failed to get home directory: %w", err)
20 }
21
22 cacheDir := filepath.Join(homeDir, ".cache", "sketch")
23 if err := os.MkdirAll(cacheDir, 0o755); err != nil {
24 return "", fmt.Errorf("failed to create cache directory: %w", err)
25 }
26
27 binaryName := fmt.Sprintf("subtrace-%s-%s", platform, arch)
28 binaryPath := filepath.Join(cacheDir, binaryName)
29
30 // Check if the binary already exists
31 if _, err := os.Stat(binaryPath); err == nil {
32 // Binary exists, return the path
33 return binaryPath, nil
34 }
35
36 // Download the binary
37 downloadURL := fmt.Sprintf("https://subtrace.dev/download/latest/%s/%s/subtrace", platform, arch)
38
39 resp, err := http.Get(downloadURL)
40 if err != nil {
41 return "", fmt.Errorf("failed to download subtrace from %s: %w", downloadURL, err)
42 }
43 defer resp.Body.Close()
44
45 if resp.StatusCode != http.StatusOK {
46 return "", fmt.Errorf("failed to download subtrace: HTTP %d", resp.StatusCode)
47 }
48
49 // Create the binary file
50 file, err := os.Create(binaryPath)
51 if err != nil {
52 return "", fmt.Errorf("failed to create subtrace binary file: %w", err)
53 }
54 defer file.Close()
55
56 // Copy the downloaded content to the file
57 _, err = io.Copy(file, resp.Body)
58 if err != nil {
59 return "", fmt.Errorf("failed to write subtrace binary: %w", err)
60 }
61
62 // Make the binary executable
63 if err := os.Chmod(binaryPath, 0o755); err != nil {
64 return "", fmt.Errorf("failed to make subtrace binary executable: %w", err)
65 }
66
67 return binaryPath, nil
68}
69
70// setupSubtraceBeforeStart downloads subtrace and uploads it to the container before it starts
71func setupSubtraceBeforeStart(ctx context.Context, cntrName, subtraceToken string) error {
72 if subtraceToken == "" {
73 return nil
74 }
75
76 // Download subtrace binary
77 subtracePath, err := downloadSubtrace(ctx, "linux", runtime.GOARCH)
78 if err != nil {
79 return fmt.Errorf("failed to download subtrace: %w", err)
80 }
81
82 // Copy subtrace binary to the container (container exists but isn't started)
83 if out, err := combinedOutput(ctx, "docker", "cp", subtracePath, cntrName+":/usr/local/bin/subtrace"); err != nil {
84 return fmt.Errorf("failed to copy subtrace to container: %s: %w", out, err)
85 }
86
87 return nil
88}