Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion etc/install-libmongocrypt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This script installs libmongocrypt into an "install" directory.
set -eux

LIBMONGOCRYPT_TAG="1.12.0"
LIBMONGOCRYPT_TAG="1.15.1"

# Install libmongocrypt based on OS.
if [ "Windows_NT" = "${OS:-}" ]; then
Expand Down
6 changes: 0 additions & 6 deletions internal/integration/mtest/mongotest.go
Original file line number Diff line number Diff line change
Expand Up @@ -797,12 +797,6 @@ func verifyRunOnBlockConstraint(rob RunOnBlock) error {
return err
}

// TODO(GODRIVER-3486): Once auto encryption is supported by the unified test
// format,this check should be removed.
if rob.CSFLEEnabled() && rob.CSFLE.Options != nil {
return fmt.Errorf("auto encryption required (GODRIVER-3486)")
}

if rob.CSFLEEnabled() && !IsCSFLEEnabled() {
return fmt.Errorf("runOnBlock requires CSFLE to be enabled. Build with the cse tag to enable")
} else if !rob.CSFLEEnabled() && IsCSFLEEnabled() {
Expand Down
84 changes: 84 additions & 0 deletions internal/integration/unified/client_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package unified

import (
"context"
"crypto/tls"
"fmt"
"strings"
"sync"
Expand Down Expand Up @@ -217,6 +218,13 @@ func newClientEntity(ctx context.Context, em *EntityMap, entityOptions *entityOp
} else {
integtest.AddTestServerAPIVersion(clientOpts)
}
if entityOptions.AutoEncryptOpts != nil {
aeo, err := createAutoEncryptionOptions(entityOptions.AutoEncryptOpts)
if err != nil {
return nil, fmt.Errorf("error parsing auto encryption options: %w", err)
}
clientOpts.SetAutoEncryptionOptions(aeo)
}
for _, cmd := range entityOptions.IgnoredCommands {
entity.ignoredCommands[cmd] = struct{}{}
}
Expand Down Expand Up @@ -251,6 +259,82 @@ func getURIForClient(opts *entityOptions) string {
}
}

func createAutoEncryptionOptions(opts bson.Raw) (*options.AutoEncryptionOptions, error) {
aeo := options.AutoEncryption()
var kvnsFound bool
elems, err := opts.Elements()
if err != nil {
return nil, err
}

for _, elem := range elems {
name := elem.Key()
opt := elem.Value()

switch name {
case "kmsProviders":
providers := make(map[string]map[string]any)
elems, err := opt.Document().Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
opt := elem.Value().Document()
provider, err := getKmsProvider(key, opt)
if err != nil {
return nil, err
}
if provider == nil {
continue
}
providers[key] = provider
if key == "kmip" && tlsClientCertificateKeyFile != "" && tlsCAFile != "" {
cfg, err := options.BuildTLSConfig(map[string]any{
"tlsCertificateKeyFile": tlsClientCertificateKeyFile,
"tlsCAFile": tlsCAFile,
})
if err != nil {
return nil, fmt.Errorf("error constructing tls config: %w", err)
}
aeo.SetTLSConfig(map[string]*tls.Config{
"kmip": cfg,
})
}
}
aeo.SetKmsProviders(providers)
case "schemaMap":
var schemaMap map[string]any
err := bson.Unmarshal(opt.Document(), &schemaMap)
if err != nil {
return nil, fmt.Errorf("error creating schema map: %v", err)
}
aeo.SetSchemaMap(schemaMap)
case "keyVaultNamespace":
kvnsFound = true
aeo.SetKeyVaultNamespace(opt.StringValue())
case "bypassAutoEncryption":
aeo.SetBypassAutoEncryption(opt.Boolean())
case "encryptedFieldsMap":
var encryptedFieldsMap map[string]any
err := bson.Unmarshal(opt.Document(), &encryptedFieldsMap)
if err != nil {
return nil, fmt.Errorf("error creating encryptedFieldsMap: %v", err)
}
aeo.SetEncryptedFieldsMap(encryptedFieldsMap)
case "bypassQueryAnalysis":
aeo.SetBypassQueryAnalysis(opt.Boolean())
default:
return nil, fmt.Errorf("unrecognized option: %v", name)
}
}
if !kvnsFound {
aeo.SetKeyVaultNamespace("keyvault.datakeys")
}

return aeo, nil
}

// disconnect disconnects the client associated with this entity. It is an
// idempotent operation, unlike the mongo client's disconnect method. This
// property will help avoid unnecessary errors when calling disconnect on a
Expand Down
28 changes: 18 additions & 10 deletions internal/integration/unified/collection_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ type collectionData struct {
}

type createOptions struct {
Capped *bool `bson:"capped"`
SizeInBytes *int64 `bson:"size"`
Capped *bool `bson:"capped"`
SizeInBytes *int64 `bson:"size"`
EncryptedFields bson.Raw `bson:"encryptedFields"`
Validator bson.Raw `bson:"validator"`
}

// createCollection configures the collection represented by the receiver using the internal client. This function
Expand All @@ -49,14 +51,18 @@ func (c *collectionData) createCollection(ctx context.Context) error {
if c.Options.SizeInBytes != nil {
createOpts = createOpts.SetSizeInBytes(*c.Options.SizeInBytes)
}
if c.Options.EncryptedFields != nil {
createOpts = createOpts.SetEncryptedFields(c.Options.EncryptedFields)
}
if c.Options.Validator != nil {
createOpts = createOpts.SetValidator(c.Options.Validator)
}

if err := db.CreateCollection(ctx, c.CollectionName, createOpts); err != nil {
return fmt.Errorf("error creating collection: %w", err)
}
}

// If neither documents nor options are provided, still create the collection with write concern "majority".
if len(c.Documents) == 0 && c.Options == nil {
} else {
// If options are provided, still create the collection with write concern "majority".
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "If options are provided" but this is in the else block where c.Options is nil. The comment should say "If no options are provided" to accurately describe this code path.

Suggested change
// If options are provided, still create the collection with write concern "majority".
// If no options are provided, still create the collection with write concern "majority".

Copilot uses AI. Check for mistakes.
// The write concern has to be manually specified in the command document because RunCommand does not honor
// the database's write concern.
create := bson.D{
Expand All @@ -68,13 +74,15 @@ func (c *collectionData) createCollection(ctx context.Context) error {
if err := db.RunCommand(ctx, create).Err(); err != nil {
return fmt.Errorf("error creating collection: %w", err)
}
return nil
}

docs := bsonutil.RawToInterfaces(c.Documents...)
if _, err := coll.InsertMany(ctx, docs); err != nil {
return fmt.Errorf("error inserting data: %w", err)
if len(c.Documents) != 0 {
docs := bsonutil.RawToInterfaces(c.Documents...)
if _, err := coll.InsertMany(ctx, docs); err != nil {
return fmt.Errorf("error inserting data: %w", err)
}
}

return nil
}

Expand Down
10 changes: 9 additions & 1 deletion internal/integration/unified/database_operation_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ func executeCreateCollection(ctx context.Context, operation *operation) (*operat
cco.SetTimeSeriesOptions(tso)
case "clusteredIndex":
cco.SetClusteredIndex(val.Document())
case "validator":
cco.SetValidator(val.Document())
case "encryptedFields":
cco.SetEncryptedFields(val.Document())
default:
return nil, fmt.Errorf("unrecognized createCollection option %q", key)
}
Expand Down Expand Up @@ -156,13 +160,17 @@ func executeDropCollection(ctx context.Context, operation *operation) (*operatio
return nil, err
}

dco := options.DropCollection()

var collName string
elems, _ := operation.Arguments.Elements()
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "encryptedFields":
dco.SetEncryptedFields(val.Document())
case "collection":
collName = val.StringValue()
default:
Expand All @@ -173,7 +181,7 @@ func executeDropCollection(ctx context.Context, operation *operation) (*operatio
return nil, newMissingArgumentError("collection")
}

err = db.Collection(collName).Drop(ctx)
err = db.Collection(collName).Drop(ctx, dco)
return newErrorResult(err), nil
}

Expand Down
Loading
Loading