github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/juju/user_add_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"path/filepath"
    11  
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "launchpad.net/gocheck"
    14  	"launchpad.net/goyaml"
    15  
    16  	"github.com/juju/juju/cmd"
    17  	"github.com/juju/juju/cmd/envcmd"
    18  	"github.com/juju/juju/environs/configstore"
    19  	"github.com/juju/juju/testing"
    20  )
    21  
    22  // All of the functionality of the AddUser api call is contained elsewhere.
    23  // This suite provides basic tests for the "user add" command
    24  type UserAddCommandSuite struct {
    25  	testing.FakeJujuHomeSuite
    26  	mockAPI *mockAddUserAPI
    27  }
    28  
    29  var _ = gc.Suite(&UserAddCommandSuite{})
    30  
    31  func (s *UserAddCommandSuite) SetUpTest(c *gc.C) {
    32  	s.FakeJujuHomeSuite.SetUpTest(c)
    33  	s.mockAPI = &mockAddUserAPI{}
    34  	s.PatchValue(&getAddUserAPI, func(c *UserAddCommand) (addUserAPI, error) {
    35  		return s.mockAPI, nil
    36  	})
    37  }
    38  
    39  func newUserAddCommand() cmd.Command {
    40  	return envcmd.Wrap(&UserAddCommand{})
    41  }
    42  
    43  func (s *UserAddCommandSuite) TestAddUserJustUsername(c *gc.C) {
    44  	context, err := testing.RunCommand(c, newUserAddCommand(), "foobar")
    45  	c.Assert(err, gc.IsNil)
    46  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
    47  	c.Assert(s.mockAPI.displayname, gc.Equals, "")
    48  	// Password is generated
    49  	c.Assert(s.mockAPI.password, gc.Not(gc.Equals), "")
    50  	expected := fmt.Sprintf(`user "foobar" added with password %q`, s.mockAPI.password)
    51  	c.Assert(testing.Stdout(context), gc.Equals, expected+"\n")
    52  }
    53  
    54  func (s *UserAddCommandSuite) TestAddUserUsernameAndDisplayname(c *gc.C) {
    55  	context, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "Foo Bar")
    56  	c.Assert(err, gc.IsNil)
    57  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
    58  	c.Assert(s.mockAPI.displayname, gc.Equals, "Foo Bar")
    59  	// Password is generated
    60  	c.Assert(s.mockAPI.password, gc.Not(gc.Equals), "")
    61  	expected := fmt.Sprintf(`user "Foo Bar (foobar)" added with password %q`, s.mockAPI.password)
    62  	c.Assert(testing.Stdout(context), gc.Equals, expected+"\n")
    63  }
    64  
    65  func (s *UserAddCommandSuite) TestAddUserUsernameAndDisplaynameWithPassword(c *gc.C) {
    66  	context, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "Foo Bar", "--password", "password")
    67  	c.Assert(err, gc.IsNil)
    68  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
    69  	c.Assert(s.mockAPI.displayname, gc.Equals, "Foo Bar")
    70  	c.Assert(s.mockAPI.password, gc.Equals, "password")
    71  	expected := `user "Foo Bar (foobar)" added with password "password"`
    72  	c.Assert(testing.Stdout(context), gc.Equals, expected+"\n")
    73  }
    74  
    75  func (s *UserAddCommandSuite) TestAddUserErrorResponse(c *gc.C) {
    76  	s.mockAPI.failMessage = "failed to create user, chaos ensues"
    77  	context, err := testing.RunCommand(c, newUserAddCommand(), "foobar")
    78  	c.Assert(err, gc.ErrorMatches, "failed to create user, chaos ensues")
    79  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
    80  	c.Assert(s.mockAPI.displayname, gc.Equals, "")
    81  	c.Assert(testing.Stdout(context), gc.Equals, "")
    82  }
    83  
    84  func (s *UserAddCommandSuite) TestInit(c *gc.C) {
    85  	for i, test := range []struct {
    86  		args        []string
    87  		user        string
    88  		displayname string
    89  		password    string
    90  		outPath     string
    91  		errorString string
    92  	}{
    93  		{
    94  			errorString: "no username supplied",
    95  		}, {
    96  			args: []string{"foobar"},
    97  			user: "foobar",
    98  		}, {
    99  			args:        []string{"foobar", "Foo Bar"},
   100  			user:        "foobar",
   101  			displayname: "Foo Bar",
   102  		}, {
   103  			args:        []string{"foobar", "Foo Bar", "extra"},
   104  			errorString: `unrecognized args: \["extra"\]`,
   105  		}, {
   106  			args:     []string{"foobar", "--password", "password"},
   107  			user:     "foobar",
   108  			password: "password",
   109  		}, {
   110  			args:    []string{"foobar", "--output", "somefile"},
   111  			user:    "foobar",
   112  			outPath: "somefile",
   113  		}, {
   114  			args:    []string{"foobar", "-o", "somefile"},
   115  			user:    "foobar",
   116  			outPath: "somefile",
   117  		},
   118  	} {
   119  		c.Logf("test %d", i)
   120  		addUserCmd := &UserAddCommand{}
   121  		err := testing.InitCommand(addUserCmd, test.args)
   122  		if test.errorString == "" {
   123  			c.Check(addUserCmd.User, gc.Equals, test.user)
   124  			c.Check(addUserCmd.DisplayName, gc.Equals, test.displayname)
   125  			c.Check(addUserCmd.Password, gc.Equals, test.password)
   126  			c.Check(addUserCmd.OutPath, gc.Equals, test.outPath)
   127  		} else {
   128  			c.Check(err, gc.ErrorMatches, test.errorString)
   129  		}
   130  	}
   131  }
   132  
   133  func fakeBootstrapEnvironment(c *gc.C, envName string) {
   134  	store, err := configstore.Default()
   135  	c.Assert(err, gc.IsNil)
   136  	envInfo, err := store.CreateInfo(envName)
   137  	c.Assert(err, gc.IsNil)
   138  	envInfo.SetBootstrapConfig(map[string]interface{}{"random": "extra data"})
   139  	envInfo.SetAPIEndpoint(configstore.APIEndpoint{
   140  		Addresses: []string{"localhost:12345"},
   141  		CACert:    testing.CACert,
   142  	})
   143  	envInfo.SetAPICredentials(configstore.APICredentials{
   144  		User:     "admin",
   145  		Password: "password",
   146  	})
   147  	err = envInfo.Write()
   148  	c.Assert(err, gc.IsNil)
   149  }
   150  
   151  func (s *UserAddCommandSuite) TestJenvOutput(c *gc.C) {
   152  	fakeBootstrapEnvironment(c, "erewhemos")
   153  	outputName := filepath.Join(c.MkDir(), "output")
   154  	ctx, err := testing.RunCommand(c, newUserAddCommand(),
   155  		"foobar", "--password", "password", "--output", outputName)
   156  	c.Assert(err, gc.IsNil)
   157  
   158  	expected := fmt.Sprintf(`user "foobar" added with password %q`, s.mockAPI.password)
   159  	expected = fmt.Sprintf("%s\nenvironment file written to %s.jenv\n", expected, outputName)
   160  	c.Assert(testing.Stdout(ctx), gc.Equals, expected)
   161  
   162  	raw, err := ioutil.ReadFile(outputName + ".jenv")
   163  	c.Assert(err, gc.IsNil)
   164  	d := map[string]interface{}{}
   165  	err = goyaml.Unmarshal(raw, &d)
   166  	c.Assert(err, gc.IsNil)
   167  	c.Assert(d["user"], gc.Equals, "foobar")
   168  	c.Assert(d["password"], gc.Equals, "password")
   169  	c.Assert(d["state-servers"], gc.DeepEquals, []interface{}{"localhost:12345"})
   170  	c.Assert(d["ca-cert"], gc.DeepEquals, testing.CACert)
   171  	_, found := d["bootstrap-config"]
   172  	c.Assert(found, jc.IsFalse)
   173  }
   174  
   175  type mockAddUserAPI struct {
   176  	failMessage string
   177  	username    string
   178  	displayname string
   179  	password    string
   180  }
   181  
   182  func (m *mockAddUserAPI) AddUser(username, displayname, password string) error {
   183  	m.username = username
   184  	m.displayname = displayname
   185  	m.password = password
   186  	if m.failMessage == "" {
   187  		return nil
   188  	}
   189  	return errors.New(m.failMessage)
   190  }
   191  
   192  func (*mockAddUserAPI) Close() error {
   193  	return nil
   194  }