github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/cluster/calcium/image.go (about) 1 package calcium 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/projecteru2/core/log" 9 "github.com/projecteru2/core/types" 10 ) 11 12 // CacheImage cache Image 13 // 在podname上cache这个image 14 // 实际上就是在所有的node上去pull一次 15 func (c *Calcium) CacheImage(ctx context.Context, opts *types.ImageOptions) (chan *types.CacheImageMessage, error) { 16 logger := log.WithFunc("calcium.CacheImage").WithField("opts", opts) 17 if err := opts.Validate(); err != nil { 18 logger.Error(ctx, err) 19 return nil, err 20 } 21 22 nodes, err := c.filterNodes(ctx, &types.NodeFilter{Podname: opts.Podname, Includes: opts.Nodenames}) 23 if err != nil { 24 logger.Error(ctx, err) 25 return nil, err 26 } 27 28 if len(nodes) == 0 { 29 logger.Error(ctx, types.ErrPodNoNodes) 30 return nil, types.ErrPodNoNodes 31 } 32 33 ch := make(chan *types.CacheImageMessage) 34 35 _ = c.pool.Invoke(func() { 36 defer close(ch) 37 wg := sync.WaitGroup{} 38 wg.Add(len(nodes)) 39 defer wg.Wait() 40 for _, node := range nodes { 41 node := node 42 _ = c.pool.Invoke(func() { 43 defer wg.Done() 44 for _, image := range opts.Images { 45 m := &types.CacheImageMessage{ 46 Image: image, 47 Success: true, 48 Nodename: node.Name, 49 Message: "", 50 } 51 if err := pullImage(ctx, node, image); err != nil { 52 logger.Error(ctx, err) 53 m.Success = false 54 m.Message = err.Error() 55 } 56 ch <- m 57 } 58 }) 59 } 60 }) 61 62 return ch, nil 63 } 64 65 // RemoveImage remove images 66 func (c *Calcium) RemoveImage(ctx context.Context, opts *types.ImageOptions) (chan *types.RemoveImageMessage, error) { 67 logger := log.WithFunc("calcium.RemoveImage").WithField("opts", opts) 68 if err := opts.Validate(); err != nil { 69 logger.Error(ctx, err) 70 return nil, err 71 } 72 73 nodes, err := c.filterNodes(ctx, &types.NodeFilter{Podname: opts.Podname, Includes: opts.Nodenames}) 74 if err != nil { 75 logger.Error(ctx, err) 76 return nil, err 77 } 78 79 if len(nodes) == 0 { 80 logger.Error(ctx, types.ErrPodNoNodes) 81 return nil, types.ErrPodNoNodes 82 } 83 84 ch := make(chan *types.RemoveImageMessage) 85 86 _ = c.pool.Invoke(func() { 87 defer close(ch) 88 wg := sync.WaitGroup{} 89 wg.Add(len(nodes)) 90 defer wg.Wait() 91 for _, node := range nodes { 92 node := node 93 _ = c.pool.Invoke(func() { 94 defer wg.Done() 95 for _, image := range opts.Images { 96 m := &types.RemoveImageMessage{ 97 Success: false, 98 Image: image, 99 Messages: []string{}, 100 } 101 if removeItems, err := node.Engine.ImageRemove(ctx, image, false, true); err != nil { 102 logger.Error(ctx, err) 103 m.Messages = append(m.Messages, err.Error()) 104 } else { 105 m.Success = true 106 for _, item := range removeItems { 107 m.Messages = append(m.Messages, fmt.Sprintf("Clean: %s", item)) 108 } 109 } 110 ch <- m 111 } 112 if opts.Prune { 113 if err := node.Engine.ImagesPrune(ctx); err != nil { 114 logger.Errorf(ctx, err, "Prune %s pod %s node failed", opts.Podname, node.Name) 115 } else { 116 logger.Infof(ctx, "Prune %s pod %s node", opts.Podname, node.Name) 117 } 118 } 119 }) 120 } 121 }) 122 123 return ch, nil 124 } 125 126 // ListImage list Image on a pod or some nodes. 127 func (c *Calcium) ListImage(ctx context.Context, opts *types.ImageOptions) (chan *types.ListImageMessage, error) { 128 logger := log.WithFunc("calcium.ListImage").WithField("opts", opts) 129 130 nodes, err := c.filterNodes(ctx, &types.NodeFilter{Podname: opts.Podname, Includes: opts.Nodenames}) 131 if err != nil { 132 logger.Error(ctx, err) 133 return nil, err 134 } 135 136 if len(nodes) == 0 { 137 logger.Error(ctx, types.ErrPodNoNodes) 138 return nil, types.ErrPodNoNodes 139 } 140 141 ch := make(chan *types.ListImageMessage) 142 143 _ = c.pool.Invoke(func() { 144 defer close(ch) 145 wg := sync.WaitGroup{} 146 wg.Add(len(nodes)) 147 defer wg.Wait() 148 for _, node := range nodes { 149 node := node 150 _ = c.pool.Invoke(func() { 151 defer wg.Done() 152 msg := &types.ListImageMessage{ 153 Images: []*types.Image{}, 154 Nodename: node.Name, 155 Error: nil, 156 } 157 if images, err := node.Engine.ImageList(ctx, opts.Filter); err != nil { 158 logger.Error(ctx, err) 159 msg.Error = err 160 } else { 161 for _, image := range images { 162 msg.Images = append(msg.Images, &types.Image{ 163 ID: image.ID, 164 Tags: image.Tags, 165 }) 166 } 167 } 168 ch <- msg 169 }) 170 } 171 }) 172 173 return ch, nil 174 }