github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/storage/volumelistformatters.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  	"fmt"
     8  	"io"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/dustin/go-humanize"
    13  	"github.com/juju/juju/cmd/output"
    14  )
    15  
    16  // formatVolumeListTabular returns a tabular summary of volume instances.
    17  func formatVolumeListTabular(writer io.Writer, infos map[string]VolumeInfo) error {
    18  	tw := output.TabWriter(writer)
    19  
    20  	print := func(values ...string) {
    21  		fmt.Fprintln(tw, strings.Join(values, "\t"))
    22  	}
    23  	print("MACHINE", "UNIT", "STORAGE", "ID", "PROVIDER-ID", "DEVICE", "SIZE", "STATE", "MESSAGE")
    24  
    25  	volumeAttachmentInfos := make(volumeAttachmentInfos, 0, len(infos))
    26  	for volumeId, info := range infos {
    27  		volumeAttachmentInfo := volumeAttachmentInfo{
    28  			VolumeId:   volumeId,
    29  			VolumeInfo: info,
    30  		}
    31  		if info.Attachments == nil {
    32  			volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
    33  			continue
    34  		}
    35  		// Each unit attachment must have a corresponding volume
    36  		// attachment. Enumerate each of the volume attachments,
    37  		// and locate the corresponding unit attachment if any.
    38  		// Each volume attachment has at most one corresponding
    39  		// unit attachment.
    40  		for machineId, machineInfo := range info.Attachments.Machines {
    41  			volumeAttachmentInfo := volumeAttachmentInfo
    42  			volumeAttachmentInfo.MachineId = machineId
    43  			volumeAttachmentInfo.MachineVolumeAttachment = machineInfo
    44  			for unitId, unitInfo := range info.Attachments.Units {
    45  				if unitInfo.MachineId == machineId {
    46  					volumeAttachmentInfo.UnitId = unitId
    47  					volumeAttachmentInfo.UnitStorageAttachment = unitInfo
    48  					break
    49  				}
    50  			}
    51  			volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
    52  		}
    53  	}
    54  	sort.Sort(volumeAttachmentInfos)
    55  
    56  	for _, info := range volumeAttachmentInfos {
    57  		var size string
    58  		if info.Size > 0 {
    59  			size = humanize.IBytes(info.Size * humanize.MiByte)
    60  		}
    61  		print(
    62  			info.MachineId, info.UnitId, info.Storage,
    63  			info.VolumeId, info.ProviderVolumeId,
    64  			info.DeviceName, size,
    65  			string(info.Status.Current), info.Status.Message,
    66  		)
    67  	}
    68  
    69  	return tw.Flush()
    70  }
    71  
    72  type volumeAttachmentInfo struct {
    73  	VolumeId string
    74  	VolumeInfo
    75  
    76  	MachineId string
    77  	MachineVolumeAttachment
    78  
    79  	UnitId string
    80  	UnitStorageAttachment
    81  }
    82  
    83  type volumeAttachmentInfos []volumeAttachmentInfo
    84  
    85  func (v volumeAttachmentInfos) Len() int {
    86  	return len(v)
    87  }
    88  
    89  func (v volumeAttachmentInfos) Swap(i, j int) {
    90  	v[i], v[j] = v[j], v[i]
    91  }
    92  
    93  func (v volumeAttachmentInfos) Less(i, j int) bool {
    94  	switch compareStrings(v[i].MachineId, v[j].MachineId) {
    95  	case -1:
    96  		return true
    97  	case 1:
    98  		return false
    99  	}
   100  
   101  	switch compareSlashSeparated(v[i].UnitId, v[j].UnitId) {
   102  	case -1:
   103  		return true
   104  	case 1:
   105  		return false
   106  	}
   107  
   108  	switch compareSlashSeparated(v[i].Storage, v[j].Storage) {
   109  	case -1:
   110  		return true
   111  	case 1:
   112  		return false
   113  	}
   114  
   115  	return v[i].VolumeId < v[j].VolumeId
   116  }