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  }