github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/user/list.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for infos. 3 4 package user 5 6 import ( 7 "io" 8 9 "github.com/juju/ansiterm" 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/gnuflag" 13 "github.com/juju/utils/clock" 14 "github.com/juju/utils/set" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/api/usermanager" 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/cmd/juju/common" 20 "github.com/juju/juju/cmd/modelcmd" 21 "github.com/juju/juju/cmd/output" 22 ) 23 24 var usageListUsersSummary = ` 25 Lists Juju users allowed to connect to a controller.`[1:] 26 27 var usageListUsersDetails = ` 28 By default, the tabular format is used. 29 30 Examples: 31 juju users 32 33 See also: 34 add-user 35 register 36 show-user 37 disable-user 38 enable-user`[1:] 39 40 func NewListCommand() cmd.Command { 41 return modelcmd.WrapController(&listCommand{ 42 infoCommandBase: infoCommandBase{ 43 clock: clock.WallClock, 44 }, 45 }) 46 } 47 48 // listCommand shows all the users in the Juju server. 49 type listCommand struct { 50 infoCommandBase 51 modelUserAPI modelUsersAPI 52 53 All bool 54 modelName string 55 currentUser string 56 } 57 58 // ModelUsersAPI defines the methods on the client API that the 59 // users command calls. 60 type modelUsersAPI interface { 61 Close() error 62 ModelUserInfo() ([]params.ModelUserInfo, error) 63 } 64 65 func (c *listCommand) getModelAPI() (modelUsersAPI, error) { 66 if c.modelUserAPI != nil { 67 return c.modelUserAPI, nil 68 } 69 conn, err := c.NewModelAPIRoot(c.modelName) 70 if err != nil { 71 return nil, errors.Trace(err) 72 } 73 return conn.Client(), nil 74 } 75 76 // Info implements Command.Info. 77 func (c *listCommand) Info() *cmd.Info { 78 return &cmd.Info{ 79 Name: "users", 80 Purpose: usageListUsersSummary, 81 Doc: usageListUsersDetails, 82 Aliases: []string{"list-users"}, 83 } 84 } 85 86 // SetFlags implements Command.SetFlags. 87 func (c *listCommand) SetFlags(f *gnuflag.FlagSet) { 88 c.infoCommandBase.SetFlags(f) 89 f.BoolVar(&c.All, "all", false, "Include disabled users") 90 c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{ 91 "yaml": cmd.FormatYaml, 92 "json": cmd.FormatJson, 93 "tabular": c.formatTabular, 94 }) 95 } 96 97 // Init implements Command.Init. 98 func (c *listCommand) Init(args []string) (err error) { 99 c.modelName, err = cmd.ZeroOrOneArgs(args) 100 if err != nil { 101 return err 102 } 103 return err 104 } 105 106 // Run implements Command.Run. 107 func (c *listCommand) Run(ctx *cmd.Context) (err error) { 108 if c.out.Name() == "tabular" { 109 // Only the tabular outputters need to know the current user, 110 // but both of them do, so do it in one place. 111 accountDetails, err := c.ClientStore().AccountDetails(c.ControllerName()) 112 if err != nil { 113 return err 114 } 115 c.currentUser = names.NewUserTag(accountDetails.User).Canonical() 116 } 117 if c.modelName == "" { 118 return c.controllerUsers(ctx) 119 } 120 return c.modelUsers(ctx) 121 } 122 123 func (c *listCommand) modelUsers(ctx *cmd.Context) error { 124 client, err := c.getModelAPI() 125 if err != nil { 126 return err 127 } 128 defer client.Close() 129 130 result, err := client.ModelUserInfo() 131 if err != nil { 132 return err 133 } 134 if len(result) == 0 { 135 ctx.Infof("No users to display.") 136 return nil 137 } 138 return c.out.Write(ctx, common.ModelUserInfoFromParams(result, c.clock.Now())) 139 } 140 141 func (c *listCommand) controllerUsers(ctx *cmd.Context) error { 142 // Note: the InfoCommandBase and the UserInfo struct are defined 143 // in info.go. 144 client, err := c.getUserInfoAPI() 145 if err != nil { 146 return err 147 } 148 defer client.Close() 149 150 result, err := client.UserInfo(nil, usermanager.IncludeDisabled(c.All)) 151 if err != nil { 152 return err 153 } 154 155 if len(result) == 0 { 156 ctx.Infof("No users to display.") 157 return nil 158 } 159 160 return c.out.Write(ctx, c.apiUsersToUserInfoSlice(result)) 161 } 162 163 func (c *listCommand) formatTabular(writer io.Writer, value interface{}) error { 164 if c.modelName == "" { 165 return c.formatControllerUsers(writer, value) 166 } 167 return c.formatModelUsers(writer, value) 168 } 169 170 func (c *listCommand) isLoggedInUser(username string) bool { 171 tag := names.NewUserTag(username) 172 return tag.Canonical() == c.currentUser 173 } 174 175 func (c *listCommand) formatModelUsers(writer io.Writer, value interface{}) error { 176 users, ok := value.(map[string]common.ModelUserInfo) 177 if !ok { 178 return errors.Errorf("expected value of type %T, got %T", users, value) 179 } 180 modelUsers := set.NewStrings() 181 for name := range users { 182 modelUsers.Add(name) 183 } 184 tw := output.TabWriter(writer) 185 w := output.Wrapper{tw} 186 w.Println("NAME", "DISPLAY NAME", "ACCESS", "LAST CONNECTION") 187 for _, name := range modelUsers.SortedValues() { 188 user := users[name] 189 190 var highlight *ansiterm.Context 191 userName := name 192 if c.isLoggedInUser(name) { 193 userName += "*" 194 highlight = output.CurrentHighlight 195 } 196 w.PrintColor(highlight, userName) 197 w.Println(user.DisplayName, user.Access, user.LastConnection) 198 } 199 tw.Flush() 200 return nil 201 } 202 203 func (c *listCommand) formatControllerUsers(writer io.Writer, value interface{}) error { 204 users, valueConverted := value.([]UserInfo) 205 if !valueConverted { 206 return errors.Errorf("expected value of type %T, got %T", users, value) 207 } 208 209 tw := output.TabWriter(writer) 210 w := output.Wrapper{tw} 211 w.Println("CONTROLLER: " + c.ControllerName()) 212 w.Println() 213 w.Println("NAME", "DISPLAY NAME", "ACCESS", "DATE CREATED", "LAST CONNECTION") 214 for _, user := range users { 215 conn := user.LastConnection 216 if user.Disabled { 217 conn += " (disabled)" 218 } 219 var highlight *ansiterm.Context 220 userName := user.Username 221 if c.isLoggedInUser(user.Username) { 222 userName += "*" 223 highlight = output.CurrentHighlight 224 } 225 w.PrintColor(highlight, userName) 226 w.Println(user.DisplayName, user.Access, user.DateCreated, conn) 227 } 228 tw.Flush() 229 return nil 230 }