github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/status/history.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package status
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"strconv"
    10  
    11  	"github.com/juju/cmd"
    12  	"github.com/juju/errors"
    13  	"launchpad.net/gnuflag"
    14  
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/cmd/envcmd"
    17  	"github.com/juju/juju/cmd/juju/common"
    18  	"github.com/juju/juju/juju/osenv"
    19  )
    20  
    21  type StatusHistoryCommand struct {
    22  	envcmd.EnvCommandBase
    23  	out           cmd.Output
    24  	outputContent string
    25  	backlogSize   int
    26  	isoTime       bool
    27  	unitName      string
    28  }
    29  
    30  var statusHistoryDoc = `
    31  This command will report the history of status changes for
    32  a given unit.
    33  The statuses for the unit workload and/or agent are available.
    34  -type supports:
    35      agent: will show statuses for the unit's agent
    36      workload: will show statuses for the unit's workload
    37      combined: will show agent and workload statuses combined
    38   and sorted by time of occurrence.
    39  `
    40  
    41  func (c *StatusHistoryCommand) Info() *cmd.Info {
    42  	return &cmd.Info{
    43  		Name:    "status-history",
    44  		Args:    "[-n N] <unit>",
    45  		Purpose: "output past statuses for a unit",
    46  		Doc:     statusHistoryDoc,
    47  	}
    48  }
    49  
    50  func (c *StatusHistoryCommand) SetFlags(f *gnuflag.FlagSet) {
    51  	f.StringVar(&c.outputContent, "type", "combined", "type of statuses to be displayed [agent|workload|combined].")
    52  	f.IntVar(&c.backlogSize, "n", 20, "size of logs backlog.")
    53  	f.BoolVar(&c.isoTime, "utc", false, "display time as UTC in RFC3339 format")
    54  }
    55  
    56  func (c *StatusHistoryCommand) Init(args []string) error {
    57  	switch {
    58  	case len(args) > 1:
    59  		return errors.Errorf("unexpected arguments after unit name.")
    60  	case len(args) == 0:
    61  		return errors.Errorf("unit name is missing.")
    62  	default:
    63  		c.unitName = args[0]
    64  	}
    65  	// If use of ISO time not specified on command line,
    66  	// check env var.
    67  	if !c.isoTime {
    68  		var err error
    69  		envVarValue := os.Getenv(osenv.JujuStatusIsoTimeEnvKey)
    70  		if envVarValue != "" {
    71  			if c.isoTime, err = strconv.ParseBool(envVarValue); err != nil {
    72  				return errors.Annotatef(err, "invalid %s env var, expected true|false", osenv.JujuStatusIsoTimeEnvKey)
    73  			}
    74  		}
    75  	}
    76  	kind := params.HistoryKind(c.outputContent)
    77  	switch kind {
    78  	case params.KindCombined, params.KindAgent, params.KindWorkload:
    79  		return nil
    80  
    81  	}
    82  	return errors.Errorf("unexpected status type %q", c.outputContent)
    83  }
    84  
    85  func (c *StatusHistoryCommand) Run(ctx *cmd.Context) error {
    86  	apiclient, err := c.NewAPIClient()
    87  	if err != nil {
    88  		return fmt.Errorf(connectionError, c.ConnectionName(), err)
    89  	}
    90  	defer apiclient.Close()
    91  	var statuses *params.UnitStatusHistory
    92  	kind := params.HistoryKind(c.outputContent)
    93  	statuses, err = apiclient.UnitStatusHistory(kind, c.unitName, c.backlogSize)
    94  	if err != nil {
    95  		if len(statuses.Statuses) == 0 {
    96  			return errors.Trace(err)
    97  		}
    98  		// Display any error, but continue to print status if some was returned
    99  		fmt.Fprintf(ctx.Stderr, "%v\n", err)
   100  	} else if len(statuses.Statuses) == 0 {
   101  		return errors.Errorf("no status history available")
   102  	}
   103  	table := [][]string{{"TIME", "TYPE", "STATUS", "MESSAGE"}}
   104  	lengths := []int{1, 1, 1, 1}
   105  	for _, v := range statuses.Statuses {
   106  		fields := []string{common.FormatTime(v.Since, c.isoTime), string(v.Kind), string(v.Status), v.Info}
   107  		for k, v := range fields {
   108  			if len(v) > lengths[k] {
   109  				lengths[k] = len(v)
   110  			}
   111  		}
   112  		table = append(table, fields)
   113  	}
   114  	f := fmt.Sprintf("%%-%ds\t%%-%ds\t%%-%ds\t%%-%ds\n", lengths[0], lengths[1], lengths[2], lengths[3])
   115  	for _, v := range table {
   116  		fmt.Printf(f, v[0], v[1], v[2], v[3])
   117  	}
   118  	return nil
   119  }