From 41b3f9fb93d25a1886609be2596545b483f0298b Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Tue, 21 Oct 2025 09:22:14 -0400 Subject: [PATCH 1/5] direct connection --- main/migration_verifier.go | 16 +++++++++++++++- mmongo/connstring.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 mmongo/connstring.go diff --git a/main/migration_verifier.go b/main/migration_verifier.go index cecc4150..7248c3cd 100644 --- a/main/migration_verifier.go +++ b/main/migration_verifier.go @@ -11,6 +11,7 @@ import ( "time" "github.com/10gen/migration-verifier/internal/verifier" + "github.com/10gen/migration-verifier/mmongo" "github.com/10gen/migration-verifier/mslices" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -275,18 +276,31 @@ func handleArgs(ctx context.Context, cCtx *cli.Context) (*verifier.Verifier, err Int("processID", os.Getpid()). Msg("migration-verifier started.") - err := v.SetSrcURI(ctx, cCtx.String(srcURI)) + srcConnStr := cCtx.String(srcURI) + _, srcConnStr, err := mmongo.MaybeAddDirectConnection(srcConnStr) + if err != nil { + return nil, errors.Wrap(err, "parsing source connection string") + } + err = v.SetSrcURI(ctx, srcURI) if err != nil { return nil, err } dstConnStr := cCtx.String(dstURI) + _, dstConnStr, err = mmongo.MaybeAddDirectConnection(dstConnStr) + if err != nil { + return nil, errors.Wrap(err, "parsing destination connection string") + } err = v.SetDstURI(ctx, dstConnStr) if err != nil { return nil, err } metaConnStr := cCtx.String(metaURI) + _, metaConnStr, err = mmongo.MaybeAddDirectConnection(metaConnStr) + if err != nil { + return nil, errors.Wrap(err, "parsing metadata connection string") + } err = v.SetMetaURI(ctx, metaConnStr) if err != nil { return nil, err diff --git a/mmongo/connstring.go b/mmongo/connstring.go new file mode 100644 index 00000000..dc32bb6a --- /dev/null +++ b/mmongo/connstring.go @@ -0,0 +1,38 @@ +package mmongo + +import ( + "fmt" + + "github.com/pkg/errors" + "github.com/samber/lo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +// MaybeAddDirectConnection adds the `directConnection` parameter +// to the connection string if: +// - There is only 1 host. +// - The connection string lacks parameters that contraindicate a +// direct connection. +// +// This logic mimics mongosh’s behavior. See: +// https://github.com/mongodb-js/mongosh/blob/fea739edfa86edc2a60756d9a9d478f87d94ddda/packages/arg-parser/src/uri-generator.ts#L308 +func MaybeAddDirectConnection(in string) (bool, string, error) { + opts := options.Client().ApplyURI(in) + if err := opts.Validate(); err != nil { + return false, "", errors.Wrapf(err, "parsing connection string %#q", in) + } + + var added bool + + switch len(opts.Hosts) { + case 0: + return false, "", fmt.Errorf("connection string has no hosts?? (%#q)", in) + case 1: + if opts.ReplicaSet == nil && opts.Direct == nil && opts.LoadBalanced == nil { + opts.Direct = lo.ToPtr(true) + added = true + } + } + + return added, opts.GetURI(), nil +} From c421f8aac60d486a62392ef0e31486f27e33a77d Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Tue, 21 Oct 2025 10:08:44 -0400 Subject: [PATCH 2/5] Update docs --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9dd3bc37..23c7416e 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ curl -sSL https://raw.githubusercontent.com/mongodb-labs/migration-verifier/refs Then start a local replica set to store verification metadata: ``` -docker run -it -p27017:27017 -v ./verifier_db:/data/db --entrypoint bash mongodb/mongodb-community-server -c 'mongod --bind_ip_all --replSet rs & mpid=$! && until mongosh --eval "rs.initiate()"; do sleep 1; done && wait $mpid' +podman run -it -p27017:27017 -v ./verifier_db:/data/db --entrypoint bash docker.io/mongodb/mongodb-community-server -c 'mongod --bind_ip_all --replSet rs & mpid=$! && until mongosh --eval "rs.initiate()"; do sleep 1; done && wait $mpid' ``` -(This will create a local `verifier_db` directory so that you can resume verification if needed.) +(This will create a local `verifier_db` directory so that you can resume verification if needed. Omit `-v` with its argument to avoid that.) Finally, run verification: ``` @@ -40,7 +40,7 @@ The verifier can alternatively store its metadata on the destination cluster. Th # More Details -To see all options: +To see all options: ``` @@ -52,7 +52,7 @@ To check all namespaces: ``` -./migration_verifier --srcURI mongodb://127.0.0.1:27002 --dstURI mongodb://127.0.0.1:27003 --metaURI mongodb://127.0.0.1:27001 --verifyAll +./migration_verifier --srcURI mongodb://127.0.0.1:27002 --dstURI mongodb://127.0.0.1:27003 --verifyAll ``` @@ -133,9 +133,9 @@ The verifier will now check to completion to make sure that there are no inconsi | Flag | Description | |-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `--configFile ` | path to an optional YAML config file | -| `--srcURI ` | source Host URI for migration verification (default: "mongodb://localhost:27017") | -| `--dstURI ` | destination Host URI for migration verification (default: "mongodb://localhost:27018") | -| `--metaURI ` | host URI for storing migration verification metadata (default: "mongodb://localhost:27019") | +| `--srcURI ` | source Host URI for migration verification (required) | +| `--dstURI ` | destination Host URI for migration verification (required) | +| `--metaURI ` | host URI for storing migration verification metadata (default: "mongodb://localhost") | | `--serverPort ` | port for the control web server (default: 27020) | | `--logPath ` | logging file path (default: "stdout") | | `--numWorkers ` | number of worker threads to use for verification (default: 10) | From a8bb5888522e6505126b3d1c5a123c72e0e7236a Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Tue, 21 Oct 2025 10:20:52 -0400 Subject: [PATCH 3/5] update docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23c7416e..decd7f1c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ curl -sSL https://raw.githubusercontent.com/mongodb-labs/migration-verifier/refs Then start a local replica set to store verification metadata: ``` -podman run -it -p27017:27017 -v ./verifier_db:/data/db --entrypoint bash docker.io/mongodb/mongodb-community-server -c 'mongod --bind_ip_all --replSet rs & mpid=$! && until mongosh --eval "rs.initiate()"; do sleep 1; done && wait $mpid' +podman run -it --rm -p27017:27017 -v ./verifier_db:/data/db --entrypoint bash docker.io/mongodb/mongodb-community-server -c 'mongod --bind_ip_all --replSet rs & mpid=$! && until mongosh --eval "rs.initiate({_id: \"rs\", members: [{_id: 0, host: \"localhost:27017\"}]})"; do sleep 1; done && wait $mpid' ``` (This will create a local `verifier_db` directory so that you can resume verification if needed. Omit `-v` with its argument to avoid that.) From f83ecc713a02b0585c38388b29cb667f2b67806b Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Tue, 21 Oct 2025 10:43:01 -0400 Subject: [PATCH 4/5] =?UTF-8?q?fix=20wrong=20string=20=E2=80=A6=20thank=20?= =?UTF-8?q?you,=20linter!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/migration_verifier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/migration_verifier.go b/main/migration_verifier.go index 7248c3cd..aa1c8a65 100644 --- a/main/migration_verifier.go +++ b/main/migration_verifier.go @@ -281,7 +281,7 @@ func handleArgs(ctx context.Context, cCtx *cli.Context) (*verifier.Verifier, err if err != nil { return nil, errors.Wrap(err, "parsing source connection string") } - err = v.SetSrcURI(ctx, srcURI) + err = v.SetSrcURI(ctx, srcConnStr) if err != nil { return nil, err } From 0d4b7775fe28671334dffee337d9ef5b3ef73395 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Tue, 21 Oct 2025 14:11:05 -0400 Subject: [PATCH 5/5] used fixed version --- mmongo/connstring.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/mmongo/connstring.go b/mmongo/connstring.go index dc32bb6a..d0c358e1 100644 --- a/mmongo/connstring.go +++ b/mmongo/connstring.go @@ -2,10 +2,9 @@ package mmongo import ( "fmt" + "strings" - "github.com/pkg/errors" - "github.com/samber/lo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/x/mongo/driver/connstring" ) // MaybeAddDirectConnection adds the `directConnection` parameter @@ -17,22 +16,32 @@ import ( // This logic mimics mongosh’s behavior. See: // https://github.com/mongodb-js/mongosh/blob/fea739edfa86edc2a60756d9a9d478f87d94ddda/packages/arg-parser/src/uri-generator.ts#L308 func MaybeAddDirectConnection(in string) (bool, string, error) { - opts := options.Client().ApplyURI(in) - if err := opts.Validate(); err != nil { - return false, "", errors.Wrapf(err, "parsing connection string %#q", in) + cs, err := connstring.ParseAndValidate(in) + + if err != nil { + return false, "", fmt.Errorf("parsing connection string %#q: %w", in, err) } var added bool - switch len(opts.Hosts) { + switch len(cs.Hosts) { case 0: return false, "", fmt.Errorf("connection string has no hosts?? (%#q)", in) case 1: - if opts.ReplicaSet == nil && opts.Direct == nil && opts.LoadBalanced == nil { - opts.Direct = lo.ToPtr(true) + if cs.ReplicaSet == "" && !cs.DirectConnectionSet && !cs.LoadBalancedSet { + if !strings.Contains(in, "?") { + if cs.Database == "" { + in += "/" + } + + in += "?" + } + + in += "directConnection=true" + added = true } } - return added, opts.GetURI(), nil + return added, in, nil }