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