From 666136b4b85529600cc0d2482a8084ce2fcba92f Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Mon, 7 Apr 2025 06:08:23 -0700 Subject: [PATCH 01/14] core: Avoid Set.removeAll() when passing a possibly-large List (#11994) (#12000) See #11958 --- .../main/java/io/grpc/internal/DelayedClientTransport.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java index 8ff755af3eb..eccd8fadc8c 100644 --- a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java +++ b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java @@ -325,7 +325,11 @@ final void reprocess(@Nullable SubchannelPicker picker) { if (!hasPendingStreams()) { return; } - pendingStreams.removeAll(toRemove); + // Avoid pendingStreams.removeAll() as it can degrade to calling toRemove.contains() for each + // element in pendingStreams. + for (PendingStream stream : toRemove) { + pendingStreams.remove(stream); + } // Because delayed transport is long-lived, we take this opportunity to down-size the // hashmap. if (pendingStreams.isEmpty()) { From 868178651f6ae0dcef5bc0048c1e94ed1a8c13cc Mon Sep 17 00:00:00 2001 From: Kannan J Date: Mon, 7 Apr 2025 15:06:04 +0000 Subject: [PATCH 02/14] xds: ClusterResolverLoadBalancer handle update for both resolved addresses and errors via ResolutionResult (#11997) (#12006) Backport of #11997 to v1.72.x. ------ Fixes #11995 --- .../grpc/xds/ClusterResolverLoadBalancer.java | 134 +++++++++--------- .../xds/ClusterResolverLoadBalancerTest.java | 83 +++++++++-- 2 files changed, 138 insertions(+), 79 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java index c92f592ebc8..0fb7cf15909 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java @@ -33,6 +33,7 @@ import io.grpc.NameResolver; import io.grpc.NameResolver.ResolutionResult; import io.grpc.Status; +import io.grpc.StatusOr; import io.grpc.SynchronizationContext; import io.grpc.SynchronizationContext.ScheduledHandle; import io.grpc.internal.BackoffPolicy; @@ -657,79 +658,84 @@ private class NameResolverListener extends NameResolver.Listener2 { @Override public void onResult(final ResolutionResult resolutionResult) { - class NameResolved implements Runnable { - @Override - public void run() { - if (shutdown) { - return; - } - backoffPolicy = null; // reset backoff sequence if succeeded - // Arbitrary priority notation for all DNS-resolved endpoints. - String priorityName = priorityName(name, 0); // value doesn't matter - List addresses = new ArrayList<>(); - for (EquivalentAddressGroup eag : resolutionResult.getAddresses()) { - // No weight attribute is attached, all endpoint-level LB policy should be able - // to handle such it. - String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY); - Attributes attr = eag.getAttributes().toBuilder() - .set(XdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY) - .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName) - .set(XdsAttributes.ATTR_ADDRESS_NAME, dnsHostName) - .build(); - eag = new EquivalentAddressGroup(eag.getAddresses(), attr); - eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName)); - addresses.add(eag); - } - PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig( - name, lrsServerInfo, maxConcurrentRequests, tlsContext, filterMetadata, - lbRegistry, Collections.emptyList()); - status = Status.OK; - resolved = true; - result = new ClusterResolutionResult(addresses, priorityName, priorityChildConfig); - handleEndpointResourceUpdate(); + syncContext.execute(() -> onResult2(resolutionResult)); + } + + @Override + public Status onResult2(final ResolutionResult resolutionResult) { + if (shutdown) { + return Status.OK; + } + // Arbitrary priority notation for all DNS-resolved endpoints. + String priorityName = priorityName(name, 0); // value doesn't matter + List addresses = new ArrayList<>(); + StatusOr> addressesOrError = + resolutionResult.getAddressesOrError(); + if (addressesOrError.hasValue()) { + backoffPolicy = null; // reset backoff sequence if succeeded + for (EquivalentAddressGroup eag : resolutionResult.getAddresses()) { + // No weight attribute is attached, all endpoint-level LB policy should be able + // to handle such it. + String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY); + Attributes attr = eag.getAttributes().toBuilder() + .set(XdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY) + .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName) + .set(XdsAttributes.ATTR_ADDRESS_NAME, dnsHostName) + .build(); + eag = new EquivalentAddressGroup(eag.getAddresses(), attr); + eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName)); + addresses.add(eag); } + PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig( + name, lrsServerInfo, maxConcurrentRequests, tlsContext, filterMetadata, + lbRegistry, Collections.emptyList()); + status = Status.OK; + resolved = true; + result = new ClusterResolutionResult(addresses, priorityName, priorityChildConfig); + handleEndpointResourceUpdate(); + return Status.OK; + } else { + handleErrorInSyncContext(addressesOrError.getStatus()); + return addressesOrError.getStatus(); } - - syncContext.execute(new NameResolved()); } @Override public void onError(final Status error) { - syncContext.execute(new Runnable() { - @Override - public void run() { - if (shutdown) { - return; - } - status = error; - // NameResolver.Listener API cannot distinguish between address-not-found and - // transient errors. If the error occurs in the first resolution, treat it as - // address not found. Otherwise, either there is previously resolved addresses - // previously encountered error, propagate the error to downstream/upstream and - // let downstream/upstream handle it. - if (!resolved) { - resolved = true; - handleEndpointResourceUpdate(); - } else { - handleEndpointResolutionError(); - } - if (scheduledRefresh != null && scheduledRefresh.isPending()) { - return; - } - if (backoffPolicy == null) { - backoffPolicy = backoffPolicyProvider.get(); - } - long delayNanos = backoffPolicy.nextBackoffNanos(); - logger.log(XdsLogLevel.DEBUG, + syncContext.execute(() -> handleErrorInSyncContext(error)); + } + + private void handleErrorInSyncContext(final Status error) { + if (shutdown) { + return; + } + status = error; + // NameResolver.Listener API cannot distinguish between address-not-found and + // transient errors. If the error occurs in the first resolution, treat it as + // address not found. Otherwise, either there is previously resolved addresses + // previously encountered error, propagate the error to downstream/upstream and + // let downstream/upstream handle it. + if (!resolved) { + resolved = true; + handleEndpointResourceUpdate(); + } else { + handleEndpointResolutionError(); + } + if (scheduledRefresh != null && scheduledRefresh.isPending()) { + return; + } + if (backoffPolicy == null) { + backoffPolicy = backoffPolicyProvider.get(); + } + long delayNanos = backoffPolicy.nextBackoffNanos(); + logger.log(XdsLogLevel.DEBUG, "Logical DNS resolver for cluster {0} encountered name resolution " - + "error: {1}, scheduling DNS resolution backoff for {2} ns", + + "error: {1}, scheduling DNS resolution backoff for {2} ns", name, error, delayNanos); - scheduledRefresh = + scheduledRefresh = syncContext.schedule( - new DelayedNameResolverRefresh(), delayNanos, TimeUnit.NANOSECONDS, - timeService); - } - }); + new DelayedNameResolverRefresh(), delayNanos, TimeUnit.NANOSECONDS, + timeService); } } } diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java index d0176d7aa38..d701f281c01 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java @@ -200,6 +200,7 @@ public XdsClient returnObject(Object object) { private ArgumentCaptor pickerCaptor; private int xdsClientRefs; private ClusterResolverLoadBalancer loadBalancer; + private NameResolverProvider fakeNameResolverProvider; @Before public void setUp() throws URISyntaxException { @@ -216,7 +217,8 @@ public void setUp() throws URISyntaxException { .setServiceConfigParser(mock(ServiceConfigParser.class)) .setChannelLogger(mock(ChannelLogger.class)) .build(); - nsRegistry.register(new FakeNameResolverProvider()); + fakeNameResolverProvider = new FakeNameResolverProvider(false); + nsRegistry.register(fakeNameResolverProvider); when(helper.getNameResolverRegistry()).thenReturn(nsRegistry); when(helper.getNameResolverArgs()).thenReturn(args); when(helper.getSynchronizationContext()).thenReturn(syncContext); @@ -826,6 +828,17 @@ public void handleEdsResource_noHealthyEndpoint() { @Test public void onlyLogicalDnsCluster_endpointsResolved() { + do_onlyLogicalDnsCluster_endpointsResolved(); + } + + @Test + public void oldListenerCallback_onlyLogicalDnsCluster_endpointsResolved() { + nsRegistry.deregister(fakeNameResolverProvider); + nsRegistry.register(new FakeNameResolverProvider(true)); + do_onlyLogicalDnsCluster_endpointsResolved(); + } + + void do_onlyLogicalDnsCluster_endpointsResolved() { ClusterResolverConfig config = new ClusterResolverConfig( Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false); deliverLbConfig(config); @@ -854,7 +867,6 @@ public void onlyLogicalDnsCluster_endpointsResolved() { .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); assertThat(childBalancer.addresses.get(1).getAttributes() .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); - } @Test @@ -874,37 +886,48 @@ public void onlyLogicalDnsCluster_handleRefreshNameResolution() { } @Test - public void onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() { + public void resolutionError_backoffAndRefresh() { + do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh(); + } + + @Test + public void oldListenerCallback_resolutionError_backoffAndRefresh() { + nsRegistry.deregister(fakeNameResolverProvider); + nsRegistry.register(new FakeNameResolverProvider(true)); + do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh(); + } + + void do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() { InOrder inOrder = Mockito.inOrder(helper, backoffPolicyProvider, - backoffPolicy1, backoffPolicy2); + backoffPolicy1, backoffPolicy2); ClusterResolverConfig config = new ClusterResolverConfig( - Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false); + Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false); deliverLbConfig(config); FakeNameResolver resolver = assertResolverCreated("/" + DNS_HOST_NAME); assertThat(childBalancers).isEmpty(); Status error = Status.UNAVAILABLE.withDescription("cannot reach DNS server"); resolver.deliverError(error); inOrder.verify(helper).updateBalancingState( - eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture()); + eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture()); assertPicker(pickerCaptor.getValue(), error, null); assertThat(resolver.refreshCount).isEqualTo(0); inOrder.verify(backoffPolicyProvider).get(); inOrder.verify(backoffPolicy1).nextBackoffNanos(); assertThat(fakeClock.getPendingTasks()).hasSize(1); assertThat(Iterables.getOnlyElement(fakeClock.getPendingTasks()).getDelay(TimeUnit.SECONDS)) - .isEqualTo(1L); + .isEqualTo(1L); fakeClock.forwardTime(1L, TimeUnit.SECONDS); assertThat(resolver.refreshCount).isEqualTo(1); error = Status.UNKNOWN.withDescription("I am lost"); resolver.deliverError(error); inOrder.verify(helper).updateBalancingState( - eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture()); + eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture()); inOrder.verify(backoffPolicy1).nextBackoffNanos(); assertPicker(pickerCaptor.getValue(), error, null); assertThat(fakeClock.getPendingTasks()).hasSize(1); assertThat(Iterables.getOnlyElement(fakeClock.getPendingTasks()).getDelay(TimeUnit.SECONDS)) - .isEqualTo(10L); + .isEqualTo(10L); fakeClock.forwardTime(10L, TimeUnit.SECONDS); assertThat(resolver.refreshCount).isEqualTo(2); @@ -914,7 +937,7 @@ public void onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() { resolver.deliverEndpointAddresses(Arrays.asList(endpoint1, endpoint2)); assertThat(childBalancers).hasSize(1); assertAddressesEqual(Arrays.asList(endpoint1, endpoint2), - Iterables.getOnlyElement(childBalancers).addresses); + Iterables.getOnlyElement(childBalancers).addresses); assertThat(fakeClock.getPendingTasks()).isEmpty(); inOrder.verifyNoMoreInteractions(); @@ -1319,10 +1342,18 @@ void deliverError(Status error) { } private class FakeNameResolverProvider extends NameResolverProvider { + private final boolean useOldListenerCallback; + + private FakeNameResolverProvider(boolean useOldListenerCallback) { + this.useOldListenerCallback = useOldListenerCallback; + } + @Override public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) { assertThat(targetUri.getScheme()).isEqualTo("dns"); - FakeNameResolver resolver = new FakeNameResolver(targetUri); + FakeNameResolver resolver = useOldListenerCallback + ? new FakeNameResolverUsingOldListenerCallback(targetUri) + : new FakeNameResolver(targetUri); resolvers.add(resolver); return resolver; } @@ -1343,9 +1374,10 @@ protected int priority() { } } + private class FakeNameResolver extends NameResolver { private final URI targetUri; - private Listener2 listener; + protected Listener2 listener; private int refreshCount; private FakeNameResolver(URI targetUri) { @@ -1372,12 +1404,33 @@ public void shutdown() { resolvers.remove(this); } - private void deliverEndpointAddresses(List addresses) { + protected void deliverEndpointAddresses(List addresses) { + syncContext.execute(() -> { + Status ret = listener.onResult2(ResolutionResult.newBuilder() + .setAddressesOrError(StatusOr.fromValue(addresses)).build()); + assertThat(ret.getCode()).isEqualTo(Status.Code.OK); + }); + } + + protected void deliverError(Status error) { + syncContext.execute(() -> listener.onResult2(ResolutionResult.newBuilder() + .setAddressesOrError(StatusOr.fromStatus(error)).build())); + } + } + + private class FakeNameResolverUsingOldListenerCallback extends FakeNameResolver { + private FakeNameResolverUsingOldListenerCallback(URI targetUri) { + super(targetUri); + } + + @Override + protected void deliverEndpointAddresses(List addresses) { listener.onResult(ResolutionResult.newBuilder() - .setAddressesOrError(StatusOr.fromValue(addresses)).build()); + .setAddressesOrError(StatusOr.fromValue(addresses)).build()); } - private void deliverError(Status error) { + @Override + protected void deliverError(Status error) { listener.onError(error); } } From a6e1c1f09c6c7ff8e54405d6782bb1ff553ffb29 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Tue, 8 Apr 2025 03:30:58 -0700 Subject: [PATCH 03/14] stub: trailersFromThrowable() metadata should be copied (#11979) (#12008) If the same exception is passed to multiple RPCs, then the results will race, which this fix addresses. Fixes #11973 Co-authored-by: jiangyuan --- .../main/java/io/grpc/stub/ServerCalls.java | 7 +++-- .../java/io/grpc/stub/ServerCallsTest.java | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/stub/src/main/java/io/grpc/stub/ServerCalls.java b/stub/src/main/java/io/grpc/stub/ServerCalls.java index 7990a5b34c0..9f0063713cc 100644 --- a/stub/src/main/java/io/grpc/stub/ServerCalls.java +++ b/stub/src/main/java/io/grpc/stub/ServerCalls.java @@ -382,9 +382,10 @@ public void onNext(RespT response) { @Override public void onError(Throwable t) { - Metadata metadata = Status.trailersFromThrowable(t); - if (metadata == null) { - metadata = new Metadata(); + Metadata metadata = new Metadata(); + Metadata trailers = Status.trailersFromThrowable(t); + if (trailers != null) { + metadata.merge(trailers); } call.close(Status.fromThrowable(t), metadata); aborted = true; diff --git a/stub/src/test/java/io/grpc/stub/ServerCallsTest.java b/stub/src/test/java/io/grpc/stub/ServerCallsTest.java index 1e51ac10110..6f458facc5e 100644 --- a/stub/src/test/java/io/grpc/stub/ServerCallsTest.java +++ b/stub/src/test/java/io/grpc/stub/ServerCallsTest.java @@ -555,6 +555,35 @@ public void invoke(Integer req, StreamObserver responseObserver) { listener.onHalfClose(); } + @Test + public void clientSendsOne_serverOnErrorWithTrailers_serverStreaming() { + Metadata trailers = new Metadata(); + Metadata.Key key = Metadata.Key.of("trailers-test-key1", + Metadata.ASCII_STRING_MARSHALLER); + trailers.put(key, "trailers-test-value1"); + + ServerCallRecorder serverCall = new ServerCallRecorder(SERVER_STREAMING_METHOD); + ServerCallHandler callHandler = ServerCalls.asyncServerStreamingCall( + new ServerCalls.ServerStreamingMethod() { + @Override + public void invoke(Integer req, StreamObserver responseObserver) { + responseObserver.onError( + Status.fromCode(Status.Code.INTERNAL) + .asRuntimeException(trailers) + ); + } + }); + ServerCall.Listener listener = callHandler.startCall(serverCall, new Metadata()); + serverCall.isReady = true; + serverCall.isCancelled = false; + listener.onReady(); + listener.onMessage(1); + listener.onHalfClose(); + // verify trailers key is set + assertTrue(serverCall.trailers.containsKey(key)); + assertTrue(serverCall.status.equals(Status.INTERNAL)); + } + @Test public void inprocessTransportManualFlow() throws Exception { final Semaphore semaphore = new Semaphore(1); @@ -652,6 +681,7 @@ private static class ServerCallRecorder extends ServerCall { private boolean isCancelled; private boolean isReady; private int onReadyThreshold; + private Metadata trailers; public ServerCallRecorder(MethodDescriptor methodDescriptor) { this.methodDescriptor = methodDescriptor; @@ -674,6 +704,7 @@ public void sendMessage(Integer message) { @Override public void close(Status status, Metadata trailers) { this.status = status; + this.trailers = trailers; } @Override From b4e635d907684f1049e4ab9fd0d8cea6c097e6af Mon Sep 17 00:00:00 2001 From: Kannan J Date: Tue, 15 Apr 2025 08:31:05 +0000 Subject: [PATCH 04/14] stub: Utility method StreamObservers.nextAndComplete() that does both onNext and onComplete (#11778) (#12021) --- .../java/io/grpc/stub/StreamObservers.java | 23 +++++++++--- .../io/grpc/stub/StreamObserversTest.java | 35 +++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 stub/src/test/java/io/grpc/stub/StreamObserversTest.java diff --git a/stub/src/main/java/io/grpc/stub/StreamObservers.java b/stub/src/main/java/io/grpc/stub/StreamObservers.java index 2cc53ea0aa2..a421d3eca2f 100644 --- a/stub/src/main/java/io/grpc/stub/StreamObservers.java +++ b/stub/src/main/java/io/grpc/stub/StreamObservers.java @@ -23,12 +23,21 @@ /** * Utility functions for working with {@link StreamObserver} and it's common subclasses like * {@link CallStreamObserver}. - * - * @deprecated Of questionable utility and generally not used. */ -@Deprecated -@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694") public final class StreamObservers { + // Prevent instantiation + private StreamObservers() { } + + /** + * Utility method to call {@link StreamObserver#onNext(Object)} and + * {@link StreamObserver#onCompleted()} on the specified responseObserver. + */ + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10957") + public static void nextAndComplete(StreamObserver responseObserver, T response) { + responseObserver.onNext(response); + responseObserver.onCompleted(); + } + /** * Copy the values of an {@link Iterator} to the target {@link CallStreamObserver} while properly * accounting for outbound flow-control. After calling this method, {@code target} should no @@ -40,7 +49,10 @@ public final class StreamObservers { * * @param source of values expressed as an {@link Iterator}. * @param target {@link CallStreamObserver} which accepts values from the source. + * @deprecated Of questionable utility and generally not used. */ + @Deprecated + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694") public static void copyWithFlowControl(final Iterator source, final CallStreamObserver target) { Preconditions.checkNotNull(source, "source"); @@ -80,7 +92,10 @@ public void run() { * * @param source of values expressed as an {@link Iterable}. * @param target {@link CallStreamObserver} which accepts values from the source. + * @deprecated Of questionable utility and generally not used. */ + @Deprecated + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694") public static void copyWithFlowControl(final Iterable source, CallStreamObserver target) { Preconditions.checkNotNull(source, "source"); diff --git a/stub/src/test/java/io/grpc/stub/StreamObserversTest.java b/stub/src/test/java/io/grpc/stub/StreamObserversTest.java new file mode 100644 index 00000000000..86a1aba2e76 --- /dev/null +++ b/stub/src/test/java/io/grpc/stub/StreamObserversTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2025 The gRPC Authors + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.stub; + +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; + +public class StreamObserversTest { + + @Test + public void nextAndComplete() { + @SuppressWarnings("unchecked") + StreamObserver observer = Mockito.mock(StreamObserver.class); + InOrder inOrder = Mockito.inOrder(observer); + StreamObservers.nextAndComplete(observer, "TEST"); + inOrder.verify(observer).onNext("TEST"); + inOrder.verify(observer).onCompleted(); + inOrder.verifyNoMoreInteractions(); + } +} From a2b642cd208f4734c16165c8977ae7b4463f275f Mon Sep 17 00:00:00 2001 From: AgraVator Date: Tue, 15 Apr 2025 08:43:35 +0000 Subject: [PATCH 05/14] Update README etc to reference 1.72.0 --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 756519d0ad0..d1b4d516f74 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ For a guided tour, take a look at the [quick start guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC basics](https://grpc.io/docs/languages/java/basics). -The [examples](https://github.com/grpc/grpc-java/tree/v1.71.0/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.71.0/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.72.0/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.72.0/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -56,18 +56,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.71.0 + 1.72.0 runtime io.grpc grpc-protobuf - 1.71.0 + 1.72.0 io.grpc grpc-stub - 1.71.0 + 1.72.0 org.apache.tomcat @@ -79,18 +79,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: Or for Gradle with non-Android, add to your dependencies: ```gradle -runtimeOnly 'io.grpc:grpc-netty-shaded:1.71.0' -implementation 'io.grpc:grpc-protobuf:1.71.0' -implementation 'io.grpc:grpc-stub:1.71.0' +runtimeOnly 'io.grpc:grpc-netty-shaded:1.72.0' +implementation 'io.grpc:grpc-protobuf:1.72.0' +implementation 'io.grpc:grpc-stub:1.72.0' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and `grpc-protobuf-lite` instead of `grpc-protobuf`: ```gradle -implementation 'io.grpc:grpc-okhttp:1.71.0' -implementation 'io.grpc:grpc-protobuf-lite:1.71.0' -implementation 'io.grpc:grpc-stub:1.71.0' +implementation 'io.grpc:grpc-okhttp:1.72.0' +implementation 'io.grpc:grpc-protobuf-lite:1.72.0' +implementation 'io.grpc:grpc-stub:1.72.0' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` @@ -99,7 +99,7 @@ For [Bazel](https://bazel.build), you can either (with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below). [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.71.0 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.72.0 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -131,7 +131,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.71.0:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.72.0:exe:${os.detected.classifier} @@ -161,7 +161,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' } } generateProtoTasks { @@ -194,7 +194,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' } } generateProtoTasks { From b0794e4fb64faaf9af10fa86e85018edfd433056 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Tue, 15 Apr 2025 09:11:17 +0000 Subject: [PATCH 06/14] Bump version to 1.72.0 --- MODULE.bazel | 2 +- build.gradle | 2 +- .../src/test/golden/TestDeprecatedService.java.txt | 2 +- compiler/src/test/golden/TestService.java.txt | 2 +- core/src/main/java/io/grpc/internal/GrpcUtil.java | 2 +- examples/MODULE.bazel | 2 +- examples/android/clientcache/app/build.gradle | 10 +++++----- examples/android/helloworld/app/build.gradle | 8 ++++---- examples/android/routeguide/app/build.gradle | 8 ++++---- examples/android/strictmode/app/build.gradle | 8 ++++---- examples/build.gradle | 2 +- examples/example-alts/build.gradle | 2 +- examples/example-debug/build.gradle | 2 +- examples/example-debug/pom.xml | 4 ++-- examples/example-dualstack/build.gradle | 2 +- examples/example-dualstack/pom.xml | 4 ++-- examples/example-gauth/build.gradle | 2 +- examples/example-gauth/pom.xml | 4 ++-- examples/example-gcp-csm-observability/build.gradle | 2 +- examples/example-gcp-observability/build.gradle | 2 +- examples/example-hostname/build.gradle | 2 +- examples/example-hostname/pom.xml | 4 ++-- examples/example-jwt-auth/build.gradle | 2 +- examples/example-jwt-auth/pom.xml | 4 ++-- examples/example-oauth/build.gradle | 2 +- examples/example-oauth/pom.xml | 4 ++-- examples/example-opentelemetry/build.gradle | 2 +- examples/example-orca/build.gradle | 2 +- examples/example-reflection/build.gradle | 2 +- examples/example-servlet/build.gradle | 2 +- examples/example-tls/build.gradle | 2 +- examples/example-tls/pom.xml | 4 ++-- examples/example-xds/build.gradle | 2 +- examples/pom.xml | 4 ++-- 34 files changed, 55 insertions(+), 55 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 88f3a524060..c7c9833b09b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,7 +2,7 @@ module( name = "grpc-java", compatibility_level = 0, repo_name = "io_grpc_grpc_java", - version = "1.72.0-SNAPSHOT", # CURRENT_GRPC_VERSION + version = "1.72.0", # CURRENT_GRPC_VERSION ) # GRPC_DEPS_START diff --git a/build.gradle b/build.gradle index 93ce60054bc..95ca37cd3a5 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.72.0-SNAPSHOT" // CURRENT_GRPC_VERSION + version = "1.72.0" // CURRENT_GRPC_VERSION repositories { maven { // The google mirror is less flaky than mavenCentral() diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt index 82fe6a81d18..2dedb3aa4af 100644 --- a/compiler/src/test/golden/TestDeprecatedService.java.txt +++ b/compiler/src/test/golden/TestDeprecatedService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.72.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.72.0)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated @java.lang.Deprecated diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index 912bd50da12..16398262d59 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.72.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.72.0)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated public final class TestServiceGrpc { diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index 937854ac3ff..ada77743677 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -219,7 +219,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - public static final String IMPLEMENTATION_VERSION = "1.72.0-SNAPSHOT"; // CURRENT_GRPC_VERSION + public static final String IMPLEMENTATION_VERSION = "1.72.0"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index 4d72ae9c395..749d15d2a52 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel @@ -1,5 +1,5 @@ bazel_dep(name = "googleapis", repo_name = "com_google_googleapis", version = "0.0.0-20240326-1c8d509c5") -bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.0-SNAPSHOT") # CURRENT_GRPC_VERSION +bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.0") # CURRENT_GRPC_VERSION bazel_dep(name = "grpc-proto", repo_name = "io_grpc_grpc_proto", version = "0.0.0-20240627-ec30f58") bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "23.1") bazel_dep(name = "rules_jvm_external", version = "6.0") diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 1f2a17ae6bb..84459d147f5 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -34,7 +34,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -54,12 +54,12 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' testImplementation 'junit:junit:4.13.2' testImplementation 'com.google.truth:truth:1.1.5' - testImplementation 'io.grpc:grpc-testing:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.72.0' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 09b994a4954..5a64566c0e2 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index bdad129845b..8d659034d7f 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index f38110a741b..ea22be41aad 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -33,7 +33,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -53,8 +53,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/build.gradle b/examples/build.gradle index e807d09f407..dce9433449f 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index e7142f3fb5a..9c7c0720ed6 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-debug/build.gradle b/examples/example-debug/build.gradle index 1d07a7cb8ec..01188ac8f38 100644 --- a/examples/example-debug/build.gradle +++ b/examples/example-debug/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-debug/pom.xml b/examples/example-debug/pom.xml index 00fdecdb6c4..100151d6b37 100644 --- a/examples/example-debug/pom.xml +++ b/examples/example-debug/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-debug https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 1.8 diff --git a/examples/example-dualstack/build.gradle b/examples/example-dualstack/build.gradle index b73902095a1..555696f181b 100644 --- a/examples/example-dualstack/build.gradle +++ b/examples/example-dualstack/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-dualstack/pom.xml b/examples/example-dualstack/pom.xml index 28539851934..233e51dd7f7 100644 --- a/examples/example-dualstack/pom.xml +++ b/examples/example-dualstack/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-dualstack https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 1.8 diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 0ef0dcaefe2..96cc029d726 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index d2a32578550..922a281a4a0 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 1.8 diff --git a/examples/example-gcp-csm-observability/build.gradle b/examples/example-gcp-csm-observability/build.gradle index e16e32e3bc1..eb6adaedd27 100644 --- a/examples/example-gcp-csm-observability/build.gradle +++ b/examples/example-gcp-csm-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-gcp-observability/build.gradle b/examples/example-gcp-observability/build.gradle index 1cad10bbb87..07f5d454985 100644 --- a/examples/example-gcp-observability/build.gradle +++ b/examples/example-gcp-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index 86aa42f8ed0..c1cfc786d26 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index 6993c40a1ac..c6798f087d3 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 1.8 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index ca12c3f7872..8d5b2225012 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 7e9a915bfbd..0f68e2fd02f 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 3.25.5 diff --git a/examples/example-oauth/build.gradle b/examples/example-oauth/build.gradle index 6d06f097ccb..efa583ad777 100644 --- a/examples/example-oauth/build.gradle +++ b/examples/example-oauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-oauth/pom.xml b/examples/example-oauth/pom.xml index a9fea928a34..b6ffebc2629 100644 --- a/examples/example-oauth/pom.xml +++ b/examples/example-oauth/pom.xml @@ -7,13 +7,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-oauth https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 3.25.5 diff --git a/examples/example-opentelemetry/build.gradle b/examples/example-opentelemetry/build.gradle index f575d24d19b..7084f342af9 100644 --- a/examples/example-opentelemetry/build.gradle +++ b/examples/example-opentelemetry/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle index 45235fa1e08..acd8eb287e0 100644 --- a/examples/example-orca/build.gradle +++ b/examples/example-orca/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-reflection/build.gradle b/examples/example-reflection/build.gradle index ad68e891436..b6e47aaef97 100644 --- a/examples/example-reflection/build.gradle +++ b/examples/example-reflection/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle index 2176df5afc5..8a940eb2db3 100644 --- a/examples/example-servlet/build.gradle +++ b/examples/example-servlet/build.gradle @@ -15,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index e741bfe1c3f..87841140e5c 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index de9298cf0e1..d4c6570c8ec 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 example-tls https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 1.8 diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index c0159dce258..01b02b4a07b 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/pom.xml b/examples/pom.xml index edc9c4cda14..c160b4dfffc 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0-SNAPSHOT + 1.72.0 examples https://github.com/grpc/grpc-java UTF-8 - 1.72.0-SNAPSHOT + 1.72.0 3.25.5 3.25.5 From 9e0740676649a897f0ec8887e00a9f655c1b2dcb Mon Sep 17 00:00:00 2001 From: AgraVator Date: Tue, 15 Apr 2025 09:26:57 +0000 Subject: [PATCH 07/14] Bump version to 1.72.1-SNAPSHOT --- MODULE.bazel | 2 +- build.gradle | 2 +- .../src/test/golden/TestDeprecatedService.java.txt | 2 +- compiler/src/test/golden/TestService.java.txt | 2 +- core/src/main/java/io/grpc/internal/GrpcUtil.java | 2 +- examples/MODULE.bazel | 2 +- examples/android/clientcache/app/build.gradle | 10 +++++----- examples/android/helloworld/app/build.gradle | 8 ++++---- examples/android/routeguide/app/build.gradle | 8 ++++---- examples/android/strictmode/app/build.gradle | 8 ++++---- examples/build.gradle | 2 +- examples/example-alts/build.gradle | 2 +- examples/example-debug/build.gradle | 2 +- examples/example-debug/pom.xml | 4 ++-- examples/example-dualstack/build.gradle | 2 +- examples/example-dualstack/pom.xml | 4 ++-- examples/example-gauth/build.gradle | 2 +- examples/example-gauth/pom.xml | 4 ++-- examples/example-gcp-csm-observability/build.gradle | 2 +- examples/example-gcp-observability/build.gradle | 2 +- examples/example-hostname/build.gradle | 2 +- examples/example-hostname/pom.xml | 4 ++-- examples/example-jwt-auth/build.gradle | 2 +- examples/example-jwt-auth/pom.xml | 4 ++-- examples/example-oauth/build.gradle | 2 +- examples/example-oauth/pom.xml | 4 ++-- examples/example-opentelemetry/build.gradle | 2 +- examples/example-orca/build.gradle | 2 +- examples/example-reflection/build.gradle | 2 +- examples/example-servlet/build.gradle | 2 +- examples/example-tls/build.gradle | 2 +- examples/example-tls/pom.xml | 4 ++-- examples/example-xds/build.gradle | 2 +- examples/pom.xml | 4 ++-- 34 files changed, 55 insertions(+), 55 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index c7c9833b09b..e62ec70dda0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,7 +2,7 @@ module( name = "grpc-java", compatibility_level = 0, repo_name = "io_grpc_grpc_java", - version = "1.72.0", # CURRENT_GRPC_VERSION + version = "1.72.1-SNAPSHOT", # CURRENT_GRPC_VERSION ) # GRPC_DEPS_START diff --git a/build.gradle b/build.gradle index 95ca37cd3a5..e63e03d22d2 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.72.0" // CURRENT_GRPC_VERSION + version = "1.72.1-SNAPSHOT" // CURRENT_GRPC_VERSION repositories { maven { // The google mirror is less flaky than mavenCentral() diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt index 2dedb3aa4af..44d4dc93175 100644 --- a/compiler/src/test/golden/TestDeprecatedService.java.txt +++ b/compiler/src/test/golden/TestDeprecatedService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.72.0)", + value = "by gRPC proto compiler (version 1.72.1-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated @java.lang.Deprecated diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index 16398262d59..085ba3abe46 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.72.0)", + value = "by gRPC proto compiler (version 1.72.1-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated public final class TestServiceGrpc { diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index ada77743677..fef4b638941 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -219,7 +219,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - public static final String IMPLEMENTATION_VERSION = "1.72.0"; // CURRENT_GRPC_VERSION + public static final String IMPLEMENTATION_VERSION = "1.72.1-SNAPSHOT"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index 749d15d2a52..3612ec2640c 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel @@ -1,5 +1,5 @@ bazel_dep(name = "googleapis", repo_name = "com_google_googleapis", version = "0.0.0-20240326-1c8d509c5") -bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.0") # CURRENT_GRPC_VERSION +bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.1-SNAPSHOT") # CURRENT_GRPC_VERSION bazel_dep(name = "grpc-proto", repo_name = "io_grpc_grpc_proto", version = "0.0.0-20240627-ec30f58") bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "23.1") bazel_dep(name = "rules_jvm_external", version = "6.0") diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 84459d147f5..f68e4b52061 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -34,7 +34,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -54,12 +54,12 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' testImplementation 'junit:junit:4.13.2' testImplementation 'com.google.truth:truth:1.1.5' - testImplementation 'io.grpc:grpc-testing:1.72.0' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 5a64566c0e2..5ff4fa926b9 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index 8d659034d7f..1ae9ca28e08 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index ea22be41aad..0e4a057675e 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -33,7 +33,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -53,8 +53,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.72.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.72.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/build.gradle b/examples/build.gradle index dce9433449f..8dc8cb39716 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index 9c7c0720ed6..369f7b212da 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-debug/build.gradle b/examples/example-debug/build.gradle index 01188ac8f38..aa13f55d7b7 100644 --- a/examples/example-debug/build.gradle +++ b/examples/example-debug/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-debug/pom.xml b/examples/example-debug/pom.xml index 100151d6b37..6807df43771 100644 --- a/examples/example-debug/pom.xml +++ b/examples/example-debug/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-debug https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-dualstack/build.gradle b/examples/example-dualstack/build.gradle index 555696f181b..b8e8ec5acc4 100644 --- a/examples/example-dualstack/build.gradle +++ b/examples/example-dualstack/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-dualstack/pom.xml b/examples/example-dualstack/pom.xml index 233e51dd7f7..8ed41f27256 100644 --- a/examples/example-dualstack/pom.xml +++ b/examples/example-dualstack/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-dualstack https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 96cc029d726..f4dcf3fb8ce 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 922a281a4a0..527916af157 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-gcp-csm-observability/build.gradle b/examples/example-gcp-csm-observability/build.gradle index eb6adaedd27..c0062d69efd 100644 --- a/examples/example-gcp-csm-observability/build.gradle +++ b/examples/example-gcp-csm-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-gcp-observability/build.gradle b/examples/example-gcp-observability/build.gradle index 07f5d454985..85703711527 100644 --- a/examples/example-gcp-observability/build.gradle +++ b/examples/example-gcp-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index c1cfc786d26..3676c3ea850 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index c6798f087d3..46644f3ee7c 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index 8d5b2225012..2382365fd82 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 0f68e2fd02f..a92e1c96dd2 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 3.25.5 diff --git a/examples/example-oauth/build.gradle b/examples/example-oauth/build.gradle index efa583ad777..d2e1654f0f8 100644 --- a/examples/example-oauth/build.gradle +++ b/examples/example-oauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-oauth/pom.xml b/examples/example-oauth/pom.xml index b6ffebc2629..17514f95116 100644 --- a/examples/example-oauth/pom.xml +++ b/examples/example-oauth/pom.xml @@ -7,13 +7,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-oauth https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 3.25.5 diff --git a/examples/example-opentelemetry/build.gradle b/examples/example-opentelemetry/build.gradle index 7084f342af9..b4b78461812 100644 --- a/examples/example-opentelemetry/build.gradle +++ b/examples/example-opentelemetry/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle index acd8eb287e0..3944e451403 100644 --- a/examples/example-orca/build.gradle +++ b/examples/example-orca/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-reflection/build.gradle b/examples/example-reflection/build.gradle index b6e47aaef97..9dcbbd6c354 100644 --- a/examples/example-reflection/build.gradle +++ b/examples/example-reflection/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle index 8a940eb2db3..da4a8744da1 100644 --- a/examples/example-servlet/build.gradle +++ b/examples/example-servlet/build.gradle @@ -15,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 87841140e5c..49f0383b49a 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index d4c6570c8ec..93095aa01d9 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT example-tls https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index 01b02b4a07b..16a85758c9d 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.72.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/pom.xml b/examples/pom.xml index c160b4dfffc..ac60626c578 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.72.0 + 1.72.1-SNAPSHOT examples https://github.com/grpc/grpc-java UTF-8 - 1.72.0 + 1.72.1-SNAPSHOT 3.25.5 3.25.5 From 390bc330bc1ce48b801ed9ba005f6cc04f6e5e80 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Wed, 23 Apr 2025 21:27:15 -0700 Subject: [PATCH 08/14] xds: XdsDepManager should ignore updates after shutdown (#12038) This prevents a NPE and subsequent channel panic when trying to build a config (because there are no watchers, so waitingOnResource==false) without any listener and route. ``` java.lang.NullPointerException: Cannot invoke "io.grpc.xds.XdsDependencyManager$RdsUpdateSupplier.getRdsUpdate()" because "routeSource" is null at io.grpc.xds.XdsDependencyManager.buildUpdate(XdsDependencyManager.java:295) at io.grpc.xds.XdsDependencyManager.maybePublishConfig(XdsDependencyManager.java:266) at io.grpc.xds.XdsDependencyManager$EdsWatcher.onChanged(XdsDependencyManager.java:899) at io.grpc.xds.XdsDependencyManager$EdsWatcher.onChanged(XdsDependencyManager.java:888) at io.grpc.xds.client.XdsClientImpl$ResourceSubscriber.notifyWatcher(XdsClientImpl.java:929) at io.grpc.xds.client.XdsClientImpl$ResourceSubscriber.lambda$onData$0(XdsClientImpl.java:837) at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:96) ``` I think this fully-fixes the problem today, but not tomorrow. subscribeToCluster() is racy as well, but not yet used. This was noticed when idleTimeout was firing, with some other code calling getState(true) to wake the channel back up. That may have made this panic more visible than it would be otherwise, but that has not been investigated. b/412474567 --- .../io/grpc/xds/XdsDependencyManager.java | 16 ++ .../io/grpc/xds/XdsDependencyManagerTest.java | 137 +++++++++++++++++- 2 files changed, 151 insertions(+), 2 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/XdsDependencyManager.java b/xds/src/main/java/io/grpc/xds/XdsDependencyManager.java index 8cd3119727d..d804954ecf9 100644 --- a/xds/src/main/java/io/grpc/xds/XdsDependencyManager.java +++ b/xds/src/main/java/io/grpc/xds/XdsDependencyManager.java @@ -199,6 +199,7 @@ private void shutdownWatchersForType(TypeWatchers for (Map.Entry> watcherEntry : watchers.watchers.entrySet()) { xdsClient.cancelXdsResourceWatch(watchers.resourceType, watcherEntry.getKey(), watcherEntry.getValue()); + watcherEntry.getValue().cancelled = true; } } @@ -591,6 +592,9 @@ private XdsWatcherBase(XdsResourceType type, String resourceName) { @Override public void onError(Status error) { checkNotNull(error, "error"); + if (cancelled) { + return; + } // Don't update configuration on error, if we've already received configuration if (!hasDataValue()) { setDataAsStatus(Status.UNAVAILABLE.withDescription( @@ -659,6 +663,9 @@ private LdsWatcher(String resourceName) { @Override public void onChanged(XdsListenerResource.LdsUpdate update) { checkNotNull(update, "update"); + if (cancelled) { + return; + } HttpConnectionManager httpConnectionManager = update.httpConnectionManager(); List virtualHosts; @@ -787,6 +794,9 @@ public RdsWatcher(String resourceName) { @Override public void onChanged(RdsUpdate update) { checkNotNull(update, "update"); + if (cancelled) { + return; + } List oldVirtualHosts = hasDataValue() ? getData().getValue().virtualHosts : Collections.emptyList(); @@ -815,6 +825,9 @@ private class CdsWatcher extends XdsWatcherBase { @Override public void onChanged(XdsClusterResource.CdsUpdate update) { checkNotNull(update, "update"); + if (cancelled) { + return; + } switch (update.clusterType()) { case EDS: setData(update); @@ -895,6 +908,9 @@ private EdsWatcher(String resourceName, CdsWatcher parentContext) { @Override public void onChanged(XdsEndpointResource.EdsUpdate update) { + if (cancelled) { + return; + } setData(checkNotNull(update, "update")); maybePublishConfig(); } diff --git a/xds/src/test/java/io/grpc/xds/XdsDependencyManagerTest.java b/xds/src/test/java/io/grpc/xds/XdsDependencyManagerTest.java index 2af04a3aedf..1f3d8511ecc 100644 --- a/xds/src/test/java/io/grpc/xds/XdsDependencyManagerTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsDependencyManagerTest.java @@ -41,6 +41,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.Message; import io.envoyproxy.envoy.config.cluster.v3.Cluster; import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment; @@ -65,7 +66,7 @@ import io.grpc.xds.XdsConfig.XdsClusterConfig; import io.grpc.xds.XdsEndpointResource.EdsUpdate; import io.grpc.xds.client.CommonBootstrapperTestUtils; -import io.grpc.xds.client.XdsClientImpl; +import io.grpc.xds.client.XdsClient; import io.grpc.xds.client.XdsClientMetricReporter; import io.grpc.xds.client.XdsTransportFactory; import java.io.Closeable; @@ -115,7 +116,7 @@ public class XdsDependencyManagerTest { }); private ManagedChannel channel; - private XdsClientImpl xdsClient; + private XdsClient xdsClient; private XdsDependencyManager xdsDependencyManager; private TestWatcher xdsConfigWatcher; private Server xdsServer; @@ -715,6 +716,138 @@ public void testCdsError() throws IOException { assertThat(status.getDescription()).contains(XdsTestUtils.CLUSTER_NAME); } + @Test + public void ldsUpdateAfterShutdown() { + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + + xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext, + serverName, serverName, nameResolverArgs, scheduler); + + verify(xdsConfigWatcher, timeout(1000)).onUpdate(any()); + + @SuppressWarnings("unchecked") + XdsClient.ResourceWatcher resourceWatcher = + mock(XdsClient.ResourceWatcher.class); + xdsClient.watchXdsResource( + XdsListenerResource.getInstance(), + serverName, + resourceWatcher, + MoreExecutors.directExecutor()); + verify(resourceWatcher, timeout(5000)).onChanged(any()); + + syncContext.execute(() -> { + // Shutdown before any updates. This will unsubscribe from XdsClient, but only after this + // Runnable returns + xdsDependencyManager.shutdown(); + + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS2", "CDS", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + verify(resourceWatcher, timeout(5000).times(2)).onChanged(any()); + xdsClient.cancelXdsResourceWatch( + XdsListenerResource.getInstance(), serverName, resourceWatcher); + }); + } + + @Test + public void rdsUpdateAfterShutdown() { + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + + xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext, + serverName, serverName, nameResolverArgs, scheduler); + + verify(xdsConfigWatcher, timeout(1000)).onUpdate(any()); + + @SuppressWarnings("unchecked") + XdsClient.ResourceWatcher resourceWatcher = + mock(XdsClient.ResourceWatcher.class); + xdsClient.watchXdsResource( + XdsRouteConfigureResource.getInstance(), + "RDS", + resourceWatcher, + MoreExecutors.directExecutor()); + verify(resourceWatcher, timeout(5000)).onChanged(any()); + + syncContext.execute(() -> { + // Shutdown before any updates. This will unsubscribe from XdsClient, but only after this + // Runnable returns + xdsDependencyManager.shutdown(); + + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS2", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + verify(resourceWatcher, timeout(5000).times(2)).onChanged(any()); + xdsClient.cancelXdsResourceWatch( + XdsRouteConfigureResource.getInstance(), serverName, resourceWatcher); + }); + } + + @Test + public void cdsUpdateAfterShutdown() { + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + + xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext, + serverName, serverName, nameResolverArgs, scheduler); + + verify(xdsConfigWatcher, timeout(1000)).onUpdate(any()); + + @SuppressWarnings("unchecked") + XdsClient.ResourceWatcher resourceWatcher = + mock(XdsClient.ResourceWatcher.class); + xdsClient.watchXdsResource( + XdsClusterResource.getInstance(), + "CDS", + resourceWatcher, + MoreExecutors.directExecutor()); + verify(resourceWatcher, timeout(5000)).onChanged(any()); + + syncContext.execute(() -> { + // Shutdown before any updates. This will unsubscribe from XdsClient, but only after this + // Runnable returns + xdsDependencyManager.shutdown(); + + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS2", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + verify(resourceWatcher, timeout(5000).times(2)).onChanged(any()); + xdsClient.cancelXdsResourceWatch( + XdsClusterResource.getInstance(), serverName, resourceWatcher); + }); + } + + @Test + public void edsUpdateAfterShutdown() { + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS", + ENDPOINT_HOSTNAME, ENDPOINT_PORT); + + xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext, + serverName, serverName, nameResolverArgs, scheduler); + + verify(xdsConfigWatcher, timeout(1000)).onUpdate(any()); + + @SuppressWarnings("unchecked") + XdsClient.ResourceWatcher resourceWatcher = + mock(XdsClient.ResourceWatcher.class); + xdsClient.watchXdsResource( + XdsEndpointResource.getInstance(), + "EDS", + resourceWatcher, + MoreExecutors.directExecutor()); + verify(resourceWatcher, timeout(5000)).onChanged(any()); + + syncContext.execute(() -> { + // Shutdown before any updates. This will unsubscribe from XdsClient, but only after this + // Runnable returns + xdsDependencyManager.shutdown(); + + XdsTestUtils.setAdsConfig(controlPlaneService, serverName, "RDS", "CDS", "EDS", + ENDPOINT_HOSTNAME + "2", ENDPOINT_PORT); + verify(resourceWatcher, timeout(5000).times(2)).onChanged(any()); + xdsClient.cancelXdsResourceWatch( + XdsEndpointResource.getInstance(), serverName, resourceWatcher); + }); + } + private Listener buildInlineClientListener(String rdsName, String clusterName) { return XdsTestUtils.buildInlineClientListener(rdsName, clusterName, serverName); } From ebee8f6444bef257091b14b7a4d2667e3f386611 Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Thu, 22 May 2025 15:41:43 -0700 Subject: [PATCH 09/14] Rename PSM interop fallback test suite to light (#12093) --- buildscripts/kokoro/{psm-fallback.cfg => psm-light.cfg} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename buildscripts/kokoro/{psm-fallback.cfg => psm-light.cfg} (94%) diff --git a/buildscripts/kokoro/psm-fallback.cfg b/buildscripts/kokoro/psm-light.cfg similarity index 94% rename from buildscripts/kokoro/psm-fallback.cfg rename to buildscripts/kokoro/psm-light.cfg index 7335d1d9fd9..decd179efa3 100644 --- a/buildscripts/kokoro/psm-fallback.cfg +++ b/buildscripts/kokoro/psm-light.cfg @@ -13,5 +13,5 @@ action { } env_vars { key: "PSM_TEST_SUITE" - value: "fallback" + value: "light" } From a2e53f6238e509c3468b45505f28223ed0034fad Mon Sep 17 00:00:00 2001 From: MV Shiva Date: Fri, 23 May 2025 08:50:41 +0530 Subject: [PATCH 10/14] xds: propagate audience from cluster resource in gcp auth filter (#11972) (#12088) --- .../io/grpc/xds/GcpAuthenticationFilter.java | 108 +++++-- .../grpc/xds/GcpAuthenticationFilterTest.java | 301 +++++++++++++++++- .../grpc/xds/GrpcXdsClientImplDataTest.java | 15 +- .../test/java/io/grpc/xds/XdsTestUtils.java | 2 +- 4 files changed, 372 insertions(+), 54 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java index add885c6416..b5568efe400 100644 --- a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java +++ b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java @@ -16,8 +16,13 @@ package io.grpc.xds; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.grpc.xds.XdsNameResolver.CLUSTER_SELECTION_KEY; +import static io.grpc.xds.XdsNameResolver.XDS_CONFIG_CALL_OPTION_KEY; + import com.google.auth.oauth2.ComputeEngineCredentials; import com.google.auth.oauth2.IdTokenCredentials; +import com.google.common.annotations.VisibleForTesting; import com.google.common.primitives.UnsignedLongs; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; @@ -34,8 +39,11 @@ import io.grpc.Metadata; import io.grpc.MethodDescriptor; import io.grpc.Status; +import io.grpc.StatusOr; import io.grpc.auth.MoreCallCredentials; +import io.grpc.xds.GcpAuthenticationFilter.AudienceMetadataParser.AudienceWrapper; import io.grpc.xds.MetadataRegistry.MetadataValueParser; +import io.grpc.xds.XdsConfig.XdsClusterConfig; import io.grpc.xds.client.XdsResourceType.ResourceInvalidException; import java.util.LinkedHashMap; import java.util.Map; @@ -52,6 +60,13 @@ final class GcpAuthenticationFilter implements Filter { static final String TYPE_URL = "type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig"; + final String filterInstanceName; + + GcpAuthenticationFilter(String name) { + filterInstanceName = checkNotNull(name, "name"); + } + + static final class Provider implements Filter.Provider { @Override public String[] typeUrls() { @@ -65,7 +80,7 @@ public boolean isClientFilter() { @Override public GcpAuthenticationFilter newInstance(String name) { - return new GcpAuthenticationFilter(); + return new GcpAuthenticationFilter(name); } @Override @@ -119,34 +134,57 @@ public ClientInterceptor buildClientInterceptor(FilterConfig config, public ClientCall interceptCall( MethodDescriptor method, CallOptions callOptions, Channel next) { - /*String clusterName = callOptions.getOption(XdsAttributes.ATTR_CLUSTER_NAME); + String clusterName = callOptions.getOption(CLUSTER_SELECTION_KEY); if (clusterName == null) { + return new FailingClientCall<>( + Status.UNAVAILABLE.withDescription( + String.format( + "GCP Authn for %s does not contain cluster resource", filterInstanceName))); + } + + if (!clusterName.startsWith("cluster:")) { return next.newCall(method, callOptions); - }*/ - - // TODO: Fetch the CDS resource for the cluster. - // If the CDS resource is not available, fail the RPC with Status.UNAVAILABLE. - - // TODO: Extract the audience from the CDS resource metadata. - // If the audience is not found or is in the wrong format, fail the RPC. - String audience = "TEST_AUDIENCE"; - - try { - CallCredentials existingCallCredentials = callOptions.getCredentials(); - CallCredentials newCallCredentials = - getCallCredentials(callCredentialsCache, audience, credentials); - if (existingCallCredentials != null) { - callOptions = callOptions.withCallCredentials( - new CompositeCallCredentials(existingCallCredentials, newCallCredentials)); - } else { - callOptions = callOptions.withCallCredentials(newCallCredentials); - } } - catch (Exception e) { - // If we fail to attach CallCredentials due to any reason, return a FailingClientCall - return new FailingClientCall<>(Status.UNAUTHENTICATED - .withDescription("Failed to attach CallCredentials.") - .withCause(e)); + XdsConfig xdsConfig = callOptions.getOption(XDS_CONFIG_CALL_OPTION_KEY); + if (xdsConfig == null) { + return new FailingClientCall<>( + Status.UNAVAILABLE.withDescription( + String.format( + "GCP Authn for %s with %s does not contain xds configuration", + filterInstanceName, clusterName))); + } + StatusOr xdsCluster = + xdsConfig.getClusters().get(clusterName.substring("cluster:".length())); + if (xdsCluster == null) { + return new FailingClientCall<>( + Status.UNAVAILABLE.withDescription( + String.format( + "GCP Authn for %s with %s - xds cluster config does not contain xds cluster", + filterInstanceName, clusterName))); + } + if (!xdsCluster.hasValue()) { + return new FailingClientCall<>(xdsCluster.getStatus()); + } + Object audienceObj = + xdsCluster.getValue().getClusterResource().parsedMetadata().get(filterInstanceName); + if (audienceObj == null) { + return next.newCall(method, callOptions); + } + if (!(audienceObj instanceof AudienceWrapper)) { + return new FailingClientCall<>( + Status.UNAVAILABLE.withDescription( + String.format("GCP Authn found wrong type in %s metadata: %s=%s", + clusterName, filterInstanceName, audienceObj.getClass()))); + } + AudienceWrapper audience = (AudienceWrapper) audienceObj; + CallCredentials existingCallCredentials = callOptions.getCredentials(); + CallCredentials newCallCredentials = + getCallCredentials(callCredentialsCache, audience.audience, credentials); + if (existingCallCredentials != null) { + callOptions = callOptions.withCallCredentials( + new CompositeCallCredentials(existingCallCredentials, newCallCredentials)); + } else { + callOptions = callOptions.withCallCredentials(newCallCredentials); } return next.newCall(method, callOptions); } @@ -186,9 +224,11 @@ public String typeUrl() { } /** An implementation of {@link ClientCall} that fails when started. */ - private static final class FailingClientCall extends ClientCall { + @VisibleForTesting + static final class FailingClientCall extends ClientCall { - private final Status error; + @VisibleForTesting + final Status error; public FailingClientCall(Status error) { this.error = error; @@ -235,13 +275,21 @@ V getOrInsert(K key, Function create) { static class AudienceMetadataParser implements MetadataValueParser { + static final class AudienceWrapper { + final String audience; + + AudienceWrapper(String audience) { + this.audience = checkNotNull(audience); + } + } + @Override public String getTypeUrl() { return "type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.Audience"; } @Override - public String parse(Any any) throws ResourceInvalidException { + public AudienceWrapper parse(Any any) throws ResourceInvalidException { Audience audience; try { audience = any.unpack(Audience.class); @@ -253,7 +301,7 @@ public String parse(Any any) throws ResourceInvalidException { throw new ResourceInvalidException( "Audience URL is empty. Metadata value must contain a valid URL."); } - return url; + return new AudienceWrapper(url); } } } diff --git a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java index 52efaf9bd7b..a5e142b4094 100644 --- a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java +++ b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java @@ -17,25 +17,60 @@ package io.grpc.xds; import static com.google.common.truth.Truth.assertThat; +import static io.grpc.xds.XdsNameResolver.CLUSTER_SELECTION_KEY; +import static io.grpc.xds.XdsNameResolver.XDS_CONFIG_CALL_OPTION_KEY; +import static io.grpc.xds.XdsTestUtils.CLUSTER_NAME; +import static io.grpc.xds.XdsTestUtils.EDS_NAME; +import static io.grpc.xds.XdsTestUtils.ENDPOINT_HOSTNAME; +import static io.grpc.xds.XdsTestUtils.ENDPOINT_PORT; +import static io.grpc.xds.XdsTestUtils.RDS_NAME; +import static io.grpc.xds.XdsTestUtils.buildRouteConfiguration; +import static io.grpc.xds.XdsTestUtils.getWrrLbConfigAsMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; import com.google.protobuf.Empty; import com.google.protobuf.Message; import com.google.protobuf.UInt64Value; +import io.envoyproxy.envoy.config.route.v3.RouteConfiguration; import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig; import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.TokenCacheConfig; import io.grpc.CallOptions; import io.grpc.Channel; +import io.grpc.ClientCall; import io.grpc.ClientInterceptor; import io.grpc.MethodDescriptor; +import io.grpc.Status; +import io.grpc.StatusOr; +import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.testing.TestMethodDescriptors; +import io.grpc.xds.Endpoints.LbEndpoint; +import io.grpc.xds.Endpoints.LocalityLbEndpoints; +import io.grpc.xds.GcpAuthenticationFilter.AudienceMetadataParser.AudienceWrapper; +import io.grpc.xds.GcpAuthenticationFilter.FailingClientCall; import io.grpc.xds.GcpAuthenticationFilter.GcpAuthenticationConfig; +import io.grpc.xds.XdsClusterResource.CdsUpdate; +import io.grpc.xds.XdsConfig.XdsClusterConfig; +import io.grpc.xds.XdsConfig.XdsClusterConfig.EndpointConfig; +import io.grpc.xds.XdsEndpointResource.EdsUpdate; +import io.grpc.xds.XdsListenerResource.LdsUpdate; +import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate; +import io.grpc.xds.client.Locality; +import io.grpc.xds.client.XdsResourceType; +import io.grpc.xds.client.XdsResourceType.ResourceInvalidException; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -46,6 +81,17 @@ public class GcpAuthenticationFilterTest { private static final GcpAuthenticationFilter.Provider FILTER_PROVIDER = new GcpAuthenticationFilter.Provider(); + private static final String serverName = InProcessServerBuilder.generateName(); + private static final LdsUpdate ldsUpdate = getLdsUpdate(); + private static final EdsUpdate edsUpdate = getEdsUpdate(); + private static final RdsUpdate rdsUpdate = getRdsUpdate(); + private static final CdsUpdate cdsUpdate = getCdsUpdate(); + + @Test + public void testNewFilterInstancesPerFilterName() { + assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1")) + .isNotEqualTo(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1")); + } @Test public void filterType_clientOnly() { @@ -92,35 +138,258 @@ public void testParseFilterConfig_withInvalidMessageType() { } @Test - public void testClientInterceptor_createsAndReusesCachedCredentials() { + public void testClientInterceptor_success() throws IOException, ResourceInvalidException { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, + cdsUpdate, + new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter(); - - // Create interceptor + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = Mockito.mock(Channel.class); + ArgumentCaptor callOptionsCaptor = ArgumentCaptor.forClass(CallOptions.class); + + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); - // Mock channel and capture CallOptions + verify(mockChannel).newCall(eq(methodDescriptor), callOptionsCaptor.capture()); + CallOptions capturedOptions = callOptionsCaptor.getAllValues().get(0); + assertNotNull(capturedOptions.getCredentials()); + } + + @Test + public void testClientInterceptor_createsAndReusesCachedCredentials() + throws IOException, ResourceInvalidException { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, + cdsUpdate, + new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = Mockito.mock(Channel.class); ArgumentCaptor callOptionsCaptor = ArgumentCaptor.forClass(CallOptions.class); - // Execute interception twice to check caching - interceptor.interceptCall(methodDescriptor, CallOptions.DEFAULT, mockChannel); - interceptor.interceptCall(methodDescriptor, CallOptions.DEFAULT, mockChannel); + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); - // Capture and verify CallOptions for CallCredentials presence - Mockito.verify(mockChannel, Mockito.times(2)) + verify(mockChannel, Mockito.times(2)) .newCall(eq(methodDescriptor), callOptionsCaptor.capture()); - - // Retrieve the CallOptions captured from both calls CallOptions firstCapturedOptions = callOptionsCaptor.getAllValues().get(0); CallOptions secondCapturedOptions = callOptionsCaptor.getAllValues().get(1); - - // Ensure that CallCredentials was added assertNotNull(firstCapturedOptions.getCredentials()); assertNotNull(secondCapturedOptions.getCredentials()); - - // Ensure that the CallCredentials from both calls are the same, indicating caching assertSame(firstCapturedOptions.getCredentials(), secondCapturedOptions.getCredentials()); } + + @Test + public void testClientInterceptor_withoutClusterSelectionKey() throws Exception { + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = mock(Channel.class); + CallOptions callOptionsWithXds = CallOptions.DEFAULT; + + ClientCall call = interceptor.interceptCall( + methodDescriptor, callOptionsWithXds, mockChannel); + + assertTrue(call instanceof FailingClientCall); + FailingClientCall clientCall = (FailingClientCall) call; + assertThat(clientCall.error.getDescription()).contains("does not contain cluster resource"); + } + + @Test + public void testClientInterceptor_clusterSelectionKeyWithoutPrefix() throws Exception { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, + cdsUpdate, + new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + Channel mockChannel = mock(Channel.class); + + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + + verify(mockChannel).newCall(methodDescriptor, callOptionsWithXds); + } + + @Test + public void testClientInterceptor_xdsConfigDoesNotExist() throws Exception { + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = mock(Channel.class); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0"); + + ClientCall call = + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + + assertTrue(call instanceof FailingClientCall); + FailingClientCall clientCall = (FailingClientCall) call; + assertThat(clientCall.error.getDescription()).contains("does not contain xds configuration"); + } + + @Test + public void testClientInterceptor_incorrectClusterName() throws Exception { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, + cdsUpdate, + new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster("custer0", StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = mock(Channel.class); + + ClientCall call = + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + + assertTrue(call instanceof FailingClientCall); + FailingClientCall clientCall = (FailingClientCall) call; + assertThat(clientCall.error.getDescription()).contains("does not contain xds cluster"); + } + + @Test + public void testClientInterceptor_statusOrError() throws Exception { + StatusOr errorCluster = + StatusOr.fromStatus(Status.NOT_FOUND.withDescription("Cluster resource not found")); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, errorCluster).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = mock(Channel.class); + + ClientCall call = + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + + assertTrue(call instanceof FailingClientCall); + FailingClientCall clientCall = (FailingClientCall) call; + assertThat(clientCall.error.getDescription()).contains("Cluster resource not found"); + } + + @Test + public void testClientInterceptor_notAudienceWrapper() + throws IOException, ResourceInvalidException { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, + getCdsUpdateWithIncorrectAudienceWrapper(), + new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = Mockito.mock(Channel.class); + + ClientCall call = + interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + + assertTrue(call instanceof FailingClientCall); + FailingClientCall clientCall = (FailingClientCall) call; + assertThat(clientCall.error.getDescription()).contains("GCP Authn found wrong type"); + } + + private static LdsUpdate getLdsUpdate() { + Filter.NamedFilterConfig routerFilterConfig = new Filter.NamedFilterConfig( + serverName, RouterFilter.ROUTER_CONFIG); + HttpConnectionManager httpConnectionManager = HttpConnectionManager.forRdsName( + 0L, RDS_NAME, Collections.singletonList(routerFilterConfig)); + return XdsListenerResource.LdsUpdate.forApiListener(httpConnectionManager); + } + + private static RdsUpdate getRdsUpdate() { + RouteConfiguration routeConfiguration = + buildRouteConfiguration(serverName, RDS_NAME, CLUSTER_NAME); + XdsResourceType.Args args = new XdsResourceType.Args(null, "0", "0", null, null, null); + try { + return XdsRouteConfigureResource.getInstance().doParse(args, routeConfiguration); + } catch (ResourceInvalidException ex) { + return null; + } + } + + private static EdsUpdate getEdsUpdate() { + Map lbEndpointsMap = new HashMap<>(); + LbEndpoint lbEndpoint = LbEndpoint.create( + serverName, ENDPOINT_PORT, 0, true, ENDPOINT_HOSTNAME, ImmutableMap.of()); + lbEndpointsMap.put( + Locality.create("", "", ""), + LocalityLbEndpoints.create(ImmutableList.of(lbEndpoint), 10, 0, ImmutableMap.of())); + return new XdsEndpointResource.EdsUpdate(EDS_NAME, lbEndpointsMap, Collections.emptyList()); + } + + private static CdsUpdate getCdsUpdate() { + ImmutableMap.Builder parsedMetadata = ImmutableMap.builder(); + parsedMetadata.put("FILTER_INSTANCE_NAME", new AudienceWrapper("TEST_AUDIENCE")); + try { + CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds( + CLUSTER_NAME, EDS_NAME, null, null, null, null, false) + .lbPolicyConfig(getWrrLbConfigAsMap()); + return cdsUpdate.parsedMetadata(parsedMetadata.build()).build(); + } catch (IOException ex) { + return null; + } + } + + private static CdsUpdate getCdsUpdateWithIncorrectAudienceWrapper() throws IOException { + ImmutableMap.Builder parsedMetadata = ImmutableMap.builder(); + parsedMetadata.put("FILTER_INSTANCE_NAME", "TEST_AUDIENCE"); + CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds( + CLUSTER_NAME, EDS_NAME, null, null, null, null, false) + .lbPolicyConfig(getWrrLbConfigAsMap()); + return cdsUpdate.parsedMetadata(parsedMetadata.build()).build(); + } } diff --git a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java index bfaa17245cf..e53ed9047ca 100644 --- a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java +++ b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java @@ -129,6 +129,7 @@ import io.grpc.xds.Endpoints.LbEndpoint; import io.grpc.xds.Endpoints.LocalityLbEndpoints; import io.grpc.xds.Filter.FilterConfig; +import io.grpc.xds.GcpAuthenticationFilter.AudienceMetadataParser.AudienceWrapper; import io.grpc.xds.MetadataRegistry.MetadataValueParser; import io.grpc.xds.RouteLookupServiceClusterSpecifierPlugin.RlsPluginConfig; import io.grpc.xds.VirtualHost.Route; @@ -2417,8 +2418,7 @@ public Object parse(Any value) { } @Test - public void processCluster_parsesAudienceMetadata() - throws ResourceInvalidException, InvalidProtocolBufferException { + public void processCluster_parsesAudienceMetadata() throws Exception { MetadataRegistry.getInstance(); Audience audience = Audience.newBuilder() @@ -2462,7 +2462,10 @@ public void processCluster_parsesAudienceMetadata() "FILTER_METADATA", ImmutableMap.of( "key1", "value1", "key2", 42.0)); - assertThat(update.parsedMetadata()).isEqualTo(expectedParsedMetadata); + assertThat(update.parsedMetadata().get("FILTER_METADATA")) + .isEqualTo(expectedParsedMetadata.get("FILTER_METADATA")); + assertThat(update.parsedMetadata().get("AUDIENCE_METADATA")) + .isInstanceOf(AudienceWrapper.class); } @Test @@ -2519,8 +2522,7 @@ public void processCluster_parsesAddressMetadata() throws Exception { } @Test - public void processCluster_metadataKeyCollision_resolvesToTypedMetadata() - throws ResourceInvalidException, InvalidProtocolBufferException { + public void processCluster_metadataKeyCollision_resolvesToTypedMetadata() throws Exception { MetadataRegistry metadataRegistry = MetadataRegistry.getInstance(); MetadataValueParser testParser = @@ -2575,8 +2577,7 @@ public Object parse(Any value) { } @Test - public void parseNonAggregateCluster_withHttp11ProxyTransportSocket() - throws ResourceInvalidException, InvalidProtocolBufferException { + public void parseNonAggregateCluster_withHttp11ProxyTransportSocket() throws Exception { XdsClusterResource.isEnabledXdsHttpConnect = true; Http11ProxyUpstreamTransport http11ProxyUpstreamTransport = diff --git a/xds/src/test/java/io/grpc/xds/XdsTestUtils.java b/xds/src/test/java/io/grpc/xds/XdsTestUtils.java index 9f90777be3d..52953ef5407 100644 --- a/xds/src/test/java/io/grpc/xds/XdsTestUtils.java +++ b/xds/src/test/java/io/grpc/xds/XdsTestUtils.java @@ -291,7 +291,7 @@ static Map createMinimalLbEndpointsMap(String ser } @SuppressWarnings("unchecked") - private static ImmutableMap getWrrLbConfigAsMap() throws IOException { + static ImmutableMap getWrrLbConfigAsMap() throws IOException { String lbConfigStr = "{\"wrr_locality_experimental\" : " + "{ \"childPolicy\" : [{\"round_robin\" : {}}]}}"; From 8bf12c67de8a0dd22aa5642f33b294934ca23bdd Mon Sep 17 00:00:00 2001 From: MV Shiva Date: Fri, 23 May 2025 14:48:17 +0530 Subject: [PATCH 11/14] xds: float LRU cache across interceptors (#11992) (#12096) --- .../io/grpc/xds/GcpAuthenticationFilter.java | 60 ++++--- .../grpc/xds/GcpAuthenticationFilterTest.java | 146 ++++++++++++++++-- 2 files changed, 175 insertions(+), 31 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java index b5568efe400..8ec02f4f809 100644 --- a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java +++ b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java @@ -59,15 +59,17 @@ final class GcpAuthenticationFilter implements Filter { static final String TYPE_URL = "type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig"; - + private final LruCache callCredentialsCache; final String filterInstanceName; - GcpAuthenticationFilter(String name) { + GcpAuthenticationFilter(String name, int cacheSize) { filterInstanceName = checkNotNull(name, "name"); + this.callCredentialsCache = new LruCache<>(cacheSize); } - static final class Provider implements Filter.Provider { + private final int cacheSize = 10; + @Override public String[] typeUrls() { return new String[]{TYPE_URL}; @@ -80,7 +82,7 @@ public boolean isClientFilter() { @Override public GcpAuthenticationFilter newInstance(String name) { - return new GcpAuthenticationFilter(name); + return new GcpAuthenticationFilter(name, cacheSize); } @Override @@ -101,11 +103,14 @@ public ConfigOrError parseFilterConfig(Message rawProto // Validate cache_config if (gcpAuthnProto.hasCacheConfig()) { TokenCacheConfig cacheConfig = gcpAuthnProto.getCacheConfig(); - cacheSize = cacheConfig.getCacheSize().getValue(); - if (cacheSize == 0) { - return ConfigOrError.fromError( - "cache_config.cache_size must be greater than zero"); + if (cacheConfig.hasCacheSize()) { + cacheSize = cacheConfig.getCacheSize().getValue(); + if (cacheSize == 0) { + return ConfigOrError.fromError( + "cache_config.cache_size must be greater than zero"); + } } + // LruCache's size is an int and briefly exceeds its maximum size before evicting entries cacheSize = UnsignedLongs.min(cacheSize, Integer.MAX_VALUE - 1); } @@ -127,8 +132,9 @@ public ClientInterceptor buildClientInterceptor(FilterConfig config, @Nullable FilterConfig overrideConfig, ScheduledExecutorService scheduler) { ComputeEngineCredentials credentials = ComputeEngineCredentials.create(); - LruCache callCredentialsCache = - new LruCache<>(((GcpAuthenticationConfig) config).getCacheSize()); + synchronized (callCredentialsCache) { + callCredentialsCache.resizeCache(((GcpAuthenticationConfig) config).getCacheSize()); + } return new ClientInterceptor() { @Override public ClientCall interceptCall( @@ -254,23 +260,37 @@ public void sendMessage(ReqT message) {} private static final class LruCache { - private final Map cache; + private Map cache; + private int maxSize; LruCache(int maxSize) { - this.cache = new LinkedHashMap( - maxSize, - 0.75f, - true) { - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > maxSize; - } - }; + this.maxSize = maxSize; + this.cache = createEvictingMap(maxSize); } V getOrInsert(K key, Function create) { return cache.computeIfAbsent(key, create); } + + private void resizeCache(int newSize) { + if (newSize >= maxSize) { + maxSize = newSize; + return; + } + Map newCache = createEvictingMap(newSize); + maxSize = newSize; + newCache.putAll(cache); + cache = newCache; + } + + private Map createEvictingMap(int size) { + return new LinkedHashMap(size, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > LruCache.this.maxSize; + } + }; + } } static class AudienceMetadataParser implements MetadataValueParser { diff --git a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java index a5e142b4094..d84d8c9d768 100644 --- a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java +++ b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java @@ -28,11 +28,13 @@ import static io.grpc.xds.XdsTestUtils.getWrrLbConfigAsMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; @@ -89,8 +91,8 @@ public class GcpAuthenticationFilterTest { @Test public void testNewFilterInstancesPerFilterName() { - assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1")) - .isNotEqualTo(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1")); + assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1", 10)) + .isNotEqualTo(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1", 10)); } @Test @@ -152,7 +154,7 @@ public void testClientInterceptor_success() throws IOException, ResourceInvalidE .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = Mockito.mock(Channel.class); @@ -181,7 +183,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials() .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = Mockito.mock(Channel.class); @@ -190,7 +192,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials() interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); - verify(mockChannel, Mockito.times(2)) + verify(mockChannel, times(2)) .newCall(eq(methodDescriptor), callOptionsCaptor.capture()); CallOptions firstCapturedOptions = callOptionsCaptor.getAllValues().get(0); CallOptions secondCapturedOptions = callOptionsCaptor.getAllValues().get(1); @@ -202,7 +204,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials() @Test public void testClientInterceptor_withoutClusterSelectionKey() throws Exception { GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = mock(Channel.class); @@ -233,7 +235,7 @@ public void testClientInterceptor_clusterSelectionKeyWithoutPrefix() throws Exce Channel mockChannel = mock(Channel.class); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); @@ -244,7 +246,7 @@ public void testClientInterceptor_clusterSelectionKeyWithoutPrefix() throws Exce @Test public void testClientInterceptor_xdsConfigDoesNotExist() throws Exception { GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = mock(Channel.class); @@ -274,7 +276,7 @@ public void testClientInterceptor_incorrectClusterName() throws Exception { .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster") .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = mock(Channel.class); @@ -300,7 +302,7 @@ public void testClientInterceptor_statusOrError() throws Exception { .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = mock(Channel.class); @@ -329,7 +331,7 @@ public void testClientInterceptor_notAudienceWrapper() .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); GcpAuthenticationConfig config = new GcpAuthenticationConfig(10); - GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME"); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10); ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null); MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); Channel mockChannel = Mockito.mock(Channel.class); @@ -342,6 +344,115 @@ public void testClientInterceptor_notAudienceWrapper() assertThat(clientCall.error.getDescription()).contains("GCP Authn found wrong type"); } + @Test + public void testLruCacheAcrossInterceptors() throws IOException, ResourceInvalidException { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, cdsUpdate, new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 2); + ClientInterceptor interceptor1 + = filter.buildClientInterceptor(new GcpAuthenticationConfig(2), null, null); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + Channel mockChannel = Mockito.mock(Channel.class); + ArgumentCaptor callOptionsCaptor = ArgumentCaptor.forClass(CallOptions.class); + + interceptor1.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + verify(mockChannel).newCall(eq(methodDescriptor), callOptionsCaptor.capture()); + CallOptions capturedOptions1 = callOptionsCaptor.getAllValues().get(0); + assertNotNull(capturedOptions1.getCredentials()); + ClientInterceptor interceptor2 + = filter.buildClientInterceptor(new GcpAuthenticationConfig(1), null, null); + interceptor2.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel); + verify(mockChannel, times(2)) + .newCall(eq(methodDescriptor), callOptionsCaptor.capture()); + CallOptions capturedOptions2 = callOptionsCaptor.getAllValues().get(1); + assertNotNull(capturedOptions2.getCredentials()); + + assertSame(capturedOptions1.getCredentials(), capturedOptions2.getCredentials()); + } + + @Test + public void testLruCacheEvictionOnResize() throws IOException, ResourceInvalidException { + XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, cdsUpdate, new EndpointConfig(StatusOr.fromValue(edsUpdate))); + XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + CallOptions callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 2); + MethodDescriptor methodDescriptor = TestMethodDescriptors.voidMethod(); + + ClientInterceptor interceptor1 = + filter.buildClientInterceptor(new GcpAuthenticationConfig(2), null, null); + Channel mockChannel1 = Mockito.mock(Channel.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(CallOptions.class); + interceptor1.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel1); + verify(mockChannel1).newCall(eq(methodDescriptor), captor.capture()); + CallOptions options1 = captor.getValue(); + // This will recreate the cache with max size of 1 and copy the credential for audience1. + ClientInterceptor interceptor2 = + filter.buildClientInterceptor(new GcpAuthenticationConfig(1), null, null); + Channel mockChannel2 = Mockito.mock(Channel.class); + interceptor2.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel2); + verify(mockChannel2).newCall(eq(methodDescriptor), captor.capture()); + CallOptions options2 = captor.getValue(); + + assertSame(options1.getCredentials(), options2.getCredentials()); + + clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, getCdsUpdate2(), new EndpointConfig(StatusOr.fromValue(edsUpdate))); + defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + + // This will evict the credential for audience1 and add new credential for audience2 + ClientInterceptor interceptor3 = + filter.buildClientInterceptor(new GcpAuthenticationConfig(1), null, null); + Channel mockChannel3 = Mockito.mock(Channel.class); + interceptor3.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel3); + verify(mockChannel3).newCall(eq(methodDescriptor), captor.capture()); + CallOptions options3 = captor.getValue(); + + assertNotSame(options1.getCredentials(), options3.getCredentials()); + + clusterConfig = new XdsConfig.XdsClusterConfig( + CLUSTER_NAME, cdsUpdate, new EndpointConfig(StatusOr.fromValue(edsUpdate))); + defaultXdsConfig = new XdsConfig.XdsConfigBuilder() + .setListener(ldsUpdate) + .setRoute(rdsUpdate) + .setVirtualHost(rdsUpdate.virtualHosts.get(0)) + .addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build(); + callOptionsWithXds = CallOptions.DEFAULT + .withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0") + .withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig); + + // This will create new credential for audience1 because it has been evicted + ClientInterceptor interceptor4 = + filter.buildClientInterceptor(new GcpAuthenticationConfig(1), null, null); + Channel mockChannel4 = Mockito.mock(Channel.class); + interceptor4.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel4); + verify(mockChannel4).newCall(eq(methodDescriptor), captor.capture()); + CallOptions options4 = captor.getValue(); + + assertNotSame(options1.getCredentials(), options4.getCredentials()); + } + private static LdsUpdate getLdsUpdate() { Filter.NamedFilterConfig routerFilterConfig = new Filter.NamedFilterConfig( serverName, RouterFilter.ROUTER_CONFIG); @@ -384,6 +495,19 @@ private static CdsUpdate getCdsUpdate() { } } + private static CdsUpdate getCdsUpdate2() { + ImmutableMap.Builder parsedMetadata = ImmutableMap.builder(); + parsedMetadata.put("FILTER_INSTANCE_NAME", new AudienceWrapper("NEW_TEST_AUDIENCE")); + try { + CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds( + CLUSTER_NAME, EDS_NAME, null, null, null, null, false) + .lbPolicyConfig(getWrrLbConfigAsMap()); + return cdsUpdate.parsedMetadata(parsedMetadata.build()).build(); + } catch (IOException ex) { + return null; + } + } + private static CdsUpdate getCdsUpdateWithIncorrectAudienceWrapper() throws IOException { ImmutableMap.Builder parsedMetadata = ImmutableMap.builder(); parsedMetadata.put("FILTER_INSTANCE_NAME", "TEST_AUDIENCE"); From c010742cb32ec37ffef3de1252e4835e71d3c0bc Mon Sep 17 00:00:00 2001 From: MV Shiva Date: Fri, 23 May 2025 15:55:05 +0530 Subject: [PATCH 12/14] xds: Add GcpAuthenticationFilter to FilterRegistry (#12075) (#12097) --- xds/src/main/java/io/grpc/xds/FilterRegistry.java | 7 +++++++ .../java/io/grpc/xds/GcpAuthenticationFilter.java | 5 +++++ .../io/grpc/xds/GcpAuthenticationFilterTest.java | 6 ++++++ .../java/io/grpc/xds/GrpcXdsClientImplDataTest.java | 13 +++++++++---- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/FilterRegistry.java b/xds/src/main/java/io/grpc/xds/FilterRegistry.java index 426c6d1b3f6..1fbccea8000 100644 --- a/xds/src/main/java/io/grpc/xds/FilterRegistry.java +++ b/xds/src/main/java/io/grpc/xds/FilterRegistry.java @@ -17,6 +17,7 @@ package io.grpc.xds; import com.google.common.annotations.VisibleForTesting; +import io.grpc.internal.GrpcUtil; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; @@ -32,12 +33,18 @@ final class FilterRegistry { private FilterRegistry() {} + static boolean isEnabledGcpAuthnFilter = + GrpcUtil.getFlag("GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER", false); + static synchronized FilterRegistry getDefaultRegistry() { if (instance == null) { instance = newRegistry().register( new FaultFilter.Provider(), new RouterFilter.Provider(), new RbacFilter.Provider()); + if (isEnabledGcpAuthnFilter) { + instance.register(new GcpAuthenticationFilter.Provider()); + } } return instance; } diff --git a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java index 8ec02f4f809..dc133eaaf1a 100644 --- a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java +++ b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java @@ -17,6 +17,7 @@ package io.grpc.xds; import static com.google.common.base.Preconditions.checkNotNull; +import static io.grpc.xds.FilterRegistry.isEnabledGcpAuthnFilter; import static io.grpc.xds.XdsNameResolver.CLUSTER_SELECTION_KEY; import static io.grpc.xds.XdsNameResolver.XDS_CONFIG_CALL_OPTION_KEY; @@ -312,6 +313,10 @@ public String getTypeUrl() { public AudienceWrapper parse(Any any) throws ResourceInvalidException { Audience audience; try { + if (!isEnabledGcpAuthnFilter) { + throw new InvalidProtocolBufferException("Environment variable for GCP Authentication " + + "Filter is Not Set"); + } audience = any.unpack(Audience.class); } catch (InvalidProtocolBufferException ex) { throw new ResourceInvalidException("Invalid Resource in address proto", ex); diff --git a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java index d84d8c9d768..cebf739d417 100644 --- a/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java +++ b/xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java @@ -73,6 +73,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -89,6 +90,11 @@ public class GcpAuthenticationFilterTest { private static final RdsUpdate rdsUpdate = getRdsUpdate(); private static final CdsUpdate cdsUpdate = getCdsUpdate(); + @Before + public void setUp() { + System.setProperty("GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER", "true"); + } + @Test public void testNewFilterInstancesPerFilterName() { assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1", 10)) diff --git a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java index e53ed9047ca..d6f711ee20c 100644 --- a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java +++ b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java @@ -2419,6 +2419,7 @@ public Object parse(Any value) { @Test public void processCluster_parsesAudienceMetadata() throws Exception { + FilterRegistry.isEnabledGcpAuthnFilter = true; MetadataRegistry.getInstance(); Audience audience = Audience.newBuilder() @@ -2462,10 +2463,14 @@ public void processCluster_parsesAudienceMetadata() throws Exception { "FILTER_METADATA", ImmutableMap.of( "key1", "value1", "key2", 42.0)); - assertThat(update.parsedMetadata().get("FILTER_METADATA")) - .isEqualTo(expectedParsedMetadata.get("FILTER_METADATA")); - assertThat(update.parsedMetadata().get("AUDIENCE_METADATA")) - .isInstanceOf(AudienceWrapper.class); + try { + assertThat(update.parsedMetadata().get("FILTER_METADATA")) + .isEqualTo(expectedParsedMetadata.get("FILTER_METADATA")); + assertThat(update.parsedMetadata().get("AUDIENCE_METADATA")) + .isInstanceOf(AudienceWrapper.class); + } finally { + FilterRegistry.isEnabledGcpAuthnFilter = false; + } } @Test From 2c7630413860a1bf53c84500fca38fde8953dc07 Mon Sep 17 00:00:00 2001 From: John Cormie Date: Mon, 23 Jun 2025 12:00:25 -0700 Subject: [PATCH 13/14] download maven using archive/permalink url (#12169) --- buildscripts/grpc-java-artifacts/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/grpc-java-artifacts/Dockerfile b/buildscripts/grpc-java-artifacts/Dockerfile index 736babe9d8e..bf71a710d74 100644 --- a/buildscripts/grpc-java-artifacts/Dockerfile +++ b/buildscripts/grpc-java-artifacts/Dockerfile @@ -28,6 +28,6 @@ RUN mkdir -p "$ANDROID_HOME/cmdline-tools" && \ yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses # Install Maven -RUN curl -Ls https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz | \ +RUN curl -Ls https://archive.apache.org/dist/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz | \ tar xz -C /var/local ENV PATH /var/local/apache-maven-3.8.8/bin:$PATH From 317709bc027c973a1a90e18e40e0b48218fa4fed Mon Sep 17 00:00:00 2001 From: eshitachandwani <59800922+eshitachandwani@users.noreply.github.com> Date: Thu, 26 Jun 2025 14:25:36 +0530 Subject: [PATCH 14/14] kokoro: add spiffe tests config (1.72.x backport) Backport of #12133 --- buildscripts/kokoro/psm-spiffe.cfg | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 buildscripts/kokoro/psm-spiffe.cfg diff --git a/buildscripts/kokoro/psm-spiffe.cfg b/buildscripts/kokoro/psm-spiffe.cfg new file mode 100644 index 00000000000..b04d715fca1 --- /dev/null +++ b/buildscripts/kokoro/psm-spiffe.cfg @@ -0,0 +1,17 @@ +# Config file for internal CI + +# Location of the continuous shell script in repository. +build_file: "grpc-java/buildscripts/kokoro/psm-interop-test-java.sh" +timeout_mins: 240 + +action { + define_artifacts { + regex: "artifacts/**/*sponge_log.xml" + regex: "artifacts/**/*.log" + strip_prefix: "artifacts" + } +} +env_vars { + key: "PSM_TEST_SUITE" + value: "spiffe" +}