~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/storage/volumelistformatters.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
// formatVolumeListTabular returns a tabular summary of volume instances.
 
18
func formatVolumeListTabular(value interface{}) ([]byte, error) {
 
19
        infos, ok := value.(map[string]VolumeInfo)
 
20
        if !ok {
 
21
                return nil, errors.Errorf("expected value of type %T, got %T", infos, value)
 
22
        }
 
23
        return formatVolumeListTabularTyped(infos), nil
 
24
}
 
25
 
 
26
func formatVolumeListTabularTyped(infos map[string]VolumeInfo) []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", "PROVIDER-ID", "DEVICE", "SIZE", "STATE", "MESSAGE")
 
42
 
 
43
        volumeAttachmentInfos := make(volumeAttachmentInfos, 0, len(infos))
 
44
        for volumeId, info := range infos {
 
45
                volumeAttachmentInfo := volumeAttachmentInfo{
 
46
                        VolumeId:   volumeId,
 
47
                        VolumeInfo: info,
 
48
                }
 
49
                if info.Attachments == nil {
 
50
                        volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
 
51
                        continue
 
52
                }
 
53
                // Each unit attachment must have a corresponding volume
 
54
                // attachment. Enumerate each of the volume attachments,
 
55
                // and locate the corresponding unit attachment if any.
 
56
                // Each volume attachment has at most one corresponding
 
57
                // unit attachment.
 
58
                for machineId, machineInfo := range info.Attachments.Machines {
 
59
                        volumeAttachmentInfo := volumeAttachmentInfo
 
60
                        volumeAttachmentInfo.MachineId = machineId
 
61
                        volumeAttachmentInfo.MachineVolumeAttachment = machineInfo
 
62
                        for unitId, unitInfo := range info.Attachments.Units {
 
63
                                if unitInfo.MachineId == machineId {
 
64
                                        volumeAttachmentInfo.UnitId = unitId
 
65
                                        volumeAttachmentInfo.UnitStorageAttachment = unitInfo
 
66
                                        break
 
67
                                }
 
68
                        }
 
69
                        volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo)
 
70
                }
 
71
        }
 
72
        sort.Sort(volumeAttachmentInfos)
 
73
 
 
74
        for _, info := range volumeAttachmentInfos {
 
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.VolumeId, info.ProviderVolumeId,
 
82
                        info.DeviceName, size,
 
83
                        string(info.Status.Current), info.Status.Message,
 
84
                )
 
85
        }
 
86
 
 
87
        tw.Flush()
 
88
        return out.Bytes()
 
89
}
 
90
 
 
91
type volumeAttachmentInfo struct {
 
92
        VolumeId string
 
93
        VolumeInfo
 
94
 
 
95
        MachineId string
 
96
        MachineVolumeAttachment
 
97
 
 
98
        UnitId string
 
99
        UnitStorageAttachment
 
100
}
 
101
 
 
102
type volumeAttachmentInfos []volumeAttachmentInfo
 
103
 
 
104
func (v volumeAttachmentInfos) Len() int {
 
105
        return len(v)
 
106
}
 
107
 
 
108
func (v volumeAttachmentInfos) Swap(i, j int) {
 
109
        v[i], v[j] = v[j], v[i]
 
110
}
 
111
 
 
112
func (v volumeAttachmentInfos) 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].VolumeId < v[j].VolumeId
 
135
}