github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/volume/service/convert.go (about)

     1  package service
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/api/types/filters"
     9  	"github.com/docker/docker/pkg/directory"
    10  	"github.com/docker/docker/volume"
    11  	"github.com/sirupsen/logrus"
    12  )
    13  
    14  // convertOpts are used to pass options to `volumeToAPI`
    15  type convertOpt interface {
    16  	isConvertOpt()
    17  }
    18  
    19  type useCachedPath bool
    20  
    21  func (useCachedPath) isConvertOpt() {}
    22  
    23  type calcSize bool
    24  
    25  func (calcSize) isConvertOpt() {}
    26  
    27  type pathCacher interface {
    28  	CachedPath() string
    29  }
    30  
    31  func (s *VolumesService) volumesToAPI(ctx context.Context, volumes []volume.Volume, opts ...convertOpt) []*types.Volume {
    32  	var (
    33  		out        = make([]*types.Volume, 0, len(volumes))
    34  		getSize    bool
    35  		cachedPath bool
    36  	)
    37  
    38  	for _, o := range opts {
    39  		switch t := o.(type) {
    40  		case calcSize:
    41  			getSize = bool(t)
    42  		case useCachedPath:
    43  			cachedPath = bool(t)
    44  		}
    45  	}
    46  	for _, v := range volumes {
    47  		select {
    48  		case <-ctx.Done():
    49  			return nil
    50  		default:
    51  		}
    52  		apiV := volumeToAPIType(v)
    53  
    54  		if cachedPath {
    55  			if vv, ok := v.(pathCacher); ok {
    56  				apiV.Mountpoint = vv.CachedPath()
    57  			}
    58  		} else {
    59  			apiV.Mountpoint = v.Path()
    60  		}
    61  
    62  		if getSize {
    63  			p := v.Path()
    64  			if apiV.Mountpoint == "" {
    65  				apiV.Mountpoint = p
    66  			}
    67  			sz, err := directory.Size(ctx, p)
    68  			if err != nil {
    69  				logrus.WithError(err).WithField("volume", v.Name()).Warnf("Failed to determine size of volume")
    70  				sz = -1
    71  			}
    72  			apiV.UsageData = &types.VolumeUsageData{Size: sz, RefCount: int64(s.vs.CountReferences(v))}
    73  		}
    74  
    75  		out = append(out, &apiV)
    76  	}
    77  	return out
    78  }
    79  
    80  func volumeToAPIType(v volume.Volume) types.Volume {
    81  	createdAt, _ := v.CreatedAt()
    82  	tv := types.Volume{
    83  		Name:      v.Name(),
    84  		Driver:    v.DriverName(),
    85  		CreatedAt: createdAt.Format(time.RFC3339),
    86  	}
    87  	if v, ok := v.(volume.DetailedVolume); ok {
    88  		tv.Labels = v.Labels()
    89  		tv.Options = v.Options()
    90  		tv.Scope = v.Scope()
    91  	}
    92  	if cp, ok := v.(pathCacher); ok {
    93  		tv.Mountpoint = cp.CachedPath()
    94  	}
    95  	return tv
    96  }
    97  
    98  func filtersToBy(filter filters.Args, acceptedFilters map[string]bool) (By, error) {
    99  	if err := filter.Validate(acceptedFilters); err != nil {
   100  		return nil, err
   101  	}
   102  	var bys []By
   103  	if drivers := filter.Get("driver"); len(drivers) > 0 {
   104  		bys = append(bys, ByDriver(drivers...))
   105  	}
   106  	if filter.Contains("name") {
   107  		bys = append(bys, CustomFilter(func(v volume.Volume) bool {
   108  			return filter.Match("name", v.Name())
   109  		}))
   110  	}
   111  	bys = append(bys, byLabelFilter(filter))
   112  
   113  	if filter.Contains("dangling") {
   114  		var dangling bool
   115  		if filter.ExactMatch("dangling", "true") || filter.ExactMatch("dangling", "1") {
   116  			dangling = true
   117  		} else if !filter.ExactMatch("dangling", "false") && !filter.ExactMatch("dangling", "0") {
   118  			return nil, invalidFilter{"dangling", filter.Get("dangling")}
   119  		}
   120  		bys = append(bys, ByReferenced(!dangling))
   121  	}
   122  
   123  	var by By
   124  	switch len(bys) {
   125  	case 0:
   126  	case 1:
   127  		by = bys[0]
   128  	default:
   129  		by = And(bys...)
   130  	}
   131  	return by, nil
   132  }