github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/resource/cmd/output_tabular.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cmd
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"sort"
    10  
    11  	"github.com/juju/ansiterm"
    12  	"github.com/juju/errors"
    13  	"github.com/juju/juju/cmd/output"
    14  )
    15  
    16  // FormatCharmTabular returns a tabular summary of charm resources.
    17  func FormatCharmTabular(writer io.Writer, value interface{}) error {
    18  	resources, valueConverted := value.([]FormattedCharmResource)
    19  	if !valueConverted {
    20  		return errors.Errorf("expected value of type %T, got %T", resources, value)
    21  	}
    22  
    23  	// TODO(ericsnow) sort the rows first?
    24  
    25  	// To format things into columns.
    26  	tw := output.TabWriter(writer)
    27  
    28  	// Write the header.
    29  	// We do not print a section label.
    30  	fmt.Fprintln(tw, "Resource\tRevision")
    31  
    32  	// Print each info to its own row.
    33  	for _, res := range resources {
    34  		// the column headers must be kept in sync with these.
    35  		fmt.Fprintf(tw, "%s\t%d\n",
    36  			res.Name,
    37  			res.Revision,
    38  		)
    39  	}
    40  	tw.Flush()
    41  
    42  	return nil
    43  }
    44  
    45  // FormatSvcTabular returns a tabular summary of resources.
    46  func FormatSvcTabular(writer io.Writer, value interface{}) error {
    47  	switch resources := value.(type) {
    48  	case FormattedServiceInfo:
    49  		formatServiceTabular(writer, resources)
    50  		return nil
    51  	case []FormattedUnitResource:
    52  		formatUnitTabular(writer, resources)
    53  		return nil
    54  	case FormattedServiceDetails:
    55  		formatServiceDetailTabular(writer, resources)
    56  		return nil
    57  	case FormattedUnitDetails:
    58  		formatUnitDetailTabular(writer, resources)
    59  		return nil
    60  	default:
    61  		return errors.Errorf("unexpected type for data: %T", resources)
    62  	}
    63  }
    64  
    65  func formatServiceTabular(writer io.Writer, info FormattedServiceInfo) {
    66  	// TODO(ericsnow) sort the rows first?
    67  
    68  	fmt.Fprintln(writer, "[Service]")
    69  	tw := output.TabWriter(writer)
    70  	fmt.Fprintln(tw, "Resource\tSupplied by\tRevision")
    71  
    72  	// Print each info to its own row.
    73  	for _, r := range info.Resources {
    74  		// the column headers must be kept in sync with these.
    75  		fmt.Fprintf(tw, "%v\t%v\t%v\n",
    76  			r.Name,
    77  			r.combinedOrigin,
    78  			r.combinedRevision,
    79  		)
    80  	}
    81  
    82  	// Don't forget to flush!  The Tab writer won't actually write to the output
    83  	// until you flush, which would then have its output incorrectly ordered
    84  	// with the below fmt.Fprintlns.
    85  	tw.Flush()
    86  
    87  	writeUpdates(info.Updates, writer, tw)
    88  }
    89  
    90  func writeUpdates(updates []FormattedCharmResource, out io.Writer, tw *ansiterm.TabWriter) {
    91  	if len(updates) > 0 {
    92  		fmt.Fprintln(out, "")
    93  		fmt.Fprintln(out, "[Updates Available]")
    94  		fmt.Fprintln(tw, "Resource\tRevision")
    95  		for _, r := range updates {
    96  			fmt.Fprintf(tw, "%v\t%v\n",
    97  				r.Name,
    98  				r.Revision,
    99  			)
   100  		}
   101  	}
   102  
   103  	tw.Flush()
   104  }
   105  
   106  func formatUnitTabular(writer io.Writer, resources []FormattedUnitResource) {
   107  	// TODO(ericsnow) sort the rows first?
   108  
   109  	fmt.Fprintln(writer, "[Unit]")
   110  
   111  	// To format things into columns.
   112  	tw := output.TabWriter(writer)
   113  
   114  	// Write the header.
   115  	// We do not print a section label.
   116  	fmt.Fprintln(tw, "Resource\tRevision")
   117  
   118  	// Print each info to its own row.
   119  	for _, r := range resources {
   120  		// the column headers must be kept in sync with these.
   121  		fmt.Fprintf(tw, "%v\t%v\n",
   122  			r.Name,
   123  			r.combinedRevision,
   124  		)
   125  	}
   126  	tw.Flush()
   127  }
   128  
   129  func formatServiceDetailTabular(writer io.Writer, resources FormattedServiceDetails) {
   130  	// note that the unit resource can be a zero value here, to indicate that
   131  	// the unit has not downloaded that resource yet.
   132  
   133  	fmt.Fprintln(writer, "[Units]")
   134  
   135  	sort.Sort(byUnitID(resources.Resources))
   136  	// To format things into columns.
   137  	tw := output.TabWriter(writer)
   138  
   139  	// Write the header.
   140  	fmt.Fprintln(tw, "Unit\tResource\tRevision\tExpected")
   141  
   142  	for _, r := range resources.Resources {
   143  		fmt.Fprintf(tw, "%v\t%v\t%v\t%v\n",
   144  			r.unitNumber,
   145  			r.Expected.Name,
   146  			r.Unit.combinedRevision,
   147  			r.revProgress,
   148  		)
   149  	}
   150  	tw.Flush()
   151  
   152  	writeUpdates(resources.Updates, writer, tw)
   153  }
   154  
   155  func formatUnitDetailTabular(writer io.Writer, resources FormattedUnitDetails) {
   156  	// note that the unit resource can be a zero value here, to indicate that
   157  	// the unit has not downloaded that resource yet.
   158  
   159  	fmt.Fprintln(writer, "[Unit]")
   160  
   161  	sort.Sort(byUnitID(resources))
   162  	// To format things into columns.
   163  	tw := output.TabWriter(writer)
   164  
   165  	// Write the header.
   166  	fmt.Fprintln(tw, "Resource\tRevision\tExpected")
   167  
   168  	for _, r := range resources {
   169  		fmt.Fprintf(tw, "%v\t%v\t%v\n",
   170  			r.Expected.Name,
   171  			r.Unit.combinedRevision,
   172  			r.revProgress,
   173  		)
   174  	}
   175  	tw.Flush()
   176  }
   177  
   178  type byUnitID []FormattedDetailResource
   179  
   180  func (b byUnitID) Len() int      { return len(b) }
   181  func (b byUnitID) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
   182  
   183  func (b byUnitID) Less(i, j int) bool {
   184  	if b[i].unitNumber != b[j].unitNumber {
   185  		return b[i].unitNumber < b[j].unitNumber
   186  	}
   187  	return b[i].Expected.Name < b[j].Expected.Name
   188  }