1
2
3
4
5
6
7
8
9
10 package configstore
11
12 import (
13 "bytes"
14 "encoding/json"
15 "fmt"
16 "os"
17 "os/exec"
18 "path/filepath"
19 "sync/atomic"
20
21 "golang.org/x/telemetry/internal/telemetry"
22 )
23
24 const (
25 ModulePath = "golang.org/x/telemetry/config"
26 configFileName = "config.json"
27 )
28
29
30
31 var needNoConsole = func(cmd *exec.Cmd) {}
32
33 var downloads int64
34
35
36
37 func Downloads() int64 {
38 return atomic.LoadInt64(&downloads)
39 }
40
41
42
43
44
45
46 func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) {
47 atomic.AddInt64(&downloads, 1)
48
49 if version == "" {
50 version = "latest"
51 }
52 modVer := ModulePath + "@" + version
53 var stdout, stderr bytes.Buffer
54 cmd := exec.Command("go", "mod", "download", "-json", modVer)
55 needNoConsole(cmd)
56 cmd.Env = append(os.Environ(), envOverlay...)
57 cmd.Stdout = &stdout
58 cmd.Stderr = &stderr
59 if err := cmd.Run(); err != nil {
60 var info struct {
61 Error string
62 }
63 if err := json.Unmarshal(stdout.Bytes(), &info); err == nil && info.Error != "" {
64 return nil, "", fmt.Errorf("failed to download config module: %v", info.Error)
65 }
66 return nil, "", fmt.Errorf("failed to download config module: %w\n%s", err, &stderr)
67 }
68
69 var info struct {
70 Dir string
71 Version string
72 Error string
73 }
74 if err := json.Unmarshal(stdout.Bytes(), &info); err != nil || info.Dir == "" {
75 return nil, "", fmt.Errorf("failed to download config module (invalid JSON): %w", err)
76 }
77 data, err := os.ReadFile(filepath.Join(info.Dir, configFileName))
78 if err != nil {
79 return nil, "", fmt.Errorf("invalid config module: %w", err)
80 }
81 cfg := new(telemetry.UploadConfig)
82 if err := json.Unmarshal(data, cfg); err != nil {
83 return nil, "", fmt.Errorf("invalid config: %w", err)
84 }
85 return cfg, info.Version, nil
86 }
87
View as plain text