github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/cmd/juju/user/info.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for infos.
     3  
     4  package user
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/errors"
    12  	"launchpad.net/gnuflag"
    13  
    14  	"github.com/juju/juju/api/usermanager"
    15  	"github.com/juju/juju/apiserver/params"
    16  )
    17  
    18  const InfoCommandDoc = `
    19  Display infomation on a user.
    20  
    21  Examples:
    22    	# Show information on the current user
    23    	$ juju user info  
    24    	user-name: foobar
    25    	display-name: Foo Bar
    26    	date-created : 1981-02-27 16:10:05 +0000 UTC
    27  	last-connection: 2014-01-01 00:00:00 +0000 UTC
    28  
    29    	# Show information on a user with the given username
    30    	$ juju user info jsmith
    31    	user-name: jsmith
    32    	display-name: John Smith
    33    	date-created : 1981-02-27 16:10:05 +0000 UTC
    34  	last-connection: 2014-01-01 00:00:00 +0000 UTC
    35  
    36    	# Show information on the current user in JSON format
    37    	$ juju user info --format json
    38    	{"user-name":"foobar",
    39    	"display-name":"Foo Bar",
    40  	"date-created": "1981-02-27 16:10:05 +0000 UTC",
    41  	"last-connection": "2014-01-01 00:00:00 +0000 UTC"}
    42  
    43    	# Show information on the current user in YAML format
    44    	$ juju user info --format yaml
    45   	user-name: foobar
    46   	display-name: Foo Bar
    47   	date-created : 1981-02-27 16:10:05 +0000 UTC
    48  	last-connection: 2014-01-01 00:00:00 +0000 UTC
    49  `
    50  
    51  // UserInfoAPI defines the API methods that the info command uses.
    52  type UserInfoAPI interface {
    53  	UserInfo([]string, usermanager.IncludeDisabled) ([]params.UserInfo, error)
    54  	Close() error
    55  }
    56  
    57  // InfoCommandBase is a common base for 'juju user info' and 'juju user list'.
    58  type InfoCommandBase struct {
    59  	UserCommandBase
    60  	api       UserInfoAPI
    61  	exactTime bool
    62  	out       cmd.Output
    63  }
    64  
    65  func (c *InfoCommandBase) SetFlags(f *gnuflag.FlagSet) {
    66  	f.BoolVar(&c.exactTime, "exact-time", false, "use full timestamp precision")
    67  }
    68  
    69  // InfoCommand retrieves information about a single user.
    70  type InfoCommand struct {
    71  	InfoCommandBase
    72  	Username string
    73  }
    74  
    75  // UserInfo defines the serialization behaviour of the user information.
    76  type UserInfo struct {
    77  	Username       string `yaml:"user-name" json:"user-name"`
    78  	DisplayName    string `yaml:"display-name" json:"display-name"`
    79  	DateCreated    string `yaml:"date-created" json:"date-created"`
    80  	LastConnection string `yaml:"last-connection" json:"last-connection"`
    81  	Disabled       bool   `yaml:"disabled,omitempty" json:"disabled,omitempty"`
    82  }
    83  
    84  // Info implements Command.Info.
    85  func (c *InfoCommand) Info() *cmd.Info {
    86  	return &cmd.Info{
    87  		Name:    "info",
    88  		Args:    "<username>",
    89  		Purpose: "shows information on a user",
    90  		Doc:     InfoCommandDoc,
    91  	}
    92  }
    93  
    94  // SetFlags implements Command.SetFlags.
    95  func (c *InfoCommand) SetFlags(f *gnuflag.FlagSet) {
    96  	c.InfoCommandBase.SetFlags(f)
    97  	c.out.AddFlags(f, "yaml", cmd.DefaultFormatters)
    98  }
    99  
   100  // Init implements Command.Init.
   101  func (c *InfoCommand) Init(args []string) (err error) {
   102  	c.Username, err = cmd.ZeroOrOneArgs(args)
   103  	return err
   104  }
   105  
   106  func (c *InfoCommandBase) getUserInfoAPI() (UserInfoAPI, error) {
   107  	if c.api != nil {
   108  		return c.api, nil
   109  	}
   110  	return c.NewUserManagerClient()
   111  }
   112  
   113  // Run implements Command.Run.
   114  func (c *InfoCommand) Run(ctx *cmd.Context) (err error) {
   115  	client, err := c.getUserInfoAPI()
   116  	if err != nil {
   117  		return err
   118  	}
   119  	defer client.Close()
   120  	username := c.Username
   121  	if username == "" {
   122  		info, err := c.ConnectionCredentials()
   123  		if err != nil {
   124  			return err
   125  		}
   126  		username = info.User
   127  	}
   128  	result, err := client.UserInfo([]string{username}, false)
   129  	if err != nil {
   130  		return err
   131  	}
   132  	// Don't output the params type, be explicit. We convert before checking
   133  	// length because we want to reuse the conversion function, and we are
   134  	// pretty sure that there is one value there.
   135  	output := c.apiUsersToUserInfoSlice(result)
   136  	if len(output) != 1 {
   137  		return errors.Errorf("expected 1 result, got %d", len(output))
   138  	}
   139  	return c.out.Write(ctx, output[0])
   140  }
   141  
   142  func (c *InfoCommandBase) apiUsersToUserInfoSlice(users []params.UserInfo) []UserInfo {
   143  	var output []UserInfo
   144  	var now = time.Now()
   145  	for _, info := range users {
   146  		outInfo := UserInfo{
   147  			Username:    info.Username,
   148  			DisplayName: info.DisplayName,
   149  			Disabled:    info.Disabled,
   150  		}
   151  		if c.exactTime {
   152  			outInfo.DateCreated = info.DateCreated.String()
   153  		} else {
   154  			outInfo.DateCreated = userFriendlyDuration(info.DateCreated, now)
   155  		}
   156  		if info.LastConnection != nil {
   157  			if c.exactTime {
   158  				outInfo.LastConnection = info.LastConnection.String()
   159  			} else {
   160  				outInfo.LastConnection = userFriendlyDuration(*info.LastConnection, now)
   161  			}
   162  		} else {
   163  			outInfo.LastConnection = "never connected"
   164  		}
   165  
   166  		output = append(output, outInfo)
   167  	}
   168  
   169  	return output
   170  }
   171  
   172  func userFriendlyDuration(when, now time.Time) string {
   173  	since := now.Sub(when)
   174  	// if over 24 hours ago, just say the date.
   175  	if since.Hours() >= 24 {
   176  		return when.Format("2006-01-02")
   177  	}
   178  	if since.Hours() >= 1 {
   179  		unit := "hours"
   180  		if int(since.Hours()) == 1 {
   181  			unit = "hour"
   182  		}
   183  		return fmt.Sprintf("%d %s ago", int(since.Hours()), unit)
   184  	}
   185  	if since.Minutes() >= 1 {
   186  		unit := "minutes"
   187  		if int(since.Minutes()) == 1 {
   188  			unit = "minute"
   189  		}
   190  		return fmt.Sprintf("%d %s ago", int(since.Minutes()), unit)
   191  	}
   192  	if since.Seconds() >= 2 {
   193  		return fmt.Sprintf("%d seconds ago", int(since.Seconds()))
   194  	}
   195  	return "just now"
   196  }