Skip to content

Commit b83d295

Browse files
authored
REP-6829 Add 4.0 support (#176)
This adds support for MongoDB 4.0 sources to Migration Verifier. - The support is limited to replica sets because 4.0 didn’t support change streams from a mongos. - The only tested destination version is 8.0. - This _downgrades_ the Go driver to v2.3.1 because that’s the last version that supported 4.0. - CI also now uses an outdated PyMongo for the same reason. Also added is CI testing of 4.2->8.0.
1 parent 59a21af commit b83d295

File tree

30 files changed

+259
-419
lines changed

30 files changed

+259
-419
lines changed

.github/workflows/all.yml

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@ on:
77
pull_request:
88
workflow_dispatch:
99

10+
env:
11+
replsetSrcConnStr: mongodb://localhost:27020,localhost:27021,localhost:27022
12+
replsetDstConnStr: mongodb://localhost:27030,localhost:27031,localhost:27032
13+
shardedSrcConnStr: mongodb://localhost:27020
14+
shardedDstConnStr: mongodb://localhost:27030
15+
1016
jobs:
1117
basics:
1218
strategy:
1319
fail-fast: false
1420
matrix:
1521
include:
22+
# NB: This is the only setup we’re supporting with 4.0.
23+
- mongodb_versions: [ '4.0', '8.0' ]
24+
topology: replset
1625

1726
# Testing fallback when `hello` isn’t implemented
1827
# (but appendOplogNote is).
1928
- mongodb_versions: [ '4.2.5', '6.0' ]
20-
topology:
21-
name: replset
22-
srcConnStr: mongodb://localhost:27020,localhost:27021,localhost:27022
23-
dstConnStr: mongodb://localhost:27030,localhost:27031,localhost:27032
29+
topology: replset
2430

2531
exclude:
2632
- mongodb_versions: [ '4.2', '4.2' ]
@@ -31,13 +37,16 @@ jobs:
3137
toHashedIndexKey: true
3238
- mongodb_versions: [ '4.2', '6.0' ]
3339
toHashedIndexKey: true
40+
- mongodb_versions: [ '4.2', '8.0' ]
41+
toHashedIndexKey: true
3442

3543
# versions are: source, destination
3644
mongodb_versions:
3745
- [ '4.2', '4.2' ]
3846
- [ '4.2', '4.4' ]
3947
- [ '4.2', '5.0' ]
4048
- [ '4.2', '6.0' ]
49+
- [ '4.2', '8.0' ]
4150

4251
- [ '4.4', '4.4' ]
4352
- [ '4.4', '5.0' ]
@@ -61,26 +70,15 @@ jobs:
6170
toHashedIndexKey: [true, false]
6271

6372
topology:
64-
- name: replset
65-
srcConnStr: mongodb://localhost:27020,localhost:27021,localhost:27022
66-
dstConnStr: mongodb://localhost:27030,localhost:27031,localhost:27032
67-
68-
- name: replset-to-sharded
69-
dstArgs: --sharded 2
70-
srcConnStr: mongodb://localhost:27020,localhost:27021,localhost:27022
71-
dstConnStr: mongodb://localhost:27030
72-
73-
- name: sharded
74-
srcArgs: --sharded 2
75-
dstArgs: --sharded 2
76-
srcConnStr: mongodb://localhost:27020
77-
dstConnStr: mongodb://localhost:27030
73+
- replset
74+
- replset-to-sharded
75+
- sharded
7876

7977
# Ubuntu 24 lacks OpenSSL 1.1.1’s libcrypto, which pre-v6 MongoDB
8078
# versions need.
8179
runs-on: ubuntu-22.04
8280

83-
name: ${{ matrix.mongodb_versions[0] }} to ${{ matrix.mongodb_versions[1] }}, ${{ matrix.topology.name }}${{ matrix.toHashedIndexKey && ', hashed doc compare' || '' }}
81+
name: ${{ matrix.mongodb_versions[0] }} to ${{ matrix.mongodb_versions[1] }}, ${{ matrix.topology }}${{ matrix.toHashedIndexKey && ', hashed doc compare' || '' }}
8482

8583
steps:
8684
- run: uname -a
@@ -95,11 +93,12 @@ jobs:
9593
with:
9694
go-version: stable
9795

96+
# Use an old pymongo so we can install MongoDB 4.0.
9897
- name: Install m and mtools
9998
run: |-
10099
{
101100
echo npm install -g m
102-
echo pipx install 'mtools[all]'
101+
echo pip install pymongo==4.10.1 'mtools[all]'
103102
} | parallel
104103
105104
- name: Install MongoDB ${{ matrix.mongodb_versions[0] }} (source)
@@ -115,15 +114,17 @@ jobs:
115114
run: |-
116115
{
117116
echo ./build.sh
118-
echo mlaunch init --binarypath $(cat .srcpath) --port 27020 --dir src --replicaset ${{ matrix.topology.srcArgs }}
119-
echo mlaunch init --binarypath $(cat .dstpath) --port 27030 --dir dst --replicaset ${{ matrix.topology.dstArgs }}
117+
echo mlaunch init --binarypath $(cat .srcpath) --port 27020 --dir src --replicaset ${{ (matrix.topology == 'sharded') && '--sharded 2' || '' }}
118+
echo mlaunch init --binarypath $(cat .dstpath) --port 27030 --dir dst --replicaset ${{ (matrix.topology == 'sharded' || matrix.topology == 'replset-to-sharded') && '--sharded 2' || '' }}
120119
echo mlaunch init --binarypath $(cat .metapath) --port 27040 --dir meta --replicaset --nodes 1
121120
} | parallel
122121
123122
- name: Test
124123
run: go test -v ./... -race
125124
env:
126125
MVTEST_DOC_COMPARE_METHOD: ${{matrix.toHashedIndexKey && 'toHashedIndexKey' || ''}}
127-
MVTEST_SRC: ${{matrix.topology.srcConnStr}}
128-
MVTEST_DST: ${{matrix.topology.dstConnStr}}
126+
127+
MVTEST_SRC: ${{ (matrix.topology == 'sharded') && env.shardedSrcConnStr || env.replsetSrcConnStr }}
128+
MVTEST_DST: ${{ (matrix.topology == 'sharded' || matrix.topology == 'replset-to-sharded') && env.shardedDstConnStr || env.replsetDstConnStr }}
129+
129130
MVTEST_META: mongodb://localhost:27040

go.mod

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ require (
88
github.com/dustin/go-humanize v1.0.1
99
github.com/gin-contrib/pprof v1.5.3
1010
github.com/gin-gonic/gin v1.10.0
11+
github.com/goaux/timer v1.1.0
1112
github.com/google/uuid v1.3.0
1213
github.com/huandu/go-clone/generic v1.7.2
14+
github.com/libp2p/go-buffer-pool v0.1.0
1315
github.com/olekukonko/tablewriter v0.0.5
1416
github.com/pkg/errors v0.9.1
1517
github.com/quasilyte/go-ruleguard/dsl v0.3.22
@@ -18,7 +20,9 @@ require (
1820
github.com/samber/mo v1.13.0
1921
github.com/stretchr/testify v1.10.0
2022
github.com/urfave/cli v1.22.9
21-
go.mongodb.org/mongo-driver/v2 v2.4.0
23+
24+
// NB: This is the last driver version that supported 4.0.
25+
go.mongodb.org/mongo-driver/v2 v2.3.1
2226
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
2327
golang.org/x/sync v0.13.0
2428
gopkg.in/natefinch/lumberjack.v2 v2.0.0
@@ -36,15 +40,13 @@ require (
3640
github.com/go-playground/locales v0.14.1 // indirect
3741
github.com/go-playground/universal-translator v0.18.1 // indirect
3842
github.com/go-playground/validator/v10 v10.26.0 // indirect
39-
github.com/goaux/timer v1.1.0 // indirect
4043
github.com/goccy/go-json v0.10.5 // indirect
4144
github.com/golang/snappy v1.0.0 // indirect
4245
github.com/huandu/go-clone v1.6.0 // indirect
4346
github.com/json-iterator/go v1.1.12 // indirect
4447
github.com/klauspost/compress v1.16.7 // indirect
4548
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
4649
github.com/leodido/go-urn v1.4.0 // indirect
47-
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
4850
github.com/mattn/go-colorable v0.1.13 // indirect
4951
github.com/mattn/go-isatty v0.0.20 // indirect
5052
github.com/mattn/go-runewidth v0.0.9 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
129129
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
130130
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
131131
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
132-
go.mongodb.org/mongo-driver/v2 v2.4.0 h1:Oq6BmUAAFTzMeh6AonuDlgZMuAuEiUxoAD1koK5MuFo=
133-
go.mongodb.org/mongo-driver/v2 v2.4.0/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
132+
go.mongodb.org/mongo-driver/v2 v2.3.1 h1:WrCgSzO7dh1/FrePud9dK5fKNZOE97q5EQimGkos7Wo=
133+
go.mongodb.org/mongo-driver/v2 v2.3.1/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
134134
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
135135
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
136136
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

internal/testutil/testutil.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log"
88
"testing"
99

10+
"github.com/10gen/migration-verifier/internal/util"
1011
"github.com/pkg/errors"
1112
"github.com/samber/lo"
1213
"go.mongodb.org/mongo-driver/v2/bson"
@@ -93,8 +94,18 @@ func KillApplicationChangeStreams(
9394
ctx context.Context,
9495
t *testing.T,
9596
client *mongo.Client,
97+
versionArray []int,
9698
appName string,
9799
) error {
100+
currentOpArg := bson.D{}
101+
102+
if util.ClusterHasCurrentOpIdleCursors([2]int(versionArray)) {
103+
currentOpArg = append(
104+
currentOpArg,
105+
bson.E{"idleCursors", true},
106+
)
107+
}
108+
98109
// Kill verifier’s change stream.
99110
cursor, err := client.Database(
100111
"admin",
@@ -103,9 +114,7 @@ func KillApplicationChangeStreams(
103114
ctx,
104115
mongo.Pipeline{
105116
{
106-
{"$currentOp", bson.D{
107-
{"idleCursors", true},
108-
}},
117+
{"$currentOp", currentOpArg},
109118
},
110119
{
111120
{"$match", bson.D{

internal/util/clusterinfo.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ func ClusterHasBSONSize(va [2]int) bool {
3131
return major > 4
3232
}
3333

34+
func ClusterHasCurrentOpIdleCursors(va [2]int) bool {
35+
major := va[0]
36+
37+
if major == 4 {
38+
return va[1] >= 2
39+
}
40+
41+
return major > 4
42+
}
43+
44+
var ClusterHasChangeStreamStartAfter = ClusterHasCurrentOpIdleCursors
45+
3446
const (
3547
TopologySharded ClusterTopology = "sharded"
3648
TopologyReplset ClusterTopology = "replset"

internal/verifier/change_stream.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,11 @@ func (csr *ChangeStreamReader) createChangeStream(
374374

375375
logEvent.Msg("Starting change stream from persisted resume token.")
376376

377-
opts = opts.SetStartAfter(token)
377+
if util.ClusterHasChangeStreamStartAfter([2]int(csr.clusterInfo.VersionArray)) {
378+
opts = opts.SetStartAfter(token)
379+
} else {
380+
opts = opts.SetResumeAfter(token)
381+
}
378382
} else {
379383
csStartLogEvent.Msgf("Starting change stream from current %s cluster time.", csr.readerType)
380384
}
@@ -386,7 +390,7 @@ func (csr *ChangeStreamReader) createChangeStream(
386390
sctx := mongo.NewSessionContext(ctx, sess)
387391
changeStream, err := csr.watcherClient.Watch(sctx, pipeline, opts)
388392
if err != nil {
389-
return nil, nil, bson.Timestamp{}, errors.Wrap(err, "failed to open change stream")
393+
return nil, nil, bson.Timestamp{}, errors.Wrap(err, "opening change stream")
390394
}
391395

392396
err = csr.persistResumeToken(ctx, changeStream.ResumeToken())

internal/verifier/change_stream_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,7 @@ func (suite *IntegrationTestSuite) TestWritesOffCursorKilledResilience() {
803803
suite.Context(),
804804
suite.T(),
805805
suite.srcMongoClient,
806+
verifier.srcClusterInfo.VersionArray,
806807
clientAppName,
807808
),
808809
)
@@ -831,6 +832,7 @@ func (suite *IntegrationTestSuite) TestCursorKilledResilience() {
831832
suite.Context(),
832833
suite.T(),
833834
suite.srcMongoClient,
835+
verifier.srcClusterInfo.VersionArray,
834836
clientAppName,
835837
),
836838
)

internal/verifier/dockey_agg_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func (suite *IntegrationTestSuite) testExtractTrueDocKeyAgg(reverseYN bool) {
6666
cursor, err := coll.Aggregate(
6767
ctx,
6868
mongo.Pipeline{
69-
{{"$replaceWith", computedDocKeyAgg}},
69+
{{"$replaceRoot", bson.D{{"newRoot", computedDocKeyAgg}}}},
7070
},
7171
)
7272
require.NoError(err, "should open cursor to agg")

internal/verifier/uri.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,7 @@ func (verifier *Verifier) maybeSuggestHashedComparisonOptimization() {
7979
}
8080

8181
func isVersionSupported(version []int) bool {
82-
if version[0] >= 5 {
83-
return true
84-
}
85-
if version[0] < 4 {
86-
return false
87-
}
88-
89-
return version[1] >= 2
82+
return version[0] >= 4
9083
}
9184

9285
func (verifier *Verifier) SetDstURI(ctx context.Context, uri string) error {

0 commit comments

Comments
 (0)