github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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  
    14  	"github.com/juju/juju/cmd/output"
    15  )
    16  
    17  // formatVolumeListTabular returns a tabular summary of volume instances.
    18  func formatVolumeListTabular(writer io.Writer, infos map[string]VolumeInfo) error {
    19  	tw := output.TabWriter(writer)
    20  
    21  	print := func(values ...string) {
    22  		fmt.Fprintln(tw, strings.Join(values, "\t"))
    23  	}
    24  
    25  	haveMachines := false
    26  	volumeAttachmentInfos := make(volumeAttachmentInfos, 0, len(infos))
    27  	for volumeId, info := range infos {
    28  		volumeAttachmentInfo := volumeAttachmentInfo{
    29  			VolumeId:   volumeId,
    30  			VolumeInfo: info,
    31  		}
    32  		if info.Attachments == nil {
    33  			volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
    34  			continue
    35  		}
    36  		// Each unit attachment must have a corresponding volume
    37  		// attachment. Enumerate each of the volume attachments,
    38  		// and locate the corresponding unit attachment if any.
    39  		// Each volume attachment has at most one corresponding
    40  		// unit attachment.
    41  		for machineId, machineInfo := range info.Attachments.Machines {
    42  			volumeAttachmentInfo := volumeAttachmentInfo
    43  			volumeAttachmentInfo.MachineId = machineId
    44  			volumeAttachmentInfo.VolumeAttachment = machineInfo
    45  			for unitId, unitInfo := range info.Attachments.Units {
    46  				if unitInfo.MachineId == machineId {
    47  					volumeAttachmentInfo.UnitId = unitId
    48  					volumeAttachmentInfo.UnitStorageAttachment = unitInfo
    49  					break
    50  				}
    51  			}
    52  			haveMachines = true
    53  			volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
    54  		}
    55  
    56  		for hostId, containerInfo := range info.Attachments.Containers {
    57  			volumeAttachmentInfo := volumeAttachmentInfo
    58  			volumeAttachmentInfo.VolumeAttachment = containerInfo
    59  			for unitId, unitInfo := range info.Attachments.Units {
    60  				if hostId == unitId {
    61  					volumeAttachmentInfo.UnitId = unitId
    62  					volumeAttachmentInfo.UnitStorageAttachment = unitInfo
    63  					break
    64  				}
    65  			}
    66  			volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
    67  		}
    68  	}
    69  	sort.Sort(volumeAttachmentInfos)
    70  
    71  	if haveMachines {
    72  		print("Machine", "Unit", "Storage id", "Volume id", "Provider Id", "Device", "Size", "State", "Message")
    73  	} else {
    74  		print("Unit", "Storage id", "Volume id", "Provider Id", "Size", "State", "Message")
    75  	}
    76  
    77  	for _, info := range volumeAttachmentInfos {
    78  		var size string
    79  		if info.Size > 0 {
    80  			size = humanize.IBytes(info.Size * humanize.MiByte)
    81  		}
    82  		if haveMachines {
    83  			print(
    84  				info.MachineId, info.UnitId, info.Storage,
    85  				info.VolumeId, info.ProviderVolumeId,
    86  				info.DeviceName, size,
    87  				string(info.Status.Current), info.Status.Message,
    88  			)
    89  		} else {
    90  			print(
    91  				info.UnitId, info.Storage,
    92  				info.VolumeId, info.ProviderVolumeId, size,
    93  				string(info.Status.Current), info.Status.Message,
    94  			)
    95  		}
    96  	}
    97  
    98  	return tw.Flush()
    99  }
   100  
   101  type volumeAttachmentInfo struct {
   102  	VolumeId string
   103  	VolumeInfo
   104  
   105  	MachineId string
   106  	VolumeAttachment
   107  
   108  	UnitId string
   109  	UnitStorageAttachment
   110  }
   111  
   112  type volumeAttachmentInfos []volumeAttachmentInfo
   113  
   114  func (v volumeAttachmentInfos) Len() int {
   115  	return len(v)
   116  }
   117  
   118  func (v volumeAttachmentInfos) Swap(i, j int) {
   119  	v[i], v[j] = v[j], v[i]
   120  }
   121  
   122  func (v volumeAttachmentInfos) Less(i, j int) bool {
   123  	switch compareStrings(v[i].MachineId, v[j].MachineId) {
   124  	case -1:
   125  		return true
   126  	case 1:
   127  		return false
   128  	}
   129  
   130  	switch compareSlashSeparated(v[i].UnitId, v[j].UnitId) {
   131  	case -1:
   132  		return true
   133  	case 1:
   134  		return false
   135  	}
   136  
   137  	switch compareSlashSeparated(v[i].Storage, v[j].Storage) {
   138  	case -1:
   139  		return true
   140  	case 1:
   141  		return false
   142  	}
   143  
   144  	return v[i].VolumeId < v[j].VolumeId
   145  }