github.com/panekj/cli@v0.0.0-20230304125325-467dd2f3797e/cli/command/formatter/volume.go (about)

     1  package formatter
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/api/types/volume"
     9  	units "github.com/docker/go-units"
    10  )
    11  
    12  const (
    13  	defaultVolumeQuietFormat = "{{.Name}}"
    14  	defaultVolumeTableFormat = "table {{.Driver}}\t{{.Name}}"
    15  
    16  	idHeader           = "ID"
    17  	volumeNameHeader   = "VOLUME NAME"
    18  	mountpointHeader   = "MOUNTPOINT"
    19  	linksHeader        = "LINKS"
    20  	groupHeader        = "GROUP"
    21  	availabilityHeader = "AVAILABILITY"
    22  	statusHeader       = "STATUS"
    23  )
    24  
    25  // NewVolumeFormat returns a format for use with a volume Context
    26  func NewVolumeFormat(source string, quiet bool) Format {
    27  	switch source {
    28  	case TableFormatKey:
    29  		if quiet {
    30  			return defaultVolumeQuietFormat
    31  		}
    32  		return defaultVolumeTableFormat
    33  	case RawFormatKey:
    34  		if quiet {
    35  			return `name: {{.Name}}`
    36  		}
    37  		return `name: {{.Name}}\ndriver: {{.Driver}}\n`
    38  	}
    39  	return Format(source)
    40  }
    41  
    42  // VolumeWrite writes formatted volumes using the Context
    43  func VolumeWrite(ctx Context, volumes []*volume.Volume) error {
    44  	render := func(format func(subContext SubContext) error) error {
    45  		for _, vol := range volumes {
    46  			if err := format(&volumeContext{v: *vol}); err != nil {
    47  				return err
    48  			}
    49  		}
    50  		return nil
    51  	}
    52  	return ctx.Write(newVolumeContext(), render)
    53  }
    54  
    55  type volumeContext struct {
    56  	HeaderContext
    57  	v volume.Volume
    58  }
    59  
    60  func newVolumeContext() *volumeContext {
    61  	volumeCtx := volumeContext{}
    62  	volumeCtx.Header = SubHeaderContext{
    63  		"ID":           idHeader,
    64  		"Name":         volumeNameHeader,
    65  		"Group":        groupHeader,
    66  		"Driver":       DriverHeader,
    67  		"Scope":        ScopeHeader,
    68  		"Availability": availabilityHeader,
    69  		"Mountpoint":   mountpointHeader,
    70  		"Labels":       LabelsHeader,
    71  		"Links":        linksHeader,
    72  		"Size":         SizeHeader,
    73  		"Status":       statusHeader,
    74  	}
    75  	return &volumeCtx
    76  }
    77  
    78  func (c *volumeContext) MarshalJSON() ([]byte, error) {
    79  	return MarshalJSON(c)
    80  }
    81  
    82  func (c *volumeContext) Name() string {
    83  	return c.v.Name
    84  }
    85  
    86  func (c *volumeContext) Driver() string {
    87  	return c.v.Driver
    88  }
    89  
    90  func (c *volumeContext) Scope() string {
    91  	return c.v.Scope
    92  }
    93  
    94  func (c *volumeContext) Mountpoint() string {
    95  	return c.v.Mountpoint
    96  }
    97  
    98  func (c *volumeContext) Labels() string {
    99  	if c.v.Labels == nil {
   100  		return ""
   101  	}
   102  
   103  	var joinLabels []string
   104  	for k, v := range c.v.Labels {
   105  		joinLabels = append(joinLabels, k+"="+v)
   106  	}
   107  	return strings.Join(joinLabels, ",")
   108  }
   109  
   110  func (c *volumeContext) Label(name string) string {
   111  	if c.v.Labels == nil {
   112  		return ""
   113  	}
   114  	return c.v.Labels[name]
   115  }
   116  
   117  func (c *volumeContext) Links() string {
   118  	if c.v.UsageData == nil {
   119  		return "N/A"
   120  	}
   121  	return strconv.FormatInt(c.v.UsageData.RefCount, 10)
   122  }
   123  
   124  func (c *volumeContext) Size() string {
   125  	if c.v.UsageData == nil {
   126  		return "N/A"
   127  	}
   128  	return units.HumanSize(float64(c.v.UsageData.Size))
   129  }
   130  
   131  func (c *volumeContext) Group() string {
   132  	if c.v.ClusterVolume == nil {
   133  		return "N/A"
   134  	}
   135  
   136  	return c.v.ClusterVolume.Spec.Group
   137  }
   138  
   139  func (c *volumeContext) Availability() string {
   140  	if c.v.ClusterVolume == nil {
   141  		return "N/A"
   142  	}
   143  
   144  	return string(c.v.ClusterVolume.Spec.Availability)
   145  }
   146  
   147  func (c *volumeContext) Status() string {
   148  	if c.v.ClusterVolume == nil {
   149  		return "N/A"
   150  	}
   151  
   152  	if c.v.ClusterVolume.Info == nil || c.v.ClusterVolume.Info.VolumeID == "" {
   153  		return "pending creation"
   154  	}
   155  
   156  	l := len(c.v.ClusterVolume.PublishStatus)
   157  	switch l {
   158  	case 0:
   159  		return "created"
   160  	case 1:
   161  		return "in use (1 node)"
   162  	default:
   163  		return fmt.Sprintf("in use (%d nodes)", l)
   164  	}
   165  }