github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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 user_test 5 6 import ( 7 "io/ioutil" 8 "path/filepath" 9 "strings" 10 11 "github.com/juju/cmd" 12 "github.com/juju/errors" 13 "github.com/juju/names" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/apiserver/params" 18 "github.com/juju/juju/cmd/envcmd" 19 "github.com/juju/juju/cmd/juju/user" 20 "github.com/juju/juju/testing" 21 ) 22 23 // All of the functionality of the AddUser api call is contained elsewhere. 24 // This suite provides basic tests for the "user add" command 25 type UserAddCommandSuite struct { 26 BaseSuite 27 mockAPI *mockAddUserAPI 28 } 29 30 var _ = gc.Suite(&UserAddCommandSuite{}) 31 32 func (s *UserAddCommandSuite) SetUpTest(c *gc.C) { 33 s.BaseSuite.SetUpTest(c) 34 s.mockAPI = &mockAddUserAPI{} 35 s.PatchValue(user.GetAddUserAPI, func(c *user.AddCommand) (user.AddUserAPI, error) { 36 return s.mockAPI, nil 37 }) 38 s.PatchValue(user.GetShareEnvAPI, func(c *user.AddCommand) (user.ShareEnvironmentAPI, error) { 39 return s.mockAPI, nil 40 }) 41 } 42 43 func newUserAddCommand() cmd.Command { 44 return envcmd.Wrap(&user.AddCommand{}) 45 } 46 47 func (s *UserAddCommandSuite) TestInit(c *gc.C) { 48 for i, test := range []struct { 49 args []string 50 user string 51 displayname string 52 outPath string 53 generate bool 54 errorString string 55 }{ 56 { 57 errorString: "no username supplied", 58 }, { 59 args: []string{"foobar"}, 60 user: "foobar", 61 }, { 62 args: []string{"foobar", "Foo Bar"}, 63 user: "foobar", 64 displayname: "Foo Bar", 65 }, { 66 args: []string{"foobar", "Foo Bar", "extra"}, 67 errorString: `unrecognized args: \["extra"\]`, 68 }, { 69 args: []string{"foobar", "--generate"}, 70 user: "foobar", 71 generate: true, 72 }, { 73 args: []string{"foobar", "--output", "somefile"}, 74 user: "foobar", 75 outPath: "somefile", 76 }, { 77 args: []string{"foobar", "-o", "somefile"}, 78 user: "foobar", 79 outPath: "somefile", 80 }, 81 } { 82 c.Logf("test %d", i) 83 addUserCmd := &user.AddCommand{} 84 err := testing.InitCommand(addUserCmd, test.args) 85 if test.errorString == "" { 86 c.Check(addUserCmd.User, gc.Equals, test.user) 87 c.Check(addUserCmd.DisplayName, gc.Equals, test.displayname) 88 c.Check(addUserCmd.OutPath, gc.Equals, test.outPath) 89 c.Check(addUserCmd.Generate, gc.Equals, test.generate) 90 } else { 91 c.Check(err, gc.ErrorMatches, test.errorString) 92 } 93 } 94 } 95 96 // serializedCACert adjusts the testing.CACert for the test below. 97 func serializedCACert() string { 98 parts := strings.Split(testing.CACert, "\n") 99 for i, part := range parts { 100 parts[i] = strings.TrimSpace(part) 101 } 102 return strings.Join(parts[:len(parts)-1], "\n") 103 } 104 105 func assertJENVContents(c *gc.C, filename, username, password string) { 106 raw, err := ioutil.ReadFile(filename) 107 c.Assert(err, jc.ErrorIsNil) 108 expected := map[string]interface{}{ 109 "user": username, 110 "password": password, 111 "state-servers": []interface{}{"127.0.0.1:12345"}, 112 "ca-cert": serializedCACert(), 113 "environ-uuid": "env-uuid", 114 } 115 c.Assert(string(raw), jc.YAMLEquals, expected) 116 } 117 118 func (s *UserAddCommandSuite) AssertJENVContents(c *gc.C, filename string) { 119 assertJENVContents(c, filename, s.mockAPI.username, s.mockAPI.password) 120 } 121 122 func (s *UserAddCommandSuite) TestAddUserJustUsername(c *gc.C) { 123 context, err := testing.RunCommand(c, newUserAddCommand(), "foobar") 124 c.Assert(err, jc.ErrorIsNil) 125 c.Assert(s.mockAPI.username, gc.Equals, "foobar") 126 c.Assert(s.mockAPI.displayname, gc.Equals, "") 127 c.Assert(s.mockAPI.password, gc.Equals, "sekrit") 128 expected := ` 129 password: 130 type password again: 131 user "foobar" added 132 environment file written to .*foobar.jenv 133 `[1:] 134 c.Assert(testing.Stdout(context), gc.Matches, expected) 135 c.Assert(testing.Stderr(context), gc.Equals, "To generate a random strong password, use the --generate flag.\n") 136 s.AssertJENVContents(c, context.AbsPath("foobar.jenv")) 137 } 138 139 func (s *UserAddCommandSuite) TestAddUserUsernameAndDisplayname(c *gc.C) { 140 context, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "Foo Bar") 141 c.Assert(err, jc.ErrorIsNil) 142 c.Assert(s.mockAPI.username, gc.Equals, "foobar") 143 c.Assert(s.mockAPI.displayname, gc.Equals, "Foo Bar") 144 expected := `user "Foo Bar (foobar)" added` 145 c.Assert(testing.Stdout(context), jc.Contains, expected) 146 s.AssertJENVContents(c, context.AbsPath("foobar.jenv")) 147 } 148 149 func (s *UserAddCommandSuite) TestBlockAddUser(c *gc.C) { 150 // Block operation 151 s.mockAPI.blocked = true 152 _, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "Foo Bar") 153 c.Assert(err, gc.ErrorMatches, cmd.ErrSilent.Error()) 154 // msg is logged 155 stripped := strings.Replace(c.GetTestLog(), "\n", "", -1) 156 c.Check(stripped, gc.Matches, ".*To unblock changes.*") 157 } 158 159 func (s *UserAddCommandSuite) TestGeneratePassword(c *gc.C) { 160 context, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "--generate") 161 c.Assert(err, jc.ErrorIsNil) 162 c.Assert(s.mockAPI.username, gc.Equals, "foobar") 163 c.Assert(s.mockAPI.password, gc.Not(gc.Equals), "sekrit") 164 c.Assert(s.mockAPI.password, gc.HasLen, 24) 165 expected := ` 166 user "foobar" added 167 environment file written to .*foobar.jenv 168 `[1:] 169 c.Assert(testing.Stdout(context), gc.Matches, expected) 170 c.Assert(testing.Stderr(context), gc.Equals, "") 171 s.AssertJENVContents(c, context.AbsPath("foobar.jenv")) 172 } 173 174 func (s *UserAddCommandSuite) TestAddUserErrorResponse(c *gc.C) { 175 s.mockAPI.failMessage = "failed to create user, chaos ensues" 176 context, err := testing.RunCommand(c, newUserAddCommand(), "foobar", "--generate") 177 c.Assert(err, gc.ErrorMatches, "failed to create user, chaos ensues") 178 c.Assert(s.mockAPI.username, gc.Equals, "foobar") 179 c.Assert(s.mockAPI.displayname, gc.Equals, "") 180 c.Assert(testing.Stdout(context), gc.Equals, "") 181 } 182 183 func (s *UserAddCommandSuite) TestJenvOutput(c *gc.C) { 184 outputName := filepath.Join(c.MkDir(), "output") 185 context, err := testing.RunCommand(c, newUserAddCommand(), 186 "foobar", "--output", outputName) 187 c.Assert(err, jc.ErrorIsNil) 188 s.AssertJENVContents(c, context.AbsPath(outputName+".jenv")) 189 } 190 191 func (s *UserAddCommandSuite) TestJenvOutputWithSuffix(c *gc.C) { 192 outputName := filepath.Join(c.MkDir(), "output.jenv") 193 context, err := testing.RunCommand(c, newUserAddCommand(), 194 "foobar", "--output", outputName) 195 c.Assert(err, jc.ErrorIsNil) 196 s.AssertJENVContents(c, context.AbsPath(outputName)) 197 } 198 199 type mockAddUserAPI struct { 200 failMessage string 201 username string 202 displayname string 203 password string 204 205 shareFailMsg string 206 sharedUsers []names.UserTag 207 blocked bool 208 } 209 210 func (m *mockAddUserAPI) AddUser(username, displayname, password string) (names.UserTag, error) { 211 if m.blocked { 212 return names.UserTag{}, ¶ms.Error{ 213 Code: params.CodeOperationBlocked, 214 Message: "The operation has been blocked.", 215 } 216 } 217 218 m.username = username 219 m.displayname = displayname 220 m.password = password 221 if m.failMessage == "" { 222 return names.NewLocalUserTag(username), nil 223 } 224 return names.UserTag{}, errors.New(m.failMessage) 225 } 226 227 func (m *mockAddUserAPI) ShareEnvironment(users []names.UserTag) error { 228 if m.shareFailMsg != "" { 229 return errors.New(m.shareFailMsg) 230 } 231 m.sharedUsers = users 232 return nil 233 } 234 235 func (*mockAddUserAPI) Close() error { 236 return nil 237 }