Skip to content

Commit 50523c2

Browse files
authored
GODRIVER-3037 Support internal-only options. (#2023)
1 parent 8c453d2 commit 50523c2

File tree

6 files changed

+165
-2
lines changed

6 files changed

+165
-2
lines changed

internal/cmd/compilecheck/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ import (
1212
"go.mongodb.org/mongo-driver/v2/bson"
1313
"go.mongodb.org/mongo-driver/v2/mongo"
1414
"go.mongodb.org/mongo-driver/v2/mongo/options"
15+
"go.mongodb.org/mongo-driver/v2/x/mongo/driver/xoptions"
1516
)
1617

1718
func main() {
19+
opts := options.Client()
20+
xoptions.SetInternalClientOptions(opts, "foo", "bar")
21+
1822
_, _ = mongo.Connect(options.Client())
1923
fmt.Println(bson.D{{Key: "key", Value: "value"}})
2024
}

internal/options/options.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (C) MongoDB, Inc. 2025-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package options
8+
9+
// Options stores internal options.
10+
type Options struct {
11+
values map[string]any
12+
}
13+
14+
// WithValue sets an option value with the associated key.
15+
func WithValue(opts Options, key string, option any) Options {
16+
if opts.values == nil {
17+
opts.values = make(map[string]any)
18+
}
19+
opts.values[key] = option
20+
return opts
21+
}
22+
23+
// Value returns the value associated with the options for key.
24+
func Value(opts Options, key string) any {
25+
if opts.values == nil {
26+
return nil
27+
}
28+
if val, ok := opts.values[key]; ok {
29+
return val
30+
}
31+
return nil
32+
}
33+
34+
// Equal compares two Options instances for equality.
35+
func Equal(opts1, opts2 Options) bool {
36+
if len(opts1.values) != len(opts2.values) {
37+
return false
38+
}
39+
for key, val1 := range opts1.values {
40+
if val2, ok := opts2.values[key]; !ok || val1 != val2 {
41+
return false
42+
}
43+
}
44+
return true
45+
}

mongo/options/clientoptions.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"go.mongodb.org/mongo-driver/v2/bson"
2727
"go.mongodb.org/mongo-driver/v2/event"
2828
"go.mongodb.org/mongo-driver/v2/internal/httputil"
29+
"go.mongodb.org/mongo-driver/v2/internal/options"
2930
"go.mongodb.org/mongo-driver/v2/mongo/readconcern"
3031
"go.mongodb.org/mongo-driver/v2/mongo/readpref"
3132
"go.mongodb.org/mongo-driver/v2/mongo/writeconcern"
@@ -286,14 +287,22 @@ type ClientOptions struct {
286287
// encryption.
287288
//
288289
// Deprecated: This option is for internal use only and should not be set (see GODRIVER-2149). It may be
289-
// changed or removed in any release.
290+
// changed in any release. This option will be removed in 3.0 and replaced with the Custom options.Options
291+
// pattern: SetInternalClientOptions(clientOptions, "crypt", myCrypt)
290292
Crypt driver.Crypt
291293

292294
// Deployment specifies a custom deployment to use for the new Client.
293295
//
296+
// Deprecated: This option is for internal use only and should not be set. It may be changed in any release.
297+
// This option will be removed in 3.0 and replaced with the Custom options.Options pattern:
298+
// SetInternalClientOptions(clientOptions, "deployment", myDeployment)
299+
Deployment driver.Deployment
300+
301+
// Custom specifies internal options for the new Client.
302+
//
294303
// Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any
295304
// release.
296-
Deployment driver.Deployment
305+
Custom options.Options
297306

298307
connString *connstring.ConnString
299308
err error

mongo/options/clientoptions_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"go.mongodb.org/mongo-driver/v2/event"
2828
"go.mongodb.org/mongo-driver/v2/internal/assert"
2929
"go.mongodb.org/mongo-driver/v2/internal/httputil"
30+
"go.mongodb.org/mongo-driver/v2/internal/options"
3031
"go.mongodb.org/mongo-driver/v2/internal/ptrutil"
3132
"go.mongodb.org/mongo-driver/v2/mongo/readconcern"
3233
"go.mongodb.org/mongo-driver/v2/mongo/readpref"
@@ -156,6 +157,7 @@ func TestClientOptions(t *testing.T) {
156157
cmp.Comparer(func(r1, r2 *bson.Registry) bool { return r1 == r2 }),
157158
cmp.Comparer(func(cfg1, cfg2 *tls.Config) bool { return cfg1 == cfg2 }),
158159
cmp.Comparer(func(fp1, fp2 *event.PoolMonitor) bool { return fp1 == fp2 }),
160+
cmp.Comparer(options.Equal),
159161
cmp.AllowUnexported(ClientOptions{}),
160162
cmpopts.IgnoreFields(http.Client{}, "Transport"),
161163
); diff != "" {
@@ -1253,6 +1255,7 @@ func TestApplyURI(t *testing.T) {
12531255
cmp.Comparer(func(r1, r2 *bson.Registry) bool { return r1 == r2 }),
12541256
cmp.Comparer(compareTLSConfig),
12551257
cmp.Comparer(compareErrors),
1258+
cmp.Comparer(options.Equal),
12561259
cmpopts.SortSlices(stringLess),
12571260
cmpopts.IgnoreFields(connstring.ConnString{}, "SSLClientCertificateKeyPassword"),
12581261
cmpopts.IgnoreFields(http.Client{}, "Transport"),

x/mongo/driver/xoptions/options.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (C) MongoDB, Inc. 2025-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package xoptions
8+
9+
import (
10+
"fmt"
11+
12+
"go.mongodb.org/mongo-driver/v2/mongo/options"
13+
"go.mongodb.org/mongo-driver/v2/x/mongo/driver"
14+
)
15+
16+
// SetInternalClientOptions sets internal options for ClientOptions.
17+
//
18+
// Deprecated: This function is for internal use only. It may be changed or removed in any release.
19+
func SetInternalClientOptions(opts *options.ClientOptions, key string, option any) error {
20+
const typeErr = "unexpected type for %s"
21+
switch key {
22+
case "crypt":
23+
c, ok := option.(driver.Crypt)
24+
if !ok {
25+
return fmt.Errorf(typeErr, key)
26+
}
27+
opts.Crypt = c
28+
case "deployment":
29+
d, ok := option.(driver.Deployment)
30+
if !ok {
31+
return fmt.Errorf(typeErr, key)
32+
}
33+
opts.Deployment = d
34+
default:
35+
return fmt.Errorf("unsupported option: %s", key)
36+
}
37+
return nil
38+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (C) MongoDB, Inc. 2025-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package xoptions
8+
9+
import (
10+
"testing"
11+
12+
"go.mongodb.org/mongo-driver/v2/internal/require"
13+
"go.mongodb.org/mongo-driver/v2/mongo/options"
14+
"go.mongodb.org/mongo-driver/v2/x/mongo/driver"
15+
"go.mongodb.org/mongo-driver/v2/x/mongo/driver/drivertest"
16+
)
17+
18+
func TestSetInternalClientOptions(t *testing.T) {
19+
t.Parallel()
20+
21+
t.Run("set crypt", func(t *testing.T) {
22+
t.Parallel()
23+
24+
c := driver.NewCrypt(&driver.CryptOptions{})
25+
opts := options.Client()
26+
err := SetInternalClientOptions(opts, "crypt", c)
27+
require.NoError(t, err, "error setting crypt: %v", err)
28+
require.Equal(t, c, opts.Crypt, "expected %v, got %v", c, opts.Crypt)
29+
})
30+
31+
t.Run("set crypt - wrong type", func(t *testing.T) {
32+
t.Parallel()
33+
34+
opts := options.Client()
35+
err := SetInternalClientOptions(opts, "crypt", &drivertest.MockDeployment{})
36+
require.EqualError(t, err, "unexpected type for crypt")
37+
})
38+
39+
t.Run("set deployment", func(t *testing.T) {
40+
t.Parallel()
41+
42+
d := &drivertest.MockDeployment{}
43+
opts := options.Client()
44+
err := SetInternalClientOptions(opts, "deployment", d)
45+
require.NoError(t, err, "error setting deployment: %v", err)
46+
require.Equal(t, d, opts.Deployment, "expected %v, got %v", d, opts.Deployment)
47+
})
48+
49+
t.Run("set deployment - wrong type", func(t *testing.T) {
50+
t.Parallel()
51+
52+
opts := options.Client()
53+
err := SetInternalClientOptions(opts, "deployment", driver.NewCrypt(&driver.CryptOptions{}))
54+
require.EqualError(t, err, "unexpected type for deployment")
55+
})
56+
57+
t.Run("set unsupported option", func(t *testing.T) {
58+
t.Parallel()
59+
60+
opts := options.Client()
61+
err := SetInternalClientOptions(opts, "unsupported", "unsupported")
62+
require.EqualError(t, err, "unsupported option: unsupported")
63+
})
64+
}

0 commit comments

Comments
 (0)