From d48a83aef6f5752b540c520c5b80971a4d6ea361 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 8 Dec 2025 15:02:59 -0500 Subject: [PATCH 1/4] Update to driver 2.4 with global overrides --- go.mod | 2 +- go.sum | 2 + .../v2/internal/decimal128/decinal128.go | 117 --------------- .../v2/internal/driverutil/description.go | 2 +- .../mongo-driver/v2/mongo/bulk_write.go | 7 + .../mongo-driver/v2/mongo/client.go | 135 ++++++++++++------ .../v2/mongo/client_bulk_write.go | 8 ++ .../mongo-driver/v2/mongo/collection.go | 96 ++++++------- .../mongo-driver/v2/mongo/database.go | 6 +- .../mongo-driver/v2/mongo/index_view.go | 18 +-- .../v2/mongo/options/changestreamoptions.go | 2 +- .../mongo/options/listcollectionsoptions.go | 3 +- .../mongo-driver/v2/version/version.go | 2 +- .../v2/x/mongo/driver/operation.go | 14 +- .../mongo/driver/operation/find_and_modify.go | 18 +++ .../v2/x/mongo/driver/operation/insert.go | 19 +++ .../v2/x/mongo/driver/operation/update.go | 18 +++ .../v2/x/mongo/driver/topology/fsm.go | 2 +- .../v2/x/mongo/driver/topology/server.go | 16 ++- .../x/mongo/driver/topology/server_options.go | 33 ++--- .../mongo/driver/topology/topology_options.go | 127 ++++++++++------ vendor/modules.txt | 2 +- 22 files changed, 338 insertions(+), 311 deletions(-) delete mode 100644 vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decinal128.go diff --git a/go.mod b/go.mod index e460feca..50b4eae3 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/urfave/cli v1.22.9 // NB: This is the last driver version that supported 4.0. - go.mongodb.org/mongo-driver/v2 v2.3.1 + go.mongodb.org/mongo-driver/v2 v2.4.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.18.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 diff --git a/go.sum b/go.sum index d6b94fb1..dcc924fd 100644 --- a/go.sum +++ b/go.sum @@ -131,6 +131,8 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver/v2 v2.3.1 h1:WrCgSzO7dh1/FrePud9dK5fKNZOE97q5EQimGkos7Wo= go.mongodb.org/mongo-driver/v2 v2.3.1/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI= +go.mongodb.org/mongo-driver/v2 v2.4.0 h1:Oq6BmUAAFTzMeh6AonuDlgZMuAuEiUxoAD1koK5MuFo= +go.mongodb.org/mongo-driver/v2 v2.4.0/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI= golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U= golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decinal128.go b/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decinal128.go deleted file mode 100644 index 2767e445..00000000 --- a/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decinal128.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2017-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package decimal128 - -import ( - "strconv" -) - -// These constants are the maximum and minimum values for the exponent field in a decimal128 value. -const ( - MaxDecimal128Exp = 6111 - MinDecimal128Exp = -6176 -) - -func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) { - div64 := uint64(div) - a := h >> 32 - aq := a / div64 - ar := a % div64 - b := ar<<32 + h&(1<<32-1) - bq := b / div64 - br := b % div64 - c := br<<32 + l>>32 - cq := c / div64 - cr := c % div64 - d := cr<<32 + l&(1<<32-1) - dq := d / div64 - dr := d % div64 - return (aq<<32 | bq), (cq<<32 | dq), uint32(dr) -} - -// String returns a string representation of the decimal value. -func String(h, l uint64) string { - var posSign int // positive sign - var exp int // exponent - var high, low uint64 // significand high/low - - if h>>63&1 == 0 { - posSign = 1 - } - - switch h >> 58 & (1<<5 - 1) { - case 0x1F: - return "NaN" - case 0x1E: - return "-Infinity"[posSign:] - } - - low = l - if h>>61&3 == 3 { - // Bits: 1*sign 2*ignored 14*exponent 111*significand. - // Implicit 0b100 prefix in significand. - exp = int(h >> 47 & (1<<14 - 1)) - // Spec says all of these values are out of range. - high, low = 0, 0 - } else { - // Bits: 1*sign 14*exponent 113*significand - exp = int(h >> 49 & (1<<14 - 1)) - high = h & (1<<49 - 1) - } - exp += MinDecimal128Exp - - // Would be handled by the logic below, but that's trivial and common. - if high == 0 && low == 0 && exp == 0 { - return "-0"[posSign:] - } - - var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero. - var last = len(repr) - var i = len(repr) - var dot = len(repr) + exp - var rem uint32 -Loop: - for d9 := 0; d9 < 5; d9++ { - high, low, rem = divmod(high, low, 1e9) - for d1 := 0; d1 < 9; d1++ { - // Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc. - if i < len(repr) && (dot == i || low == 0 && high == 0 && rem > 0 && rem < 10 && (dot < i-6 || exp > 0)) { - exp += len(repr) - i - i-- - repr[i] = '.' - last = i - 1 - dot = len(repr) // Unmark. - } - c := '0' + byte(rem%10) - rem /= 10 - i-- - repr[i] = c - // Handle "0E+3", "1E+3", etc. - if low == 0 && high == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || exp > 0) { - last = i - break Loop - } - if c != '0' { - last = i - } - // Break early. Works without it, but why. - if dot > i && low == 0 && high == 0 && rem == 0 { - break Loop - } - } - } - repr[last-1] = '-' - last-- - - if exp > 0 { - return string(repr[last+posSign:]) + "E+" + strconv.Itoa(exp) - } - if exp < 0 { - return string(repr[last+posSign:]) + "E" + strconv.Itoa(exp) - } - return string(repr[last+posSign:]) -} diff --git a/vendor/go.mongodb.org/mongo-driver/v2/internal/driverutil/description.go b/vendor/go.mongodb.org/mongo-driver/v2/internal/driverutil/description.go index 89963799..926de0bd 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/internal/driverutil/description.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/internal/driverutil/description.go @@ -21,7 +21,7 @@ import ( ) const ( - MinWireVersion = 7 + MinWireVersion = 8 MaxWireVersion = 25 ) diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/bulk_write.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/bulk_write.go index 036e3bad..ca683c1d 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/bulk_write.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/bulk_write.go @@ -40,6 +40,7 @@ type bulkWrite struct { result BulkWriteResult let any rawData *bool + additionalCmd bson.D } func (bw *bulkWrite) execute(ctx context.Context) error { @@ -213,6 +214,9 @@ func (bw *bulkWrite) runInsert(ctx context.Context, batch bulkWriteBatch) (opera if bw.rawData != nil { op.RawData(*bw.rawData) } + if len(bw.additionalCmd) > 0 { + op.AdditionalCmd(bw.additionalCmd) + } err := op.Execute(ctx) @@ -427,6 +431,9 @@ func (bw *bulkWrite) runUpdate(ctx context.Context, batch bulkWriteBatch) (opera if bw.rawData != nil { op.RawData(*bw.rawData) } + if len(bw.additionalCmd) > 0 { + op.AdditionalCmd(bw.additionalCmd) + } err := op.Execute(ctx) diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/client.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/client.go index cb2e5494..10182276 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/client.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/client.go @@ -11,6 +11,8 @@ import ( "errors" "fmt" "net/http" + "sync" + "sync/atomic" "time" "go.mongodb.org/mongo-driver/v2/bson" @@ -56,24 +58,26 @@ var ( // The Client type opens and closes connections automatically and maintains a pool of idle connections. For // connection pool configuration options, see documentation for the ClientOptions type in the mongo/options package. type Client struct { - id uuid.UUID - deployment driver.Deployment - localThreshold time.Duration - retryWrites bool - retryReads bool - clock *session.ClusterClock - readPreference *readpref.ReadPref - readConcern *readconcern.ReadConcern - writeConcern *writeconcern.WriteConcern - bsonOpts *options.BSONOptions - registry *bson.Registry - monitor *event.CommandMonitor - serverAPI *driver.ServerAPIOptions - serverMonitor *event.ServerMonitor - sessionPool *session.Pool - timeout *time.Duration - httpClient *http.Client - logger *logger.Logger + id uuid.UUID + deployment driver.Deployment + localThreshold time.Duration + retryWrites bool + retryReads bool + clock *session.ClusterClock + readPreference *readpref.ReadPref + readConcern *readconcern.ReadConcern + writeConcern *writeconcern.WriteConcern + bsonOpts *options.BSONOptions + registry *bson.Registry + monitor *event.CommandMonitor + serverAPI *driver.ServerAPIOptions + serverMonitor *event.ServerMonitor + sessionPool *session.Pool + timeout *time.Duration + httpClient *http.Client + logger *logger.Logger + currentDriverInfo *atomic.Pointer[options.DriverInfo] + seenDriverInfo sync.Map // in-use encryption fields isAutoEncryptionSet bool @@ -87,27 +91,19 @@ type Client struct { authenticator driver.Authenticator } -// Connect creates a new Client and then initializes it using the Connect method. +// Connect creates a new Client with the given configuration options. // -// When creating an options.ClientOptions, the order the methods are called matters. Later Set* -// methods will overwrite the values from previous Set* method invocations. This includes the -// ApplyURI method. This allows callers to determine the order of precedence for option -// application. For instance, if ApplyURI is called before SetAuth, the Credential from -// SetAuth will overwrite the values from the connection string. If ApplyURI is called -// after SetAuth, then its values will overwrite those from SetAuth. +// Connect returns an error if the configuration options are invalid, but does +// not validate that the MongoDB deployment is reachable. To verify that the +// deployment is reachable, call [Client.Ping]. // -// The opts parameter is processed using options.MergeClientOptions, which will overwrite entire -// option fields of previous options, there is no partial overwriting. For example, if Username is -// set in the Auth field for the first option, and Password is set for the second but with no -// Username, after the merge the Username field will be empty. -// -// The NewClient function does not do any I/O and returns an error if the given options are invalid. -// The Client.Connect method starts background goroutines to monitor the state of the deployment and does not do -// any I/O in the main goroutine to prevent the main goroutine from blocking. Therefore, it will not error if the -// deployment is down. -// -// The Client.Ping method can be used to verify that the deployment is successfully connected and the -// Client was correctly configured. +// When creating an [options.ClientOptions], the order the methods are called +// matters. Later option setter calls overwrite the values from previous option +// setter calls, including the ApplyURI method. This allows callers to +// determine the order of precedence for setting options. For instance, if +// ApplyURI is called before SetAuth, the Credential from SetAuth will +// overwrite the values from the connection string. If ApplyURI is called +// after SetAuth, then its values will overwrite those from SetAuth. func Connect(opts ...*options.ClientOptions) (*Client, error) { c, err := newClient(opts...) if err != nil { @@ -140,7 +136,11 @@ func newClient(opts ...*options.ClientOptions) (*Client, error) { if err != nil { return nil, err } - client := &Client{id: id} + + client := &Client{ + id: id, + currentDriverInfo: &atomic.Pointer[options.DriverInfo]{}, + } // ClusterClock client.clock = new(session.ClusterClock) @@ -225,7 +225,16 @@ func newClient(opts ...*options.ClientOptions) (*Client, error) { } } - cfg, err := topology.NewConfigFromOptionsWithAuthenticator(clientOpts, client.clock, client.authenticator) + if clientOpts.DriverInfo != nil { + client.AppendDriverInfo(*clientOpts.DriverInfo) + } + + cfg, err := topology.NewAuthenticatorConfig(client.authenticator, + topology.WithAuthConfigClock(client.clock), + topology.WithAuthConfigClientOptions(clientOpts), + topology.WithAuthConfigDriverInfo(client.currentDriverInfo), + ) + if err != nil { return nil, err } @@ -302,6 +311,45 @@ func (c *Client) connect() error { return nil } +// AppendDriverInfo appends the provided [options.DriverInfo] to the metadata +// (e.g. name, version, platform) that will be sent to the server in handshake +// requests when establishing new connections. +// +// Repeated calls to AppendDriverInfo with equivalent DriverInfo is a no-op. +// +// Metadata is limited to 512 bytes; any excess will be truncated. +func (c *Client) AppendDriverInfo(info options.DriverInfo) { + if _, loaded := c.seenDriverInfo.LoadOrStore(info, struct{}{}); loaded { + return + } + + if old := c.currentDriverInfo.Load(); old != nil { + if old.Name != "" && info.Name != "" && old.Name != info.Name { + info.Name = old.Name + "|" + info.Name + } else if old.Name != "" { + info.Name = old.Name + } + + if old.Version != "" && info.Version != "" && old.Version != info.Version { + info.Version = old.Version + "|" + info.Version + } else if old.Version != "" { + info.Version = old.Version + } + + if old.Platform != "" && info.Platform != "" && old.Platform != info.Platform { + info.Platform = old.Platform + "|" + info.Platform + } else if old.Platform != "" { + info.Platform = old.Platform + } + } + + // Copy-on-write so that the info stored in the client is immutable. + infoCopy := new(options.DriverInfo) + *infoCopy = info + + c.currentDriverInfo.Store(infoCopy) +} + // Disconnect closes sockets to the topology referenced by this Client. It will // shut down any monitoring goroutines, close the idle connection pool, and will // wait until all the in use connections have been returned to the connection @@ -958,10 +1006,11 @@ func (c *Client) BulkWrite(ctx context.Context, writes []ClientBulkWrite, selector: selector, writeConcern: wc, } - if rawDataOpt := optionsutil.Value(bwo.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op.rawData = &rawData - } + if rawData, ok := optionsutil.Value(bwo.Internal, "rawData").(bool); ok { + op.rawData = &rawData + } + if additionalCmd, ok := optionsutil.Value(bwo.Internal, "addCommandFields").(bson.D); ok { + op.additionalCmd = additionalCmd } if bwo.VerboseResults == nil || !(*bwo.VerboseResults) { op.errorsOnly = true diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/client_bulk_write.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/client_bulk_write.go index 27c3ad3c..cb9d8cb4 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/client_bulk_write.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/client_bulk_write.go @@ -45,6 +45,7 @@ type clientBulkWrite struct { selector description.ServerSelector writeConcern *writeconcern.WriteConcern rawData *bool + additionalCmd bson.D result ClientBulkWriteResult } @@ -148,6 +149,13 @@ func (bw *clientBulkWrite) newCommand() func([]byte, description.SelectedServer) if bw.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { dst = bsoncore.AppendBooleanElement(dst, "rawData", *bw.rawData) } + if len(bw.additionalCmd) > 0 { + doc, err := bson.Marshal(bw.additionalCmd) + if err != nil { + return nil, err + } + dst = append(dst, doc[4:len(doc)-1]...) + } return dst, nil } } diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/collection.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/collection.go index ef4188d6..af1960d9 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/collection.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/collection.go @@ -246,10 +246,11 @@ func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel, writeConcern: wc, let: args.Let, } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op.rawData = &rawData - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op.rawData = &rawData + } + if additionalCmd, ok := optionsutil.Value(args.Internal, "addCommandFields").(bson.D); ok { + op.additionalCmd = additionalCmd } err = op.execute(ctx) @@ -330,10 +331,11 @@ func (coll *Collection) insert( if args.Ordered != nil { op = op.Ordered(*args.Ordered) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) + } + if additionalCmd, ok := optionsutil.Value(args.Internal, "addCommandFields").(bson.D); ok { + op = op.AdditionalCmd(additionalCmd) } retry := driver.RetryNone if coll.client.retryWrites { @@ -388,7 +390,14 @@ func (coll *Collection) InsertOne(ctx context.Context, document any, } if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { imOpts.Opts = append(imOpts.Opts, func(opts *options.InsertManyOptions) error { - optionsutil.WithValue(opts.Internal, "rawData", rawDataOpt) + opts.Internal = optionsutil.WithValue(opts.Internal, "rawData", rawDataOpt) + + return nil + }) + } + if additionalCmd := optionsutil.Value(args.Internal, "addCommandFields"); additionalCmd != nil { + imOpts.Opts = append(imOpts.Opts, func(opts *options.InsertManyOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, "addCommandFields", additionalCmd) return nil }) @@ -552,10 +561,8 @@ func (coll *Collection) delete( } op = op.Let(let) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } // deleteMany cannot be retried @@ -705,10 +712,11 @@ func (coll *Collection) updateOrReplace( } op = op.Comment(comment) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) + } + if additionalCmd, ok := optionsutil.Value(args.Internal, "addCommandFields").(bson.D); ok { + op = op.AdditionalCmd(additionalCmd) } retry := driver.RetryNone // retryable writes are only enabled updateOne/replaceOne operations @@ -1067,10 +1075,8 @@ func aggregate(a aggregateParams, opts ...options.Lister[options.AggregateOption } op.CustomOptions(customOptions) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone @@ -1166,10 +1172,8 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter any, } op.Hint(hintVal) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone if coll.client.retryReads { @@ -1252,10 +1256,8 @@ func (coll *Collection) EstimatedDocumentCount( } op = op.Comment(comment) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone @@ -1346,10 +1348,8 @@ func (coll *Collection) Distinct( } op.Hint(hint) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone if coll.client.retryReads { @@ -1554,10 +1554,8 @@ func (coll *Collection) find( } op.Sort(sort) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone if coll.client.retryReads { @@ -1757,10 +1755,8 @@ func (coll *Collection) FindOneAndDelete( } op = op.Let(let) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } return coll.findAndModify(ctx, op) @@ -1859,10 +1855,11 @@ func (coll *Collection) FindOneAndReplace( } op = op.Let(let) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) + } + if additionalCmd, ok := optionsutil.Value(args.Internal, "addCommandFields").(bson.D); ok { + op = op.AdditionalCmd(additionalCmd) } return coll.findAndModify(ctx, op) @@ -1973,10 +1970,11 @@ func (coll *Collection) FindOneAndUpdate( } op = op.Let(let) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) + } + if additionalCmd, ok := optionsutil.Value(args.Internal, "addCommandFields").(bson.D); ok { + op = op.AdditionalCmd(additionalCmd) } return coll.findAndModify(ctx, op) diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/database.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/database.go index e42097bb..7064929e 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/database.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/database.go @@ -489,10 +489,8 @@ func (db *Database) ListCollections( if args.AuthorizedCollections != nil { op = op.AuthorizedCollections(*args.AuthorizedCollections) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/index_view.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/index_view.go index f8529c16..147978d2 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/index_view.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/index_view.go @@ -102,10 +102,8 @@ func (iv IndexView) List(ctx context.Context, opts ...options.Lister[options.Lis op = op.BatchSize(*args.BatchSize) cursorOpts.BatchSize = *args.BatchSize } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } retry := driver.RetryNone @@ -290,10 +288,8 @@ func (iv IndexView) CreateMany( op.CommitQuorum(commitQuorum) } - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } _, err = processWriteError(op.Execute(ctx)) @@ -429,10 +425,8 @@ func (iv IndexView) drop(ctx context.Context, index any, opts ...options.Lister[ Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). Timeout(iv.coll.client.timeout).Crypt(iv.coll.client.cryptFLE).Authenticator(iv.coll.client.authenticator) - if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { - if rawData, ok := rawDataOpt.(bool); ok { - op = op.RawData(rawData) - } + if rawData, ok := optionsutil.Value(args.Internal, "rawData").(bool); ok { + op = op.RawData(rawData) } err = op.Execute(ctx) diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/changestreamoptions.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/changestreamoptions.go index 9e5bb93b..92f19638 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/changestreamoptions.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/changestreamoptions.go @@ -135,7 +135,7 @@ func (cso *ChangeStreamOptionsBuilder) SetShowExpandedEvents(see bool) *ChangeSt } // SetStartAtOperationTime sets the value for the StartAtOperationTime field. If specified, the change stream -// will only return changes that occurred at or after the given timestamp. This MongoDB versions >= 4.0. +// will only return changes that occurred at or after the given timestamp. // If this is specified, ResumeAfter and StartAfter must not be set. func (cso *ChangeStreamOptionsBuilder) SetStartAtOperationTime(t *bson.Timestamp) *ChangeStreamOptionsBuilder { cso.Opts = append(cso.Opts, func(opts *ChangeStreamOptions) error { diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/listcollectionsoptions.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/listcollectionsoptions.go index 14f96cc6..c69a6dc4 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/listcollectionsoptions.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/options/listcollectionsoptions.go @@ -65,8 +65,7 @@ func (lc *ListCollectionsOptionsBuilder) SetBatchSize(size int32) *ListCollectio // SetAuthorizedCollections sets the value for the AuthorizedCollections field. If true, and // NameOnly is true, limits the documents returned to only contain collections the user is -// authorized to use. The default value is false. This option is only valid for MongoDB server -// versions >= 4.0. Server versions < 4.0 ignore this option. +// authorized to use. The default value is false. func (lc *ListCollectionsOptionsBuilder) SetAuthorizedCollections(b bool) *ListCollectionsOptionsBuilder { lc.Opts = append(lc.Opts, func(opts *ListCollectionsOptions) error { opts.AuthorizedCollections = &b diff --git a/vendor/go.mongodb.org/mongo-driver/v2/version/version.go b/vendor/go.mongodb.org/mongo-driver/v2/version/version.go index 2b483845..ab026bd1 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/version/version.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/version/version.go @@ -11,4 +11,4 @@ package version // Driver is the current version of the driver. -var Driver = "2.3.1" +var Driver = "2.4.0" diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation.go index 57ec762e..3e720eba 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation.go @@ -1133,9 +1133,11 @@ func (op Operation) readWireMessage(ctx context.Context, conn *mnet.Connection) // decode res, err := op.decodeResult(opcode, rem) - // Update cluster/operation time and recovery tokens before handling the error to ensure we're properly updating - // everything. - op.updateClusterTimes(res) + // When a cluster clock is given, update cluster/operation time and recovery tokens before handling the error + // to ensure we're properly updating everything. + if op.Clock != nil { + op.updateClusterTimes(res) + } op.updateOperationTime(res) op.Client.UpdateRecoveryToken(bson.Raw(res)) @@ -1729,7 +1731,10 @@ func (op Operation) addClusterTime(dst []byte, desc description.SelectedServer) if (clock == nil && client == nil) || !sessionsSupported(desc.WireVersion) { return dst } - clusterTime := clock.GetClusterTime() + var clusterTime bson.Raw + if clock != nil { + clusterTime = clock.GetClusterTime() + } if client != nil { clusterTime = session.MaxClusterTime(clusterTime, client.ClusterTime) } @@ -1741,7 +1746,6 @@ func (op Operation) addClusterTime(dst []byte, desc description.SelectedServer) return dst } return append(bsoncore.AppendHeader(dst, bsoncore.Type(val.Type), "$clusterTime"), val.Value...) - // return bsoncore.AppendDocumentElement(dst, "$clusterTime", clusterTime) } // calculateMaxTimeMS calculates the value of the 'maxTimeMS' field to potentially append diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/find_and_modify.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/find_and_modify.go index 09205681..0b3da9c4 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/find_and_modify.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/find_and_modify.go @@ -51,6 +51,7 @@ type FindAndModify struct { let bsoncore.Document timeout *time.Duration rawData *bool + additionalCmd bson.D result FindAndModifyResult } @@ -216,6 +217,13 @@ func (fam *FindAndModify) command(dst []byte, desc description.SelectedServer) ( if fam.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { dst = bsoncore.AppendBooleanElement(dst, "rawData", *fam.rawData) } + if len(fam.additionalCmd) > 0 { + doc, err := bson.Marshal(fam.additionalCmd) + if err != nil { + return nil, err + } + dst = append(dst, doc[4:len(doc)-1]...) + } return dst, nil } @@ -491,3 +499,13 @@ func (fam *FindAndModify) RawData(rawData bool) *FindAndModify { fam.rawData = &rawData return fam } + +// AdditionalCmd sets additional command fields to be attached. +func (fam *FindAndModify) AdditionalCmd(d bson.D) *FindAndModify { + if fam == nil { + fam = new(FindAndModify) + } + + fam.additionalCmd = d + return fam +} diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/insert.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/insert.go index 57d461ae..d4f01e6b 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/insert.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/insert.go @@ -12,6 +12,7 @@ import ( "fmt" "time" + "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/event" "go.mongodb.org/mongo-driver/v2/internal/driverutil" "go.mongodb.org/mongo-driver/v2/internal/logger" @@ -43,6 +44,7 @@ type Insert struct { serverAPI *driver.ServerAPIOptions timeout *time.Duration rawData *bool + additionalCmd bson.D logger *logger.Logger } @@ -137,6 +139,13 @@ func (i *Insert) command(dst []byte, desc description.SelectedServer) ([]byte, e if i.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { dst = bsoncore.AppendBooleanElement(dst, "rawData", *i.rawData) } + if len(i.additionalCmd) > 0 { + doc, err := bson.Marshal(i.additionalCmd) + if err != nil { + return nil, err + } + dst = append(dst, doc[4:len(doc)-1]...) + } return dst, nil } @@ -333,3 +342,13 @@ func (i *Insert) RawData(rawData bool) *Insert { i.rawData = &rawData return i } + +// AdditionalCmd sets additional command fields to be attached. +func (i *Insert) AdditionalCmd(d bson.D) *Insert { + if i == nil { + i = new(Insert) + } + + i.additionalCmd = d + return i +} diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/update.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/update.go index 00e193ef..07848a54 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/update.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/operation/update.go @@ -47,6 +47,7 @@ type Update struct { let bsoncore.Document timeout *time.Duration rawData *bool + additionalCmd bson.D logger *logger.Logger } @@ -208,6 +209,13 @@ func (u *Update) command(dst []byte, desc description.SelectedServer) ([]byte, e if u.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { dst = bsoncore.AppendBooleanElement(dst, "rawData", *u.rawData) } + if len(u.additionalCmd) > 0 { + doc, err := bson.Marshal(u.additionalCmd) + if err != nil { + return nil, err + } + dst = append(dst, doc[4:len(doc)-1]...) + } return dst, nil } @@ -437,3 +445,13 @@ func (u *Update) RawData(rawData bool) *Update { u.rawData = &rawData return u } + +// AdditionalCmd sets additional command fields to be attached. +func (u *Update) AdditionalCmd(d bson.D) *Update { + if u == nil { + u = new(Update) + } + + u.additionalCmd = d + return u +} diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/fsm.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/fsm.go index 530b2169..26e2fc32 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/fsm.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/fsm.go @@ -20,7 +20,7 @@ import ( var ( // MinSupportedMongoDBVersion is the version string for the lowest MongoDB version supported by the driver. - MinSupportedMongoDBVersion = "4.0" + MinSupportedMongoDBVersion = "4.2" // SupportedWireVersions is the range of wire versions supported by the driver. SupportedWireVersions = driverutil.NewVersionRange(driverutil.MinWireVersion, driverutil.MaxWireVersion) diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server.go index 90cee89e..a408aee5 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server.go @@ -807,9 +807,18 @@ func (s *Server) createConnection() *connection { opts := copyConnectionOpts(s.cfg.connectionOpts) opts = append(opts, WithHandshaker(func(Handshaker) Handshaker { - return operation.NewHello().AppName(s.cfg.appname).Compressors(s.cfg.compressionOpts). - ServerAPI(s.cfg.serverAPI).OuterLibraryName(s.cfg.outerLibraryName). - OuterLibraryVersion(s.cfg.outerLibraryVersion).OuterLibraryPlatform(s.cfg.outerLibraryPlatform) + handshaker := operation.NewHello().AppName(s.cfg.appname).Compressors(s.cfg.compressionOpts). + ServerAPI(s.cfg.serverAPI) + + if s.cfg.driverInfo != nil { + driverInfo := s.cfg.driverInfo.Load() + if driverInfo != nil { + handshaker = handshaker.OuterLibraryName(driverInfo.Name).OuterLibraryVersion(driverInfo.Version). + OuterLibraryPlatform(driverInfo.Platform) + } + } + + return handshaker }), // Override any monitors specified in options with nil to avoid monitoring heartbeats. WithMonitor(func(*event.CommandMonitor) *event.CommandMonitor { return nil }), @@ -842,7 +851,6 @@ func (s *Server) setupHeartbeatConnection(ctx context.Context) error { func (s *Server) createBaseOperation(conn *mnet.Connection) *operation.Hello { return operation. NewHello(). - ClusterClock(s.cfg.clock). Deployment(driver.SingleConnectionDeployment{C: conn}). ServerAPI(s.cfg.serverAPI) } diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server_options.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server_options.go index 490834cb..297cafc7 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server_options.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/server_options.go @@ -7,11 +7,13 @@ package topology import ( + "sync/atomic" "time" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/event" "go.mongodb.org/mongo-driver/v2/internal/logger" + "go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/x/mongo/driver" "go.mongodb.org/mongo-driver/v2/x/mongo/driver/connstring" "go.mongodb.org/mongo-driver/v2/x/mongo/driver/session" @@ -32,6 +34,7 @@ type serverConfig struct { monitoringDisabled bool serverAPI *driver.ServerAPIOptions loadBalanced bool + driverInfo *atomic.Pointer[options.DriverInfo] // Connection pool options. maxConns uint64 @@ -41,11 +44,6 @@ type serverConfig struct { logger *logger.Logger poolMaxIdleTime time.Duration poolMaintainInterval time.Duration - - // Fields provided by a library that wraps the Go Driver. - outerLibraryName string - outerLibraryVersion string - outerLibraryPlatform string } func newServerConfig(connectTimeout time.Duration, opts ...ServerOption) *serverConfig { @@ -101,27 +99,12 @@ func WithServerAppName(fn func(string) string) ServerOption { } } -// WithOuterLibraryName configures the name for the outer library to include -// in the drivers section of the handshake metadata. -func WithOuterLibraryName(fn func(string) string) ServerOption { - return func(cfg *serverConfig) { - cfg.outerLibraryName = fn(cfg.outerLibraryName) - } -} - -// WithOuterLibraryVersion configures the version for the outer library to -// include in the drivers section of the handshake metadata. -func WithOuterLibraryVersion(fn func(string) string) ServerOption { - return func(cfg *serverConfig) { - cfg.outerLibraryVersion = fn(cfg.outerLibraryVersion) - } -} - -// WithOuterLibraryPlatform configures the platform for the outer library to -// include in the platform section of the handshake metadata. -func WithOuterLibraryPlatform(fn func(string) string) ServerOption { +// WithDriverInfo sets at atomic pointer to the server configuration, which will +// be used to create the "driver" section on handshake commands. An atomic +// pointer is used so that the driver info can be updated concurrently. +func WithDriverInfo(info *atomic.Pointer[options.DriverInfo]) ServerOption { return func(cfg *serverConfig) { - cfg.outerLibraryPlatform = fn(cfg.outerLibraryPlatform) + cfg.driverInfo = info } } diff --git a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/topology_options.go b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/topology_options.go index 2ddc7434..2d53805d 100644 --- a/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/topology_options.go +++ b/vendor/go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology/topology_options.go @@ -11,6 +11,7 @@ import ( "crypto/tls" "fmt" "net/http" + "sync/atomic" "time" "go.mongodb.org/mongo-driver/v2/event" @@ -139,14 +140,56 @@ func NewConfig(opts *options.ClientOptions, clock *session.ClusterClock) (*Confi return nil, fmt.Errorf("error creating authenticator: %w", err) } } - return NewConfigFromOptionsWithAuthenticator(opts, clock, authenticator) + return NewAuthenticatorConfig(authenticator, + WithAuthConfigClock(clock), + WithAuthConfigClientOptions(opts), + ) +} + +type authConfigOptions struct { + clock *session.ClusterClock + opts *options.ClientOptions + driverInfo *atomic.Pointer[options.DriverInfo] +} + +// AuthConfigOption is a function that configures authConfigOptions. +type AuthConfigOption func(*authConfigOptions) + +// WithAuthConfigClock sets the cluster clock in authConfigOptions. +func WithAuthConfigClock(clock *session.ClusterClock) AuthConfigOption { + return func(co *authConfigOptions) { + co.clock = clock + } +} + +// WithAuthConfigClientOptions sets the client options in authConfigOptions. +func WithAuthConfigClientOptions(opts *options.ClientOptions) AuthConfigOption { + return func(co *authConfigOptions) { + co.opts = opts + } } -// NewConfigFromOptionsWithAuthenticator will translate data from client options into a +// WithAuthConfigDriverInfo sets the driver info in authConfigOptions. +func WithAuthConfigDriverInfo(driverInfo *atomic.Pointer[options.DriverInfo]) AuthConfigOption { + return func(co *authConfigOptions) { + co.driverInfo = driverInfo + } +} + +// NewAuthenticatorConfig will translate data from client options into a // topology config for building non-default deployments. Server and topology // options are not honored if a custom deployment is used. It uses a passed in // authenticator to authenticate the connection. -func NewConfigFromOptionsWithAuthenticator(opts *options.ClientOptions, clock *session.ClusterClock, authenticator driver.Authenticator) (*Config, error) { +func NewAuthenticatorConfig(authenticator driver.Authenticator, clientOpts ...AuthConfigOption) (*Config, error) { + settings := authConfigOptions{} + for _, apply := range clientOpts { + apply(&settings) + } + + opts := settings.opts + clock := settings.clock + driverInfo := settings.driverInfo + var serverAPI *driver.ServerAPIOptions if err := opts.Validate(); err != nil { @@ -200,23 +243,8 @@ func NewConfigFromOptionsWithAuthenticator(opts *options.ClientOptions, clock *s })) } - var outerLibraryName, outerLibraryVersion, outerLibraryPlatform string - if opts.DriverInfo != nil { - outerLibraryName = opts.DriverInfo.Name - outerLibraryVersion = opts.DriverInfo.Version - outerLibraryPlatform = opts.DriverInfo.Platform - - serverOpts = append(serverOpts, WithOuterLibraryName(func(string) string { - return outerLibraryName - })) - - serverOpts = append(serverOpts, WithOuterLibraryVersion(func(string) string { - return outerLibraryVersion - })) - - serverOpts = append(serverOpts, WithOuterLibraryPlatform(func(string) string { - return outerLibraryPlatform - })) + if driverInfo != nil { + serverOpts = append(serverOpts, WithDriverInfo(driverInfo)) } // Compressors & ZlibLevel @@ -256,46 +284,57 @@ func NewConfigFromOptionsWithAuthenticator(opts *options.ClientOptions, clock *s // Handshaker var handshaker func(driver.Handshaker) driver.Handshaker if authenticator != nil { - handshakeOpts := &auth.HandshakeOptions{ - AppName: appName, - Authenticator: authenticator, - Compressors: comps, - ServerAPI: serverAPI, - LoadBalanced: loadBalanced, - ClusterClock: clock, - OuterLibraryName: outerLibraryName, - OuterLibraryVersion: outerLibraryVersion, - OuterLibraryPlatform: outerLibraryPlatform, - } + handshaker = func(driver.Handshaker) driver.Handshaker { + handshakeOpts := &auth.HandshakeOptions{ + AppName: appName, + Authenticator: authenticator, + Compressors: comps, + ServerAPI: serverAPI, + LoadBalanced: loadBalanced, + ClusterClock: clock, + } - if opts.Auth.AuthMechanism == "" { - // Required for SASL mechanism negotiation during handshake - handshakeOpts.DBUser = opts.Auth.AuthSource + "." + opts.Auth.Username - } - if a := optionsutil.Value(opts.Custom, "authenticateToAnything"); a != nil { - if v, ok := a.(bool); ok && v { + if opts.Auth.AuthMechanism == "" { + // Required for SASL mechanism negotiation during handshake + handshakeOpts.DBUser = opts.Auth.AuthSource + "." + opts.Auth.Username + } + + if auth, ok := optionsutil.Value(opts.Custom, "authenticateToAnything").(bool); ok && auth { // Authenticate arbiters handshakeOpts.PerformAuthentication = func(_ description.Server) bool { return true } } - } - handshaker = func(driver.Handshaker) driver.Handshaker { + if driverInfo != nil { + if di := driverInfo.Load(); di != nil { + handshakeOpts.OuterLibraryName = di.Name + handshakeOpts.OuterLibraryVersion = di.Version + handshakeOpts.OuterLibraryPlatform = di.Platform + } + } + return auth.Handshaker(nil, handshakeOpts) } } else { handshaker = func(driver.Handshaker) driver.Handshaker { - return operation.NewHello(). + op := operation.NewHello(). AppName(appName). Compressors(comps). ClusterClock(clock). ServerAPI(serverAPI). - LoadBalanced(loadBalanced). - OuterLibraryName(outerLibraryName). - OuterLibraryVersion(outerLibraryVersion). - OuterLibraryPlatform(outerLibraryPlatform) + LoadBalanced(loadBalanced) + + if driverInfo != nil { + if di := driverInfo.Load(); di != nil { + op = op.OuterLibraryName(di.Name). + OuterLibraryVersion(di.Version). + OuterLibraryPlatform(di.Platform) + } + } + + return op } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 4a3bc735..21f10df6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -240,7 +240,7 @@ github.com/xdg-go/stringprep # github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 ## explicit; go 1.17 github.com/youmark/pkcs8 -# go.mongodb.org/mongo-driver/v2 v2.3.1 +# go.mongodb.org/mongo-driver/v2 v2.4.0 ## explicit; go 1.19 go.mongodb.org/mongo-driver/v2/bson go.mongodb.org/mongo-driver/v2/event From 56dd410a0c78ea4da4309fcf20c7ec95122eab3e Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 8 Dec 2025 15:03:17 -0500 Subject: [PATCH 2/4] init --- internal/verifier/driver_topology.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 internal/verifier/driver_topology.go diff --git a/internal/verifier/driver_topology.go b/internal/verifier/driver_topology.go new file mode 100644 index 00000000..96332360 --- /dev/null +++ b/internal/verifier/driver_topology.go @@ -0,0 +1,9 @@ +package verifier + +import "go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology" + +func init() { + topology.MinSupportedMongoDBVersion = "4.0" + + topology.SupportedWireVersions.Min = 7 // 4.0 +} From a9cb719dff58ea7f5cf03486fea22655571819f2 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 8 Dec 2025 15:30:07 -0500 Subject: [PATCH 3/4] rename --- .../v2/internal/decimal128/decimal128.go | 117 ++++++++++++++++++ .../mongo-driver/v2/mongo/mongointernal.go | 41 ++++++ 2 files changed, 158 insertions(+) create mode 100644 vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decimal128.go create mode 100644 vendor/go.mongodb.org/mongo-driver/v2/mongo/mongointernal.go diff --git a/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decimal128.go b/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decimal128.go new file mode 100644 index 00000000..2767e445 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/v2/internal/decimal128/decimal128.go @@ -0,0 +1,117 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package decimal128 + +import ( + "strconv" +) + +// These constants are the maximum and minimum values for the exponent field in a decimal128 value. +const ( + MaxDecimal128Exp = 6111 + MinDecimal128Exp = -6176 +) + +func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) { + div64 := uint64(div) + a := h >> 32 + aq := a / div64 + ar := a % div64 + b := ar<<32 + h&(1<<32-1) + bq := b / div64 + br := b % div64 + c := br<<32 + l>>32 + cq := c / div64 + cr := c % div64 + d := cr<<32 + l&(1<<32-1) + dq := d / div64 + dr := d % div64 + return (aq<<32 | bq), (cq<<32 | dq), uint32(dr) +} + +// String returns a string representation of the decimal value. +func String(h, l uint64) string { + var posSign int // positive sign + var exp int // exponent + var high, low uint64 // significand high/low + + if h>>63&1 == 0 { + posSign = 1 + } + + switch h >> 58 & (1<<5 - 1) { + case 0x1F: + return "NaN" + case 0x1E: + return "-Infinity"[posSign:] + } + + low = l + if h>>61&3 == 3 { + // Bits: 1*sign 2*ignored 14*exponent 111*significand. + // Implicit 0b100 prefix in significand. + exp = int(h >> 47 & (1<<14 - 1)) + // Spec says all of these values are out of range. + high, low = 0, 0 + } else { + // Bits: 1*sign 14*exponent 113*significand + exp = int(h >> 49 & (1<<14 - 1)) + high = h & (1<<49 - 1) + } + exp += MinDecimal128Exp + + // Would be handled by the logic below, but that's trivial and common. + if high == 0 && low == 0 && exp == 0 { + return "-0"[posSign:] + } + + var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero. + var last = len(repr) + var i = len(repr) + var dot = len(repr) + exp + var rem uint32 +Loop: + for d9 := 0; d9 < 5; d9++ { + high, low, rem = divmod(high, low, 1e9) + for d1 := 0; d1 < 9; d1++ { + // Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc. + if i < len(repr) && (dot == i || low == 0 && high == 0 && rem > 0 && rem < 10 && (dot < i-6 || exp > 0)) { + exp += len(repr) - i + i-- + repr[i] = '.' + last = i - 1 + dot = len(repr) // Unmark. + } + c := '0' + byte(rem%10) + rem /= 10 + i-- + repr[i] = c + // Handle "0E+3", "1E+3", etc. + if low == 0 && high == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || exp > 0) { + last = i + break Loop + } + if c != '0' { + last = i + } + // Break early. Works without it, but why. + if dot > i && low == 0 && high == 0 && rem == 0 { + break Loop + } + } + } + repr[last-1] = '-' + last-- + + if exp > 0 { + return string(repr[last+posSign:]) + "E+" + strconv.Itoa(exp) + } + if exp < 0 { + return string(repr[last+posSign:]) + "E" + strconv.Itoa(exp) + } + return string(repr[last+posSign:]) +} diff --git a/vendor/go.mongodb.org/mongo-driver/v2/mongo/mongointernal.go b/vendor/go.mongodb.org/mongo-driver/v2/mongo/mongointernal.go new file mode 100644 index 00000000..31195d37 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/v2/mongo/mongointernal.go @@ -0,0 +1,41 @@ +// Copyright (C) MongoDB, Inc. 2025-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +//go:build mongointernal + +package mongo + +import ( + "time" + + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/x/mongo/driver/session" +) + +// NewSessionWithLSID returns a Session with the given sessionID document. The +// sessionID is a BSON document with key "id" containing a 16-byte UUID (binary +// subtype 4). +// +// Sessions returned by NewSessionWithLSID are never added to the driver's +// session pool. Calling "EndSession" or "ClientSession.SetServer" on a Session +// returned by NewSessionWithLSID will panic. +// +// NewSessionWithLSID is intended only for internal use and may be changed or +// removed at any time. +func NewSessionWithLSID(client *Client, sessionID bson.Raw) *Session { + return &Session{ + clientSession: &session.Client{ + Server: &session.Server{ + SessionID: bsoncore.Document(sessionID), + LastUsed: time.Now(), + }, + ClientID: client.id, + }, + client: client, + deployment: client.deployment, + } +} From a9617d1bfcfc99557d46b365e2981e177d50cae4 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 8 Dec 2025 16:15:10 -0500 Subject: [PATCH 4/4] add comment --- internal/verifier/driver_topology.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/verifier/driver_topology.go b/internal/verifier/driver_topology.go index 96332360..7ec52967 100644 --- a/internal/verifier/driver_topology.go +++ b/internal/verifier/driver_topology.go @@ -3,7 +3,10 @@ package verifier import "go.mongodb.org/mongo-driver/v2/x/mongo/driver/topology" func init() { - topology.MinSupportedMongoDBVersion = "4.0" + // Version 2.4 of the driver dropped support for server 4.0. + // This is a workaround from GODRIVER-3701 that the maintainers + // indicate will preserve the needed functionality. + topology.MinSupportedMongoDBVersion = "4.0" topology.SupportedWireVersions.Min = 7 // 4.0 }