diff --git a/README.md b/README.md index 9dd3bc37..decd7f1c 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 --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.) +(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) | diff --git a/main/migration_verifier.go b/main/migration_verifier.go index cecc4150..aa1c8a65 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, srcConnStr) 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..d0c358e1 --- /dev/null +++ b/mmongo/connstring.go @@ -0,0 +1,47 @@ +package mmongo + +import ( + "fmt" + "strings" + + "go.mongodb.org/mongo-driver/x/mongo/driver/connstring" +) + +// 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) { + cs, err := connstring.ParseAndValidate(in) + + if err != nil { + return false, "", fmt.Errorf("parsing connection string %#q: %w", in, err) + } + + var added bool + + switch len(cs.Hosts) { + case 0: + return false, "", fmt.Errorf("connection string has no hosts?? (%#q)", in) + case 1: + if cs.ReplicaSet == "" && !cs.DirectConnectionSet && !cs.LoadBalancedSet { + if !strings.Contains(in, "?") { + if cs.Database == "" { + in += "/" + } + + in += "?" + } + + in += "directConnection=true" + + added = true + } + } + + return added, in, nil +}