From 6b13ae1d91987f2f736107cc9d1247ac6f7bd430 Mon Sep 17 00:00:00 2001 From: Ross Lawley <420+rozza@users.noreply.github.com> Date: Wed, 7 May 2025 08:58:59 +0000 Subject: [PATCH 1/8] Version: bump 5.5.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7da38a9cbc..5504436c80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ # limitations under the License. # -version=5.5.0-SNAPSHOT +version=5.5.0 org.gradle.daemon=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en From c59ab52457e7c45fd31c6f29b2085c28926a65a4 Mon Sep 17 00:00:00 2001 From: Ross Lawley <420+rozza@users.noreply.github.com> Date: Wed, 7 May 2025 08:58:59 +0000 Subject: [PATCH 2/8] Version: bump 5.5.1-SNAPSHOT --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5504436c80..67c7191cfe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ # limitations under the License. # -version=5.5.0 +version=5.5.1-SNAPSHOT org.gradle.daemon=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en From 02a572213a78a5527aa35adb4c8b9e1111700e47 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 2 Jun 2025 20:47:56 -0600 Subject: [PATCH 3/8] Fix OIDC reauthentication when a session is involved (#1719) (#1725) A backport of https://github.com/mongodb/mongo-java-driver/pull/1719. JAVA-5880 --- .../internal/connection/Authenticator.java | 9 ++++-- .../OidcAuthenticationProseTests.java | 31 ++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java b/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java index cd1809966b..b1579cd119 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java +++ b/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java @@ -103,13 +103,18 @@ abstract void authenticateAsync(InternalConnection connection, ConnectionDescrip OperationContext operationContext, SingleResultCallback callback); public void reauthenticate(final InternalConnection connection, final OperationContext operationContext) { - authenticate(connection, connection.getDescription(), operationContext); + authenticate(connection, connection.getDescription(), operationContextWithoutSession(operationContext)); } public void reauthenticateAsync(final InternalConnection connection, final OperationContext operationContext, final SingleResultCallback callback) { beginAsync().thenRun((c) -> { - authenticateAsync(connection, connection.getDescription(), operationContext, c); + authenticateAsync(connection, connection.getDescription(), operationContextWithoutSession(operationContext), c); }).finish(callback); } + + private static OperationContext operationContextWithoutSession(final OperationContext operationContext) { + return operationContext.withSessionContext( + new ReadConcernAwareNoOpSessionContext(operationContext.getSessionContext().getReadConcern())); + } } diff --git a/driver-sync/src/test/functional/com/mongodb/internal/connection/OidcAuthenticationProseTests.java b/driver-sync/src/test/functional/com/mongodb/internal/connection/OidcAuthenticationProseTests.java index b6a23a576c..2b0544f0c5 100644 --- a/driver-sync/src/test/functional/com/mongodb/internal/connection/OidcAuthenticationProseTests.java +++ b/driver-sync/src/test/functional/com/mongodb/internal/connection/OidcAuthenticationProseTests.java @@ -24,9 +24,12 @@ import com.mongodb.MongoSecurityException; import com.mongodb.MongoSocketException; import com.mongodb.assertions.Assertions; +import com.mongodb.client.ClientSession; +import com.mongodb.client.FindIterable; import com.mongodb.client.Fixture; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; import com.mongodb.client.TestListener; import com.mongodb.event.CommandListener; import com.mongodb.lang.Nullable; @@ -334,12 +337,17 @@ public void test3p3UnexpectedErrorDoesNotClearCache() { @Test public void test4p1Reauthentication() { + testReauthentication(false); + } + + private void testReauthentication(final boolean inSession) { TestCallback callback = createCallback(); MongoClientSettings clientSettings = createSettings(callback); - try (MongoClient mongoClient = createMongoClient(clientSettings)) { + try (MongoClient mongoClient = createMongoClient(clientSettings); + ClientSession session = inSession ? mongoClient.startSession() : null) { failCommand(391, 1, "find"); // #. Perform a find operation that succeeds. - performFind(mongoClient); + performFind(mongoClient, session); } assertEquals(2, callback.invocations.get()); } @@ -392,6 +400,11 @@ private static void performInsert(final MongoClient mongoClient) { .insertOne(Document.parse("{ x: 1 }")); } + @Test + public void test4p5ReauthenticationInSession() { + testReauthentication(true); + } + @Test public void test5p1AzureSucceedsWithNoUsername() { assumeAzure(); @@ -914,12 +927,14 @@ private void assertFindFails( } } - private void performFind(final MongoClient mongoClient) { - mongoClient - .getDatabase("test") - .getCollection("test") - .find() - .first(); + private static void performFind(final MongoClient mongoClient) { + performFind(mongoClient, null); + } + + private static void performFind(final MongoClient mongoClient, @Nullable final ClientSession session) { + MongoCollection collection = mongoClient.getDatabase("test").getCollection("test"); + FindIterable findIterable = session == null ? collection.find() : collection.find(session); + findIterable.first(); } protected void delayNextFind() { From ebdd5bfaac9adcca4682e0cb9fc1574b615edd3a Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin Date: Fri, 6 Jun 2025 10:33:56 -0700 Subject: [PATCH 4/8] Ensure custom KProperty include the name in the hashcode (#1731) The `pathCache` utilised the string representation of the KProperty instance. The custom implementations didn't include the calculated `path` value, this can lead to naming collisions in the `pathCache` key. This commit adds `hashCode` and `equals` methods to ensure the `name` value is included in our custom implementations of `KProperty1`. Finally, the cache key now uses the `hashCode` for the cacheKey. JAVA-5868 Co-authored-by: Ross Lawley --- .../mongodb/kotlin/client/model/Properties.kt | 5 ++--- .../kotlin/client/property/KPropertyPath.kt | 17 +++++++++++++++++ .../kotlin/client/model/KPropertiesTest.kt | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/model/Properties.kt b/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/model/Properties.kt index fc8a4e94e8..97ebae27d6 100644 --- a/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/model/Properties.kt +++ b/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/model/Properties.kt @@ -32,7 +32,7 @@ import kotlin.reflect.jvm.javaField import org.bson.codecs.pojo.annotations.BsonId import org.bson.codecs.pojo.annotations.BsonProperty -private val pathCache: MutableMap by lazySoft { ConcurrentHashMap() } +private val pathCache: MutableMap by lazySoft { ConcurrentHashMap() } /** Returns a composed property. For example Friend::address / Address::postalCode = "address.postalCode". */ public operator fun KProperty1.div(p2: KProperty1): KProperty1 = @@ -71,8 +71,7 @@ public fun KProperty.path(): String { return if (this is KPropertyPath<*, T>) { this.name } else { - pathCache.computeIfAbsent(this.toString()) { - + pathCache.computeIfAbsent(hashCode()) { // Check serial name - Note kotlinx.serialization.SerialName may not be on the class // path val serialName = diff --git a/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/property/KPropertyPath.kt b/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/property/KPropertyPath.kt index a460266f09..1aaa3f622e 100644 --- a/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/property/KPropertyPath.kt +++ b/driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/property/KPropertyPath.kt @@ -20,6 +20,7 @@ package com.mongodb.kotlin.client.property import com.mongodb.annotations.Sealed import com.mongodb.kotlin.client.model.path +import java.util.Objects import kotlin.reflect.KParameter import kotlin.reflect.KProperty1 import kotlin.reflect.KType @@ -84,6 +85,15 @@ public open class KPropertyPath( override fun callBy(args: Map): R = unSupportedOperation() override fun get(receiver: T): R = unSupportedOperation() override fun getDelegate(receiver: T): Any? = unSupportedOperation() + override fun hashCode(): Int = Objects.hash(previous, property, name) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as KPropertyPath<*, *> + return Objects.equals(previous, other.previous) && + Objects.equals(property, other.property) && + Objects.equals(name, other.name) + } public companion object { @@ -121,6 +131,13 @@ public open class KPropertyPath( override fun get(receiver: T): R = unSupportedOperation() override fun getDelegate(receiver: T): Any? = unSupportedOperation() override fun invoke(p1: T): R = unSupportedOperation() + override fun hashCode(): Int = Objects.hash(previous, name) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as CustomProperty<*, *> + return Objects.equals(previous, other.previous) && Objects.equals(name, other.name) + } } /** Provides "fake" property with custom name. */ diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt index 0007c6251e..51e09675d7 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt @@ -139,4 +139,20 @@ class KPropertiesTest { assertThrows { property.get(restaurant) } assertThrows { property.getDelegate(restaurant) } } + + @Test + fun testNoCacheCollisions() { + for (i in 1.rangeTo(25_000)) { + assertEquals("reviews.$i", Restaurant::reviews.pos(i).path()) + assertEquals("reviews.$[identifier$i]", Restaurant::reviews.filteredPosOp("identifier$i").path()) + assertEquals("localeMap.$i", Restaurant::localeMap.keyProjection(i).path()) + + val x = i / 2 + assertEquals( + "reviews.$[identifier$x].rating", + (Restaurant::reviews.filteredPosOp("identifier$x") / Review::score).path()) + assertEquals("reviews.$x.rating", (Restaurant::reviews.pos(x) / Review::score).path()) + assertEquals("localeMap.$x.rating", (Restaurant::localeMap.keyProjection(x) / Review::score).path()) + } + } } From a2e0c29857d5234fb60475a5e36e4880f6d0e986 Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin Date: Fri, 6 Jun 2025 10:48:33 -0700 Subject: [PATCH 5/8] Fix datalake and k8s test failures (#1732) - Increase timeout for k8s tests. - Add explicit "assume role". - Include submodules to OIDC testing. JAVA-5885 --- .evergreen/.evg.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.evergreen/.evg.yml b/.evergreen/.evg.yml index b1685115e7..b28e40a075 100644 --- a/.evergreen/.evg.yml +++ b/.evergreen/.evg.yml @@ -207,8 +207,12 @@ functions: file: mo-expansion.yml "bootstrap mongohoused": + - command: ec2.assume_role + params: + role_arn: ${aws_test_secrets_role} - command: shell.exec params: + include_expansions_in_env: [ "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN" ] script: | DRIVERS_TOOLS="${DRIVERS_TOOLS}" bash ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/pull-mongohouse-image.sh - command: shell.exec @@ -838,6 +842,8 @@ functions: export K8S_DRIVERS_TAR_FILE=/tmp/mongo-java-driver.tar git archive -o $K8S_DRIVERS_TAR_FILE HEAD tar -rf $K8S_DRIVERS_TAR_FILE .git + # Loop through all submodule directories and append to the archive + git submodule status --recursive | awk '{ print $2 }' | xargs tar -rf "$K8S_DRIVERS_TAR_FILE" export K8S_TEST_CMD="OIDC_ENV=k8s VARIANT=${VARIANT} ./.evergreen/run-mongodb-oidc-test.sh" bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/setup-pod.sh bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/run-self-test.sh @@ -969,6 +975,8 @@ tasks: bash $DRIVERS_TOOLS/.evergreen/auth_oidc/gcp/run-driver-test.sh - name: "oidc-auth-test-k8s" + # Might exceed 1 hour of execution. + exec_timeout_secs: 7200 commands: - command: ec2.assume_role params: @@ -983,6 +991,8 @@ tasks: - func: "oidc-auth-test-k8s-func" vars: VARIANT: gke + params: + include_expansions_in_env: [ "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN" ] - name: serverless-test commands: From f325224c1e9263e23b6699b99f2d2eff213764c2 Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin Date: Fri, 6 Jun 2025 12:58:36 -0700 Subject: [PATCH 6/8] Use OperationContext with NOOP Session (#1733) JAVA-5880 --- .../main/com/mongodb/internal/connection/Authenticator.java | 2 +- .../com/mongodb/internal/connection/OidcAuthenticator.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java b/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java index b1579cd119..2889a93870 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java +++ b/driver-core/src/main/com/mongodb/internal/connection/Authenticator.java @@ -113,7 +113,7 @@ public void reauthenticateAsync(final InternalConnection connection, final Opera }).finish(callback); } - private static OperationContext operationContextWithoutSession(final OperationContext operationContext) { + static OperationContext operationContextWithoutSession(final OperationContext operationContext) { return operationContext.withSessionContext( new ReadConcernAwareNoOpSessionContext(operationContext.getSessionContext().getReadConcern())); } diff --git a/driver-core/src/main/com/mongodb/internal/connection/OidcAuthenticator.java b/driver-core/src/main/com/mongodb/internal/connection/OidcAuthenticator.java index 99fcee788e..1e67626d60 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/OidcAuthenticator.java +++ b/driver-core/src/main/com/mongodb/internal/connection/OidcAuthenticator.java @@ -253,7 +253,7 @@ static OidcCallback getGcpCallback(final MongoCredential credential) { @Override public void reauthenticate(final InternalConnection connection, final OperationContext operationContext) { assertTrue(connection.opened()); - authenticationLoop(connection, connection.getDescription(), operationContext); + authenticationLoop(connection, connection.getDescription(), operationContextWithoutSession(operationContext)); } @Override @@ -262,7 +262,7 @@ public void reauthenticateAsync(final InternalConnection connection, final SingleResultCallback callback) { beginAsync().thenRun(c -> { assertTrue(connection.opened()); - authenticationLoopAsync(connection, connection.getDescription(), operationContext, c); + authenticationLoopAsync(connection, connection.getDescription(), operationContextWithoutSession(operationContext), c); }).finish(callback); } From a91368dc46ab295bc97697156e431d7551f826a6 Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin <18335884+vbabanin@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:35:15 +0000 Subject: [PATCH 7/8] Version: bump 5.5.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 67c7191cfe..85e3c33ce5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ # limitations under the License. # -version=5.5.1-SNAPSHOT +version=5.5.1 org.gradle.daemon=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en From 53be81f9bf84f7f96543d43e3639b99938610966 Mon Sep 17 00:00:00 2001 From: Viacheslav Babanin <18335884+vbabanin@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:35:15 +0000 Subject: [PATCH 8/8] Version: bump 5.5.2-SNAPSHOT --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 85e3c33ce5..99e74d41c8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ # limitations under the License. # -version=5.5.1 +version=5.5.2-SNAPSHOT org.gradle.daemon=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en