-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1073 from percona/PBM-1455-oplog-restore-tests-wi…
…th-mocks PBM-1455: Oplog restore tests
- Loading branch information
Showing
148 changed files
with
23,521 additions
and
11,742 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package oplog | ||
|
||
import ( | ||
"context" | ||
"strings" | ||
|
||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
|
||
"github.com/percona/percona-backup-mongodb/pbm/errors" | ||
) | ||
|
||
// mDB represents MongoDB access functionality. | ||
type mDB struct { | ||
m *mongo.Client | ||
} | ||
|
||
func newMDB(m *mongo.Client) *mDB { | ||
return &mDB{m: m} | ||
} | ||
|
||
// getUUIDForNS ruturns UUID of existing collection. | ||
// When ns doesn't exist, it returns zero value without an error. | ||
// In case of error, it returns zero value for UUID in addition to error. | ||
func (d *mDB) getUUIDForNS(ctx context.Context, ns string) (primitive.Binary, error) { | ||
var uuid primitive.Binary | ||
|
||
db, coll, _ := strings.Cut(ns, ".") | ||
cur, err := d.m.Database(db).ListCollections(ctx, bson.D{{"name", coll}}) | ||
if err != nil { | ||
return uuid, errors.Wrap(err, "list collections") | ||
} | ||
defer cur.Close(ctx) | ||
|
||
for cur.Next(ctx) { | ||
if subtype, data, ok := cur.Current.Lookup("info", "uuid").BinaryOK(); ok { | ||
uuid = primitive.Binary{ | ||
Subtype: subtype, | ||
Data: data, | ||
} | ||
break | ||
} | ||
} | ||
|
||
return uuid, errors.Wrap(cur.Err(), "list collections cursor") | ||
} | ||
|
||
// ensureCollExists ensures that the collection exists before "creating" views or timeseries. | ||
// See PBM-921 for details. | ||
func (d *mDB) ensureCollExists(dbName string) error { | ||
err := d.m.Database(dbName).CreateCollection(context.TODO(), "system.views") | ||
if err != nil { | ||
// MongoDB 5.0 and 6.0 returns NamespaceExists error. | ||
// MongoDB 7.0 and 8.0 does not return error. | ||
// https://github.com/mongodb/mongo/blob/v6.0/src/mongo/base/error_codes.yml#L84 | ||
const NamespaceExists = 48 | ||
var cmdError mongo.CommandError | ||
if !errors.As(err, &cmdError) || cmdError.Code != NamespaceExists { | ||
return errors.Wrapf(err, "ensure %s.system.views collection", dbName) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// applyOps is a wrapper for the applyOps database command, we pass in | ||
// a session to avoid opening a new connection for a few inserts at a time. | ||
func (d *mDB) applyOps(entries []interface{}) error { | ||
singleRes := d.m.Database("admin").RunCommand(context.TODO(), bson.D{{"applyOps", entries}}) | ||
if err := singleRes.Err(); err != nil { | ||
return errors.Wrap(err, "applyOps") | ||
} | ||
res := bson.M{} | ||
err := singleRes.Decode(&res) | ||
if err != nil { | ||
return errors.Wrap(err, "decode singleRes") | ||
} | ||
if isFalsy(res["ok"]) { | ||
return errors.Errorf("applyOps command: %v", res["errmsg"]) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package oplog | ||
|
||
import ( | ||
"context" | ||
"strings" | ||
"testing" | ||
|
||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
"go.mongodb.org/mongo-driver/mongo/integration/mtest" | ||
) | ||
|
||
func TestGetUUIDForNS(t *testing.T) { | ||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock)) | ||
|
||
mt.Run("successful response from db", func(mt *mtest.T) { | ||
expectedUUID := primitive.Binary{Subtype: 0xFF, Data: []byte{0x01, 0x02, 0x03}} | ||
listCollRes := bson.D{ | ||
{"name", "c1"}, | ||
{"type", "collection"}, | ||
{"info", bson.D{ | ||
{"readOnly", false}, | ||
{"uuid", expectedUUID}, | ||
}}, | ||
} | ||
mt.AddMockResponses(mtest.CreateCursorResponse(1, "mydb.c1", mtest.FirstBatch, listCollRes)) | ||
|
||
db := newMDB(mt.Client) | ||
uuid, err := db.getUUIDForNS(context.Background(), "mydb.c1") | ||
if err != nil { | ||
t.Errorf("got err=%v", err) | ||
} | ||
primitive.NewObjectID() | ||
|
||
if !uuid.Equal(expectedUUID) { | ||
t.Errorf("wrong uuid for ns: expected=%v, got=%v", expectedUUID, uuid) | ||
} | ||
t.Log(uuid) | ||
}) | ||
|
||
mt.Run("failed response from db", func(mt *mtest.T) { | ||
errRes := mtest.CreateCommandErrorResponse(mtest.CommandError{ | ||
Code: 11601, | ||
Name: "error", | ||
Message: "querying list collections", | ||
}) | ||
mt.AddMockResponses(errRes) | ||
db := newMDB(mt.Client) | ||
_, err := db.getUUIDForNS(context.Background(), "mydb.c1") | ||
if err == nil { | ||
t.Error("expected to get error from getUUIDForNS") | ||
} | ||
if !strings.Contains(err.Error(), "list collections") { | ||
t.Error("wrong err") | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.