github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/environment/users.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for infos. 3 4 package environment 5 6 import ( 7 "bytes" 8 "fmt" 9 "text/tabwriter" 10 "time" 11 12 "github.com/juju/cmd" 13 "github.com/juju/errors" 14 "launchpad.net/gnuflag" 15 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/cmd/envcmd" 18 "github.com/juju/juju/cmd/juju/user" 19 ) 20 21 const ListCommandDoc = `List all users with access to the current environment` 22 23 // UsersCommand shows all the users with access to the current environment. 24 type UsersCommand struct { 25 envcmd.EnvCommandBase 26 out cmd.Output 27 api UsersAPI 28 } 29 30 // UserInfo defines the serialization behaviour of the user information. 31 type UserInfo struct { 32 Username string `yaml:"user-name" json:"user-name"` 33 DateCreated string `yaml:"date-created" json:"date-created"` 34 LastConnection string `yaml:"last-connection" json:"last-connection"` 35 } 36 37 // UsersAPI defines the methods on the client API that the 38 // users command calls. 39 type UsersAPI interface { 40 Close() error 41 EnvironmentUserInfo() ([]params.EnvUserInfo, error) 42 } 43 44 func (c *UsersCommand) getAPI() (UsersAPI, error) { 45 if c.api != nil { 46 return c.api, nil 47 } 48 return c.NewAPIClient() 49 } 50 51 // Info implements Command.Info. 52 func (c *UsersCommand) Info() *cmd.Info { 53 return &cmd.Info{ 54 Name: "users", 55 Purpose: "shows all users with access to the current environment", 56 Doc: ListCommandDoc, 57 } 58 } 59 60 // SetFlags implements Command.SetFlags. 61 func (c *UsersCommand) SetFlags(f *gnuflag.FlagSet) { 62 c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{ 63 "yaml": cmd.FormatYaml, 64 "json": cmd.FormatJson, 65 "tabular": c.formatTabular, 66 }) 67 } 68 69 // Run implements Command.Run. 70 func (c *UsersCommand) Run(ctx *cmd.Context) (err error) { 71 client, err := c.getAPI() 72 if err != nil { 73 return err 74 } 75 defer client.Close() 76 77 result, err := client.EnvironmentUserInfo() 78 if err != nil { 79 return err 80 } 81 82 return c.out.Write(ctx, c.apiUsersToUserInfoSlice(result)) 83 } 84 85 // formatTabular takes an interface{} to adhere to the cmd.Formatter interface 86 func (c *UsersCommand) formatTabular(value interface{}) ([]byte, error) { 87 users, ok := value.([]UserInfo) 88 if !ok { 89 return nil, errors.Errorf("expected value of type %T, got %T", users, value) 90 } 91 var out bytes.Buffer 92 const ( 93 // To format things into columns. 94 minwidth = 0 95 tabwidth = 1 96 padding = 2 97 padchar = ' ' 98 flags = 0 99 ) 100 tw := tabwriter.NewWriter(&out, minwidth, tabwidth, padding, padchar, flags) 101 fmt.Fprintf(tw, "NAME\tDATE CREATED\tLAST CONNECTION\n") 102 for _, user := range users { 103 fmt.Fprintf(tw, "%s\t%s\t%s\n", user.Username, user.DateCreated, user.LastConnection) 104 } 105 tw.Flush() 106 return out.Bytes(), nil 107 } 108 109 func (c *UsersCommand) apiUsersToUserInfoSlice(users []params.EnvUserInfo) []UserInfo { 110 var output []UserInfo 111 for _, info := range users { 112 outInfo := UserInfo{Username: info.UserName} 113 outInfo.DateCreated = user.UserFriendlyDuration(info.DateCreated, time.Now()) 114 if info.LastConnection != nil { 115 outInfo.LastConnection = user.UserFriendlyDuration(*info.LastConnection, time.Now()) 116 } else { 117 outInfo.LastConnection = "never connected" 118 } 119 120 output = append(output, outInfo) 121 } 122 123 return output 124 }