github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/juju/user_add.go (about) 1 // Copyright 2012, 2013, 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 10 11 "github.com/juju/errors" 12 "github.com/juju/utils" 13 "launchpad.net/gnuflag" 14 15 "github.com/juju/juju/cmd" 16 "github.com/juju/juju/cmd/envcmd" 17 "github.com/juju/juju/environs/configstore" 18 "github.com/juju/juju/juju" 19 ) 20 21 const userAddCommandDoc = ` 22 Add users to an existing environment. 23 24 The user information is stored within an existing environment, and 25 will be lost when the environent is destroyed. An environment file 26 (.jenv) identifying the new user and the environment can be generated 27 using --output. 28 29 Examples: 30 juju user add foobar (Add user "foobar". A strong password will be generated and printed) 31 juju user add foobar --password=mypass (Add user "foobar" with password "mypass") 32 juju user add foobar --output filename (Add user "foobar" and save environment file to "filename") 33 ` 34 35 type UserAddCommand struct { 36 envcmd.EnvCommandBase 37 User string 38 DisplayName string 39 Password string 40 OutPath string 41 } 42 43 func (c *UserAddCommand) Info() *cmd.Info { 44 return &cmd.Info{ 45 Name: "add", 46 Args: "<username> [<display name>]", 47 Purpose: "adds a user", 48 Doc: userAddCommandDoc, 49 } 50 } 51 52 func (c *UserAddCommand) SetFlags(f *gnuflag.FlagSet) { 53 f.StringVar(&c.Password, "password", "", "Password for new user") 54 f.StringVar(&c.OutPath, "o", "", "Output an environment file for new user") 55 f.StringVar(&c.OutPath, "output", "", "") 56 } 57 58 func (c *UserAddCommand) Init(args []string) error { 59 if len(args) == 0 { 60 return fmt.Errorf("no username supplied") 61 } 62 c.User, args = args[0], args[1:] 63 if len(args) > 0 { 64 c.DisplayName, args = args[0], args[1:] 65 } 66 return cmd.CheckEmpty(args) 67 } 68 69 type addUserAPI interface { 70 AddUser(username, displayname, password string) error 71 Close() error 72 } 73 74 var getAddUserAPI = func(c *UserAddCommand) (addUserAPI, error) { 75 return juju.NewUserManagerClient(c.EnvName) 76 } 77 78 func (c *UserAddCommand) Run(ctx *cmd.Context) error { 79 client, err := getAddUserAPI(c) 80 if err != nil { 81 return err 82 } 83 defer client.Close() 84 if c.Password == "" { 85 c.Password, err = utils.RandomPassword() 86 if err != nil { 87 return errors.Annotate(err, "failed to generate password") 88 } 89 } 90 91 err = client.AddUser(c.User, c.DisplayName, c.Password) 92 if err != nil { 93 return err 94 } 95 user := c.User 96 if c.DisplayName != "" { 97 user = fmt.Sprintf("%s (%s)", c.DisplayName, user) 98 } 99 100 fmt.Fprintf(ctx.Stdout, "user %q added with password %q\n", user, c.Password) 101 102 if c.OutPath != "" { 103 outPath := NormaliseJenvPath(ctx, c.OutPath) 104 err = GenerateUserJenv(c.EnvName, c.User, c.Password, outPath) 105 if err == nil { 106 fmt.Fprintf(ctx.Stdout, "environment file written to %s\n", outPath) 107 } 108 } 109 return err 110 } 111 112 func NormaliseJenvPath(ctx *cmd.Context, outPath string) string { 113 if !strings.HasSuffix(outPath, ".jenv") { 114 outPath = outPath + ".jenv" 115 } 116 return ctx.AbsPath(outPath) 117 } 118 119 func GenerateUserJenv(envName, user, password, outPath string) error { 120 store, err := configstore.Default() 121 if err != nil { 122 return errors.Trace(err) 123 } 124 storeInfo, err := store.ReadInfo(envName) 125 if err != nil { 126 return errors.Trace(err) 127 } 128 outputInfo := configstore.EnvironInfoData{} 129 outputInfo.User = user 130 outputInfo.Password = password 131 outputInfo.StateServers = storeInfo.APIEndpoint().Addresses 132 outputInfo.CACert = storeInfo.APIEndpoint().CACert 133 yaml, err := cmd.FormatYaml(outputInfo) 134 if err != nil { 135 return errors.Trace(err) 136 } 137 138 outFile, err := os.Create(outPath) 139 if err != nil { 140 return errors.Trace(err) 141 } 142 defer outFile.Close() 143 outFile.Write(yaml) 144 if err != nil { 145 return errors.Trace(err) 146 } 147 return nil 148 }