github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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 "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 // formatFilesystemListTabular writes a tabular summary of filesystem instances. 18 func formatFilesystemListTabular(writer io.Writer, infos map[string]FilesystemInfo) 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 filesystemAttachmentInfos := make(filesystemAttachmentInfos, 0, len(infos)) 27 for filesystemId, info := range infos { 28 filesystemAttachmentInfo := filesystemAttachmentInfo{ 29 FilesystemId: filesystemId, 30 FilesystemInfo: info, 31 } 32 if info.Attachments == nil { 33 filesystemAttachmentInfos = append(filesystemAttachmentInfos, filesystemAttachmentInfo) 34 continue 35 } 36 // Each unit attachment must have a corresponding filesystem 37 // attachment. Enumerate each of the filesystem attachments, 38 // and locate the corresponding unit attachment if any. 39 // Each filesystem attachment has at most one corresponding 40 // unit attachment. 41 for machineId, machineInfo := range info.Attachments.Machines { 42 filesystemAttachmentInfo := filesystemAttachmentInfo 43 filesystemAttachmentInfo.MachineId = machineId 44 filesystemAttachmentInfo.FilesystemAttachment = machineInfo 45 for unitId, unitInfo := range info.Attachments.Units { 46 if unitInfo.MachineId == machineId { 47 filesystemAttachmentInfo.UnitId = unitId 48 filesystemAttachmentInfo.UnitStorageAttachment = unitInfo 49 break 50 } 51 } 52 haveMachines = true 53 filesystemAttachmentInfos = append(filesystemAttachmentInfos, filesystemAttachmentInfo) 54 } 55 56 for hostId, containerInfo := range info.Attachments.Containers { 57 filesystemAttachmentInfo := filesystemAttachmentInfo 58 filesystemAttachmentInfo.FilesystemAttachment = containerInfo 59 for unitId, unitInfo := range info.Attachments.Units { 60 if hostId == unitId { 61 filesystemAttachmentInfo.UnitId = unitId 62 filesystemAttachmentInfo.UnitStorageAttachment = unitInfo 63 break 64 } 65 } 66 filesystemAttachmentInfos = append(filesystemAttachmentInfos, filesystemAttachmentInfo) 67 } 68 } 69 sort.Sort(filesystemAttachmentInfos) 70 71 if haveMachines { 72 print("Machine", "Unit", "Storage id", "Id", "Volume", "Provider id", "Mountpoint", "Size", "State", "Message") 73 } else { 74 print("Unit", "Storage id", "Id", "Provider id", "Mountpoint", "Size", "State", "Message") 75 } 76 77 for _, info := range filesystemAttachmentInfos { 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.FilesystemId, info.Volume, info.ProviderFilesystemId, 86 info.MountPoint, size, 87 string(info.Status.Current), info.Status.Message, 88 ) 89 } else { 90 print( 91 info.UnitId, info.Storage, 92 info.FilesystemId, info.ProviderFilesystemId, 93 info.MountPoint, size, 94 string(info.Status.Current), info.Status.Message, 95 ) 96 } 97 } 98 99 return tw.Flush() 100 } 101 102 type filesystemAttachmentInfo struct { 103 FilesystemId string 104 FilesystemInfo 105 106 MachineId string 107 FilesystemAttachment 108 109 UnitId string 110 UnitStorageAttachment 111 } 112 113 type filesystemAttachmentInfos []filesystemAttachmentInfo 114 115 func (v filesystemAttachmentInfos) Len() int { 116 return len(v) 117 } 118 119 func (v filesystemAttachmentInfos) Swap(i, j int) { 120 v[i], v[j] = v[j], v[i] 121 } 122 123 func (v filesystemAttachmentInfos) Less(i, j int) bool { 124 switch compareStrings(v[i].MachineId, v[j].MachineId) { 125 case -1: 126 return true 127 case 1: 128 return false 129 } 130 131 switch compareSlashSeparated(v[i].UnitId, v[j].UnitId) { 132 case -1: 133 return true 134 case 1: 135 return false 136 } 137 138 switch compareSlashSeparated(v[i].Storage, v[j].Storage) { 139 case -1: 140 return true 141 case 1: 142 return false 143 } 144 145 return v[i].FilesystemId < v[j].FilesystemId 146 }