github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/state/backups/db_restore_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package backups_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 "gopkg.in/mgo.v2" 13 "gopkg.in/mgo.v2/bson" 14 15 "github.com/juju/juju/mongo" 16 "github.com/juju/juju/state/backups" 17 "github.com/juju/juju/testing" 18 ) 19 20 var _ = gc.Suite(&mongoRestoreSuite{}) 21 22 type mongoRestoreSuite struct { 23 testing.BaseSuite 24 } 25 26 func (s *mongoRestoreSuite) TestRestoreDatabase24(c *gc.C) { 27 s.PatchValue(backups.GetMongorestorePath, func() (string, error) { return "/a/fake/mongorestore", nil }) 28 var ranCommand string 29 var ranWithArgs []string 30 fakeRunCommand := func(c string, args ...string) error { 31 ranCommand = c 32 ranWithArgs = args 33 return nil 34 } 35 args := backups.RestorerArgs{ 36 Version: mongo.Mongo24, 37 TagUser: "machine-0", 38 TagUserPassword: "fakePassword", 39 RunCommandFn: fakeRunCommand, 40 StartMongo: func() error { return nil }, 41 StopMongo: func() error { return nil }, 42 } 43 44 s.PatchValue(backups.MongoInstalledVersion, func() mongo.Version { return mongo.Mongo24 }) 45 restorer, err := backups.NewDBRestorer(args) 46 c.Assert(err, jc.ErrorIsNil) 47 err = restorer.Restore("fakePath", nil) 48 c.Assert(err, jc.ErrorIsNil) 49 50 c.Assert(ranCommand, gc.Equals, "/a/fake/mongorestore") 51 c.Assert(ranWithArgs, gc.DeepEquals, []string{"--drop", "--journal", "--oplogReplay", "--dbpath", "/var/lib/juju/db", "fakePath"}) 52 } 53 54 type mongoDb struct { 55 user *mgo.User 56 } 57 58 func (m *mongoDb) UpsertUser(u *mgo.User) error { 59 m.user = u 60 return nil 61 } 62 63 type mongoSession struct { 64 closed bool 65 createRoleCount int 66 cmd []bson.D 67 } 68 69 func (m *mongoSession) Run(cmd interface{}, result interface{}) error { 70 bsoncmd, ok := cmd.(bson.D) 71 if !ok { 72 return errors.New("unexpected cmd") 73 } 74 m.cmd = append(m.cmd, bsoncmd) 75 bsoncmdMap := bsoncmd.Map() 76 if _, ok := bsoncmdMap["createRole"]; ok { 77 m.createRoleCount += 1 78 if m.createRoleCount > 1 { 79 return &mgo.QueryError{ 80 Code: 11000, 81 Message: fmt.Sprintf("Role %q already exists", "oploger@admin"), 82 Assertion: false, 83 } 84 } 85 } 86 return nil 87 } 88 89 func (m *mongoSession) Close() { 90 m.closed = true 91 } 92 93 func (m *mongoSession) DB(_ string) *mgo.Database { 94 return nil 95 } 96 97 func (s *mongoRestoreSuite) assertRestore(c *gc.C) { 98 s.PatchValue(backups.GetMongorestorePath, func() (string, error) { return "/a/fake/mongorestore", nil }) 99 var ranCommand string 100 var ranWithArgs []string 101 fakeRunCommand := func(c string, args ...string) error { 102 ranCommand = c 103 ranWithArgs = args 104 return nil 105 } 106 mgoDb := &mongoDb{} 107 mgoSession := &mongoSession{} 108 109 args := backups.RestorerArgs{ 110 DialInfo: &mgo.DialInfo{ 111 Username: "fakeUsername", 112 Password: "fakePassword", 113 Addrs: []string{"127.0.0.1"}, 114 }, 115 Version: mongo.Mongo32wt, 116 TagUser: "machine-0", 117 TagUserPassword: "fakePassword", 118 GetDB: func(string, backups.MongoSession) backups.MongoDB { return mgoDb }, 119 NewMongoSession: func(dialInfo *mgo.DialInfo) (backups.MongoSession, error) { 120 return mgoSession, nil 121 }, 122 RunCommandFn: fakeRunCommand, 123 } 124 s.PatchValue(backups.MongoInstalledVersion, func() mongo.Version { return mongo.Mongo32wt }) 125 restorer, err := backups.NewDBRestorer(args) 126 c.Assert(err, jc.ErrorIsNil) 127 err = restorer.Restore("fakePath", nil) 128 c.Assert(err, jc.ErrorIsNil) 129 130 c.Assert(ranCommand, gc.Equals, "/a/fake/mongorestore") 131 c.Assert(ranWithArgs, gc.DeepEquals, []string{"--ssl", "--sslAllowInvalidCertificates", "--authenticationDatabase", "admin", "--host", "127.0.0.1", "--username", "fakeUsername", "--password", "fakePassword", "--drop", "--oplogReplay", "--batchSize", "10", "fakePath"}) 132 user := &mgo.User{Username: "machine-0", Password: "fakePassword"} 133 c.Assert(mgoDb.user, gc.DeepEquals, user) 134 c.Assert(mgoSession.closed, jc.IsTrue) 135 mgoSessionCmd := []bson.D{ 136 { 137 bson.DocElem{Name: "createRole", Value: "oploger"}, 138 bson.DocElem{Name: "privileges", Value: []bson.D{ 139 { 140 bson.DocElem{Name: "resource", Value: bson.M{"anyResource": true}}, 141 bson.DocElem{Name: "actions", Value: []string{"anyAction"}}}}}, 142 bson.DocElem{Name: "roles", Value: []string{}}}, 143 { 144 bson.DocElem{Name: "grantRolesToUser", Value: "fakeUsername"}, 145 bson.DocElem{Name: "roles", Value: []string{"oploger"}}}, 146 { 147 bson.DocElem{Name: "grantRolesToUser", Value: "admin"}, 148 bson.DocElem{Name: "roles", Value: []string{"oploger"}}}} 149 c.Assert(mgoSession.cmd, gc.DeepEquals, mgoSessionCmd) 150 } 151 152 func (s *mongoRestoreSuite) TestRestoreDatabase32(c *gc.C) { 153 s.assertRestore(c) 154 } 155 156 func (s *mongoRestoreSuite) TestRestoreIdempotent(c *gc.C) { 157 s.assertRestore(c) 158 // Run a 2nd time, lp:1740969 159 s.assertRestore(c) 160 } 161 162 func (s *mongoRestoreSuite) TestRestoreFailsOnOlderMongo(c *gc.C) { 163 s.PatchValue(backups.GetMongorestorePath, func() (string, error) { return "/a/fake/mongorestore", nil }) 164 args := backups.RestorerArgs{ 165 DialInfo: &mgo.DialInfo{ 166 Username: "fakeUsername", 167 Password: "fakePassword", 168 Addrs: []string{"127.0.0.1"}, 169 }, 170 Version: mongo.Mongo32wt, 171 TagUser: "machine-0", 172 TagUserPassword: "fakePassword", 173 } 174 s.PatchValue(backups.MongoInstalledVersion, func() mongo.Version { return mongo.Mongo24 }) 175 _, err := backups.NewDBRestorer(args) 176 c.Assert(err, gc.ErrorMatches, "restore mongo version 3.2/wiredTiger into version 2.4/mmapv1 not supported") 177 }