github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/storage/listformatters.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  	"strconv"
    11  	"strings"
    12  	"text/tabwriter"
    13  
    14  	"github.com/juju/errors"
    15  )
    16  
    17  // formatListTabular returns a tabular summary of storage instances.
    18  func formatListTabular(value interface{}) ([]byte, error) {
    19  	storageInfo, ok := value.(map[string]map[string]StorageInfo)
    20  	if !ok {
    21  		return nil, errors.Errorf("expected value of type %T, got %T", storageInfo, value)
    22  	}
    23  	var out bytes.Buffer
    24  	// To format things into columns.
    25  	tw := tabwriter.NewWriter(&out, 0, 1, 1, ' ', 0)
    26  	p := func(values ...interface{}) {
    27  		for _, v := range values {
    28  			fmt.Fprintf(tw, "%v\t", v)
    29  		}
    30  		fmt.Fprintln(tw)
    31  	}
    32  	p("[Storage]")
    33  	p("UNIT\tID\tLOCATION\tSTATUS\tPERSISTENT")
    34  
    35  	// First sort by units
    36  	units := make([]string, 0, len(storageInfo))
    37  	for order := range storageInfo {
    38  		units = append(units, order)
    39  	}
    40  	sort.Strings(bySuffixNaturally(units))
    41  	for _, unit := range units {
    42  		all := storageInfo[unit]
    43  
    44  		// Then sort by storage ids
    45  		storageIds := make([]string, 0, len(all))
    46  		for anId := range all {
    47  			storageIds = append(storageIds, anId)
    48  		}
    49  		sort.Strings(bySuffixNaturally(storageIds))
    50  
    51  		for _, storageId := range storageIds {
    52  			info := all[storageId]
    53  			p(unit, storageId, info.Location, info.Status, info.Persistent)
    54  		}
    55  	}
    56  	tw.Flush()
    57  
    58  	return out.Bytes(), nil
    59  }
    60  
    61  type bySuffixNaturally []string
    62  
    63  func (s bySuffixNaturally) Len() int {
    64  	return len(s)
    65  }
    66  
    67  func (s bySuffixNaturally) Swap(a, b int) {
    68  	s[a], s[b] = s[b], s[a]
    69  }
    70  
    71  func (s bySuffixNaturally) Less(a, b int) bool {
    72  	sa := strings.SplitN(s[a], "/", 2)
    73  	sb := strings.SplitN(s[b], "/", 2)
    74  	if sa[0] < sb[0] {
    75  		return true
    76  	}
    77  	altReturn := sa[0] == sb[0] && sa[1] < sb[1]
    78  
    79  	getInt := func(suffix string) (bool, int) {
    80  		num, err := strconv.Atoi(suffix)
    81  		if err != nil {
    82  			// It's possible that we are not looking at numeric suffix
    83  			logger.Infof("parsing a non-numeric %v: %v", suffix, err)
    84  			return false, 0
    85  		}
    86  		fmt.Printf("parsing a non-numeric %v: %v", suffix, err)
    87  		return true, num
    88  	}
    89  
    90  	naIsNumeric, na := getInt(sa[1])
    91  	if !naIsNumeric {
    92  		return altReturn
    93  	}
    94  	nbIsNumeric, nb := getInt(sb[1])
    95  	if !nbIsNumeric {
    96  		return altReturn
    97  	}
    98  	return sa[0] == sb[0] && na < nb
    99  }