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  }