github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/storage/filesystemlistformatters.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storage
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"sort"
    10  	"strings"
    11  	"text/tabwriter"
    12  
    13  	"github.com/dustin/go-humanize"
    14  	"github.com/juju/errors"
    15  )
    16  
    17  // formatFilesystemListTabular returns a tabular summary of filesystem instances.
    18  func formatFilesystemListTabular(value interface{}) ([]byte, error) {
    19  	infos, ok := value.(map[string]FilesystemInfo)
    20  	if !ok {
    21  		return nil, errors.Errorf("expected value of type %T, got %T", infos, value)
    22  	}
    23  	return formatFilesystemListTabularTyped(infos), nil
    24  }
    25  
    26  func formatFilesystemListTabularTyped(infos map[string]FilesystemInfo) []byte {
    27  	var out bytes.Buffer
    28  	const (
    29  		// To format things into columns.
    30  		minwidth = 0
    31  		tabwidth = 1
    32  		padding  = 2
    33  		padchar  = ' '
    34  		flags    = 0
    35  	)
    36  	tw := tabwriter.NewWriter(&out, minwidth, tabwidth, padding, padchar, flags)
    37  
    38  	print := func(values ...string) {
    39  		fmt.Fprintln(tw, strings.Join(values, "\t"))
    40  	}
    41  	print("MACHINE", "UNIT", "STORAGE", "ID", "VOLUME", "PROVIDER-ID", "MOUNTPOINT", "SIZE", "STATE", "MESSAGE")
    42  
    43  	filesystemAttachmentInfos := make(filesystemAttachmentInfos, 0, len(infos))
    44  	for filesystemId, info := range infos {
    45  		filesystemAttachmentInfo := filesystemAttachmentInfo{
    46  			FilesystemId:   filesystemId,
    47  			FilesystemInfo: info,
    48  		}
    49  		if info.Attachments == nil {
    50  			filesystemAttachmentInfos = append(filesystemAttachmentInfos, filesystemAttachmentInfo)
    51  			continue
    52  		}
    53  		// Each unit attachment must have a corresponding filesystem
    54  		// attachment. Enumerate each of the filesystem attachments,
    55  		// and locate the corresponding unit attachment if any.
    56  		// Each filesystem attachment has at most one corresponding
    57  		// unit attachment.
    58  		for machineId, machineInfo := range info.Attachments.Machines {
    59  			filesystemAttachmentInfo := filesystemAttachmentInfo
    60  			filesystemAttachmentInfo.MachineId = machineId
    61  			filesystemAttachmentInfo.MachineFilesystemAttachment = machineInfo
    62  			for unitId, unitInfo := range info.Attachments.Units {
    63  				if unitInfo.MachineId == machineId {
    64  					filesystemAttachmentInfo.UnitId = unitId
    65  					filesystemAttachmentInfo.UnitStorageAttachment = unitInfo
    66  					break
    67  				}
    68  			}
    69  			filesystemAttachmentInfos = append(filesystemAttachmentInfos, filesystemAttachmentInfo)
    70  		}
    71  	}
    72  	sort.Sort(filesystemAttachmentInfos)
    73  
    74  	for _, info := range filesystemAttachmentInfos {
    75  		var size string
    76  		if info.Size > 0 {
    77  			size = humanize.IBytes(info.Size * humanize.MiByte)
    78  		}
    79  		print(
    80  			info.MachineId, info.UnitId, info.Storage,
    81  			info.FilesystemId, info.Volume, info.ProviderFilesystemId,
    82  			info.MountPoint, size,
    83  			string(info.Status.Current), info.Status.Message,
    84  		)
    85  	}
    86  
    87  	tw.Flush()
    88  	return out.Bytes()
    89  }
    90  
    91  type filesystemAttachmentInfo struct {
    92  	FilesystemId string
    93  	FilesystemInfo
    94  
    95  	MachineId string
    96  	MachineFilesystemAttachment
    97  
    98  	UnitId string
    99  	UnitStorageAttachment
   100  }
   101  
   102  type filesystemAttachmentInfos []filesystemAttachmentInfo
   103  
   104  func (v filesystemAttachmentInfos) Len() int {
   105  	return len(v)
   106  }
   107  
   108  func (v filesystemAttachmentInfos) Swap(i, j int) {
   109  	v[i], v[j] = v[j], v[i]
   110  }
   111  
   112  func (v filesystemAttachmentInfos) Less(i, j int) bool {
   113  	switch compareStrings(v[i].MachineId, v[j].MachineId) {
   114  	case -1:
   115  		return true
   116  	case 1:
   117  		return false
   118  	}
   119  
   120  	switch compareSlashSeparated(v[i].UnitId, v[j].UnitId) {
   121  	case -1:
   122  		return true
   123  	case 1:
   124  		return false
   125  	}
   126  
   127  	switch compareSlashSeparated(v[i].Storage, v[j].Storage) {
   128  	case -1:
   129  		return true
   130  	case 1:
   131  		return false
   132  	}
   133  
   134  	return v[i].FilesystemId < v[j].FilesystemId
   135  }