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  }