github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/mongo/admin_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mongo_test 5 6 import ( 7 "net" 8 "os" 9 "path/filepath" 10 "strconv" 11 12 gitjujutesting "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "labix.org/v2/mgo" 15 gc "launchpad.net/gocheck" 16 17 "github.com/juju/juju/mongo" 18 coretesting "github.com/juju/juju/testing" 19 "github.com/juju/juju/upstart" 20 ) 21 22 type adminSuite struct { 23 coretesting.BaseSuite 24 serviceStarts int 25 serviceStops int 26 } 27 28 var _ = gc.Suite(&adminSuite{}) 29 30 func (s *adminSuite) SetUpTest(c *gc.C) { 31 s.BaseSuite.SetUpTest(c) 32 s.serviceStarts = 0 33 s.serviceStops = 0 34 s.PatchValue(mongo.UpstartConfInstall, func(conf *upstart.Conf) error { 35 return nil 36 }) 37 s.PatchValue(mongo.UpstartServiceStart, func(svc *upstart.Service) error { 38 s.serviceStarts++ 39 return nil 40 }) 41 s.PatchValue(mongo.UpstartServiceStop, func(svc *upstart.Service) error { 42 s.serviceStops++ 43 return nil 44 }) 45 } 46 47 func (s *adminSuite) TestEnsureAdminUser(c *gc.C) { 48 inst := &gitjujutesting.MgoInstance{} 49 err := inst.Start(coretesting.Certs) 50 c.Assert(err, gc.IsNil) 51 defer inst.DestroyWithLog() 52 dialInfo := inst.DialInfo() 53 54 // Mock out mongod, so the --noauth execution doesn't 55 // do anything nasty. Also mock out the Signal method. 56 gitjujutesting.PatchExecutableAsEchoArgs(c, s, "mongod") 57 mongodDir := filepath.SplitList(os.Getenv("PATH"))[0] 58 s.PatchValue(&mongo.JujuMongodPath, filepath.Join(mongodDir, "mongod")) 59 s.PatchValue(mongo.ProcessSignal, func(*os.Process, os.Signal) error { 60 return nil 61 }) 62 63 // First call succeeds, as there are no users yet. 64 added, err := s.ensureAdminUser(c, dialInfo, "whomever", "whatever") 65 c.Assert(err, gc.IsNil) 66 c.Assert(added, jc.IsTrue) 67 68 // EnsureAdminUser should have stopped the mongo service, 69 // started a new mongod with --noauth, and then finally 70 // started the service back up. 71 c.Assert(s.serviceStarts, gc.Equals, 1) 72 c.Assert(s.serviceStops, gc.Equals, 1) 73 _, portString, err := net.SplitHostPort(dialInfo.Addrs[0]) 74 c.Assert(err, gc.IsNil) 75 gitjujutesting.AssertEchoArgs(c, "mongod", 76 "--noauth", 77 "--dbpath", "db", 78 "--sslOnNormalPorts", 79 "--sslPEMKeyFile", "server.pem", 80 "--sslPEMKeyPassword", "ignored", 81 "--bind_ip", "127.0.0.1", 82 "--port", portString, 83 "--noprealloc", 84 "--syslog", 85 "--smallfiles", 86 "--journal", 87 ) 88 89 // Second call succeeds, as the admin user is already there. 90 added, err = s.ensureAdminUser(c, dialInfo, "whomever", "whatever") 91 c.Assert(err, gc.IsNil) 92 c.Assert(added, jc.IsFalse) 93 94 // There should have been no additional start/stop. 95 c.Assert(s.serviceStarts, gc.Equals, 1) 96 c.Assert(s.serviceStops, gc.Equals, 1) 97 } 98 99 func (s *adminSuite) TestEnsureAdminUserError(c *gc.C) { 100 inst := &gitjujutesting.MgoInstance{} 101 err := inst.Start(coretesting.Certs) 102 c.Assert(err, gc.IsNil) 103 defer inst.Destroy() 104 dialInfo := inst.DialInfo() 105 106 // First call succeeds, as there are no users yet (mimics --noauth). 107 added, err := s.ensureAdminUser(c, dialInfo, "whomever", "whatever") 108 c.Assert(err, gc.IsNil) 109 c.Assert(added, jc.IsTrue) 110 111 // Second call fails, as there is another user and the database doesn't 112 // actually get reopened with --noauth in the test; mimics AddUser failure 113 _, err = s.ensureAdminUser(c, dialInfo, "whomeverelse", "whateverelse") 114 c.Assert(err, gc.ErrorMatches, `failed to add "whomeverelse" to admin database: cannot set admin password: not authorized for upsert on admin.system.users`) 115 } 116 117 func (s *adminSuite) ensureAdminUser(c *gc.C, dialInfo *mgo.DialInfo, user, password string) (added bool, err error) { 118 _, portString, err := net.SplitHostPort(dialInfo.Addrs[0]) 119 c.Assert(err, gc.IsNil) 120 port, err := strconv.Atoi(portString) 121 c.Assert(err, gc.IsNil) 122 return mongo.EnsureAdminUser(mongo.EnsureAdminUserParams{ 123 DialInfo: dialInfo, 124 Port: port, 125 User: user, 126 Password: password, 127 }) 128 } 129 130 func (s *adminSuite) setUpMongo(c *gc.C) *mgo.DialInfo { 131 inst := &gitjujutesting.MgoInstance{} 132 err := inst.Start(coretesting.Certs) 133 c.Assert(err, gc.IsNil) 134 s.AddCleanup(func(*gc.C) { inst.Destroy() }) 135 dialInfo := inst.DialInfo() 136 dialInfo.Direct = true 137 return dialInfo 138 } 139 140 func (s *adminSuite) TestSetAdminMongoPassword(c *gc.C) { 141 dialInfo := s.setUpMongo(c) 142 session, err := mgo.DialWithInfo(dialInfo) 143 c.Assert(err, gc.IsNil) 144 defer session.Close() 145 admin := session.DB("admin") 146 147 // Check that we can SetAdminMongoPassword to nothing when there's 148 // no password currently set. 149 err = mongo.SetAdminMongoPassword(session, "admin", "") 150 c.Assert(err, gc.IsNil) 151 152 err = mongo.SetAdminMongoPassword(session, "admin", "foo") 153 c.Assert(err, gc.IsNil) 154 err = admin.Login("admin", "") 155 c.Assert(err, gc.ErrorMatches, "auth fails") 156 err = admin.Login("admin", "foo") 157 c.Assert(err, gc.IsNil) 158 } 159 160 func (s *adminSuite) TestSetMongoPassword(c *gc.C) { 161 dialInfo := s.setUpMongo(c) 162 session, err := mgo.DialWithInfo(dialInfo) 163 c.Assert(err, gc.IsNil) 164 defer session.Close() 165 db := session.DB("juju") 166 167 err = db.Login("foo", "bar") 168 c.Assert(err, gc.ErrorMatches, "auth fails") 169 170 err = mongo.SetMongoPassword("foo", "bar", db) 171 c.Assert(err, gc.IsNil) 172 err = db.Login("foo", "bar") 173 c.Assert(err, gc.IsNil) 174 }