|
7 | 7 | package prefetch
|
8 | 8 |
|
9 | 9 | import (
|
| 10 | + "context" |
10 | 11 | "encoding/json"
|
11 |
| - "sync" |
| 12 | + "fmt" |
| 13 | + "io" |
| 14 | + "net" |
| 15 | + "net/http" |
| 16 | + "os" |
| 17 | + "path/filepath" |
| 18 | + "strings" |
12 | 19 |
|
13 | 20 | "github.com/containerd/containerd/log"
|
| 21 | + "github.com/pkg/errors" |
14 | 22 | )
|
15 | 23 |
|
16 |
| -type prefetchInfo struct { |
17 |
| - prefetchMap map[string]string |
18 |
| - prefetchMutex sync.Mutex |
| 24 | +type prefetchlist struct { |
| 25 | + FilePaths []string `json:"files"` |
19 | 26 | }
|
20 | 27 |
|
21 |
| -var Pm prefetchInfo |
| 28 | +const ( |
| 29 | + endpointPrefetch = "/api/v1/imagename" |
| 30 | + udsSocket = "/tmp/prefetch.sock" |
| 31 | +) |
| 32 | + |
| 33 | +var ErrUds = errors.New("failed to connect unix domain socket") |
22 | 34 |
|
23 |
| -func (p *prefetchInfo) SetPrefetchFiles(body []byte) error { |
24 |
| - p.prefetchMutex.Lock() |
25 |
| - defer p.prefetchMutex.Unlock() |
| 35 | +func GetPrefetchList(prefetchDir, imageRepo string) (string, error) { |
| 36 | + url := fmt.Sprintf("http://unix%s", endpointPrefetch) |
26 | 37 |
|
27 |
| - var prefetchMsg []map[string]string |
28 |
| - if err := json.Unmarshal(body, &prefetchMsg); err != nil { |
29 |
| - return err |
| 38 | + req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(imageRepo)) |
| 39 | + if err != nil { |
| 40 | + return "", err |
30 | 41 | }
|
31 | 42 |
|
32 |
| - if p.prefetchMap == nil { |
33 |
| - p.prefetchMap = make(map[string]string) |
| 43 | + client := &http.Client{ |
| 44 | + Transport: &http.Transport{ |
| 45 | + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { |
| 46 | + return net.Dial("unix", udsSocket) |
| 47 | + }, |
| 48 | + }, |
34 | 49 | }
|
35 |
| - for _, item := range prefetchMsg { |
36 |
| - image := item["image"] |
37 |
| - prefetchfiles := item["prefetch"] |
38 |
| - p.prefetchMap[image] = prefetchfiles |
| 50 | + resp, err := client.Do(req) |
| 51 | + if err != nil { |
| 52 | + log.L.Infof("failed to connect unix domain socket. Skipping prefetch for image: %s\n", imageRepo) |
| 53 | + return "", ErrUds |
39 | 54 | }
|
| 55 | + defer resp.Body.Close() |
40 | 56 |
|
41 |
| - log.L.Infof("received prefetch list from nri plugin: %v ", p.prefetchMap) |
42 |
| - return nil |
43 |
| -} |
| 57 | + if resp.StatusCode != http.StatusOK { |
| 58 | + return "", fmt.Errorf("failed to send data, status code: %v", resp.StatusCode) |
| 59 | + } |
44 | 60 |
|
45 |
| -func (p *prefetchInfo) GetPrefetchInfo(image string) string { |
46 |
| - p.prefetchMutex.Lock() |
47 |
| - defer p.prefetchMutex.Unlock() |
| 61 | + body, err := io.ReadAll(resp.Body) |
| 62 | + if err != nil { |
| 63 | + return "", err |
| 64 | + } |
48 | 65 |
|
49 |
| - if prefetchfiles, ok := p.prefetchMap[image]; ok { |
50 |
| - return prefetchfiles |
| 66 | + if strings.Contains(string(body), "CacheItem not found") { |
| 67 | + log.L.Infof("Cache item not found for image: %s\n", imageRepo) |
| 68 | + return "", nil |
51 | 69 | }
|
52 |
| - return "" |
| 70 | + |
| 71 | + prefetchfilePath, err := storePrefetchList(prefetchDir, body) |
| 72 | + if err != nil { |
| 73 | + return "", err |
| 74 | + } |
| 75 | + return prefetchfilePath, nil |
53 | 76 | }
|
54 | 77 |
|
55 |
| -func (p *prefetchInfo) DeleteFromPrefetchMap(image string) { |
56 |
| - p.prefetchMutex.Lock() |
57 |
| - defer p.prefetchMutex.Unlock() |
| 78 | +func storePrefetchList(prefetchDir string, list []byte) (string, error) { |
| 79 | + if err := os.MkdirAll(prefetchDir, 0755); err != nil { |
| 80 | + return "", errors.Wrapf(err, "create prefetch dir %s", prefetchDir) |
| 81 | + } |
| 82 | + |
| 83 | + filePath := filepath.Join(prefetchDir, "prefetchList") |
| 84 | + jsonfilePath := filepath.Join(prefetchDir, "prefetchList.json") |
| 85 | + |
| 86 | + file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) |
| 87 | + if err != nil { |
| 88 | + fmt.Println("Error opening file:", err) |
| 89 | + return "", errors.Wrap(err, "error opening prefetch file") |
| 90 | + } |
| 91 | + defer file.Close() |
| 92 | + |
| 93 | + var prefetchSlice []string |
| 94 | + err = json.Unmarshal(list, &prefetchSlice) |
| 95 | + if err != nil { |
| 96 | + return "", errors.Wrap(err, "failed to parse prefetch list") |
| 97 | + } |
| 98 | + |
| 99 | + for _, path := range prefetchSlice { |
| 100 | + content := path + "\n" |
| 101 | + _, err := file.WriteString(content) |
| 102 | + if err != nil { |
| 103 | + return "", errors.Wrap(err, "error writing to prefetch file") |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + prefetchStruct := prefetchlist{FilePaths: prefetchSlice} |
| 108 | + jsonByte, err := json.Marshal(prefetchStruct) |
| 109 | + if err != nil { |
| 110 | + return "", errors.Wrap(err, "failed to marshal to JSON") |
| 111 | + } |
| 112 | + |
| 113 | + jsonfile, err := os.Create(jsonfilePath) |
| 114 | + if err != nil { |
| 115 | + return "", errors.Wrapf(err, "failed to create file %s", jsonfilePath) |
| 116 | + } |
| 117 | + defer jsonfile.Close() |
| 118 | + |
| 119 | + _, err = jsonfile.Write(jsonByte) |
| 120 | + if err != nil { |
| 121 | + return "", errors.Wrap(err, "error writing JSON to file") |
| 122 | + } |
58 | 123 |
|
59 |
| - delete(p.prefetchMap, image) |
| 124 | + return filePath, nil |
60 | 125 | }
|
0 commit comments