From b6eafbe695939436f87bd0c3bb089244c3986602 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Tue, 9 Nov 2021 08:41:11 -0800 Subject: [PATCH 0001/2009] netty: Add system property to disable Connection header check A user has a proxy that is sending "Connection: close", which is against the HTTP/2 spec, but will take time to fix. Fixes #8674 --- netty/src/main/java/io/grpc/netty/NettyServerHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyServerHandler.java b/netty/src/main/java/io/grpc/netty/NettyServerHandler.java index c286c17f640..f552b937a05 100644 --- a/netty/src/main/java/io/grpc/netty/NettyServerHandler.java +++ b/netty/src/main/java/io/grpc/netty/NettyServerHandler.java @@ -109,6 +109,9 @@ class NettyServerHandler extends AbstractNettyHandler { @VisibleForTesting static final long GRACEFUL_SHUTDOWN_PING = 0x97ACEF001L; private static final long GRACEFUL_SHUTDOWN_PING_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(10); + /** Temporary workaround for #8674. Fine to delete after v1.45 release, and maybe earlier. */ + private static final boolean DISABLE_CONNECTION_HEADER_CHECK = Boolean.parseBoolean( + System.getProperty("io.grpc.netty.disableConnectionHeaderCheck", "false")); private final Http2Connection.PropertyKey streamKey; private final ServerTransportListener transportListener; @@ -380,7 +383,7 @@ private void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers try { // Connection-specific header fields makes a request malformed. Ideally this would be handled // by Netty. RFC 7540 section 8.1.2.2 - if (headers.contains(CONNECTION)) { + if (!DISABLE_CONNECTION_HEADER_CHECK && headers.contains(CONNECTION)) { resetStream(ctx, streamId, Http2Error.PROTOCOL_ERROR.code(), ctx.newPromise()); return; } From 6518d7bd6dc496c89ff320e06c73424f26af364a Mon Sep 17 00:00:00 2001 From: Kevin Wooten Date: Tue, 9 Nov 2021 11:36:04 -0700 Subject: [PATCH 0002/2009] Copy macOS x86 artifacts to aarch during upload (#8680) --- buildscripts/kokoro/upload_artifacts.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildscripts/kokoro/upload_artifacts.sh b/buildscripts/kokoro/upload_artifacts.sh index 8d7f2f5b365..20e16c38a2f 100644 --- a/buildscripts/kokoro/upload_artifacts.sh +++ b/buildscripts/kokoro/upload_artifacts.sh @@ -33,6 +33,8 @@ LOCAL_OTHER_ARTIFACTS="$KOKORO_GFILE_DIR"/github/grpc-java/artifacts/ # from macos job: [[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'protoc-gen-grpc-java-*-osx-x86_64.exe' | wc -l)" != '0' ]] +# copy all x86 artifacts to aarch until native artifacts are built +find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'protoc-gen-grpc-java-*-osx-x86_64.exe*' -exec bash -c 'cp "${0}" "${0/x86/aarch}"' {} \; # from windows job: [[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'protoc-gen-grpc-java-*-windows-x86_64.exe' | wc -l)" != '0' ]] From 389b865b9ba88cc16354b84023cf21a1a8e2e632 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Tue, 9 Nov 2021 16:37:54 -0800 Subject: [PATCH 0003/2009] xds: populate LRS ServerInfo to CdsUpdate (#8676) Replace `String lrsServerName` with `ServerInfo lrsServerInfo` in `CdsUpdate`. See http://go/grpc-xds-federation#heading=h.gh3gjftay27x for details. This PR is only refactoring. Federation support is not implemented until the TODO [here](https://github.com/grpc/grpc-java/blob/a5c526c12f699af9a846d9faabc18038ef431675/xds/src/main/java/io/grpc/xds/ClientXdsClient.java#L2280) is addressed. Resolves #8628 --- .../java/io/grpc/xds/CdsLoadBalancer2.java | 4 +- .../java/io/grpc/xds/ClientXdsClient.java | 27 +++++---- .../io/grpc/xds/ClusterImplLoadBalancer.java | 27 ++++----- .../xds/ClusterImplLoadBalancerProvider.java | 11 ++-- .../grpc/xds/ClusterResolverLoadBalancer.java | 31 ++++++----- .../ClusterResolverLoadBalancerProvider.java | 23 ++++---- xds/src/main/java/io/grpc/xds/XdsClient.java | 24 ++++---- .../io/grpc/xds/CdsLoadBalancer2Test.java | 55 ++++++++++--------- .../io/grpc/xds/ClientXdsClientDataTest.java | 14 +++-- .../io/grpc/xds/ClientXdsClientTestBase.java | 33 ++++++----- .../grpc/xds/ClusterImplLoadBalancerTest.java | 37 +++++++------ .../xds/ClusterResolverLoadBalancerTest.java | 25 +++++---- 12 files changed, 167 insertions(+), 144 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java index 4af187bf1dd..396292a2392 100644 --- a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java +++ b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java @@ -157,12 +157,12 @@ private void handleClusterDiscovered() { if (clusterState.result.clusterType() == ClusterType.EDS) { instance = DiscoveryMechanism.forEds( clusterState.name, clusterState.result.edsServiceName(), - clusterState.result.lrsServerName(), clusterState.result.maxConcurrentRequests(), + clusterState.result.lrsServerInfo(), clusterState.result.maxConcurrentRequests(), clusterState.result.upstreamTlsContext()); } else { // logical DNS instance = DiscoveryMechanism.forLogicalDns( clusterState.name, clusterState.result.dnsHostName(), - clusterState.result.lrsServerName(), clusterState.result.maxConcurrentRequests(), + clusterState.result.lrsServerInfo(), clusterState.result.maxConcurrentRequests(), clusterState.result.upstreamTlsContext()); } instances.add(instance); diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index 005da16a012..c8172a87d18 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -1471,7 +1471,7 @@ public void handleCdsResponse( if (getBootstrapInfo() != null && getBootstrapInfo().certProviders() != null) { certProviderInstances = getBootstrapInfo().certProviders().keySet(); } - cdsUpdate = parseCluster(cluster, retainedEdsResources, certProviderInstances); + cdsUpdate = parseCluster(cluster, retainedEdsResources, certProviderInstances, serverInfo); } catch (ResourceInvalidException e) { errors.add( "CDS response Cluster '" + clusterName + "' validation error: " + e.getMessage()); @@ -1490,13 +1490,13 @@ public void handleCdsResponse( @VisibleForTesting static CdsUpdate parseCluster(Cluster cluster, Set retainedEdsResources, - Set certProviderInstances) + Set certProviderInstances, ServerInfo serverInfo) throws ResourceInvalidException { StructOrError structOrError; switch (cluster.getClusterDiscoveryTypeCase()) { case TYPE: structOrError = parseNonAggregateCluster(cluster, retainedEdsResources, - certProviderInstances); + certProviderInstances, serverInfo); break; case CLUSTER_TYPE: structOrError = parseAggregateCluster(cluster); @@ -1559,9 +1559,10 @@ private static StructOrError parseAggregateCluster(Cluster cl } private static StructOrError parseNonAggregateCluster( - Cluster cluster, Set edsResources, Set certProviderInstances) { + Cluster cluster, Set edsResources, Set certProviderInstances, + ServerInfo serverInfo) { String clusterName = cluster.getName(); - String lrsServerName = null; + ServerInfo lrsServerInfo = null; Long maxConcurrentRequests = null; UpstreamTlsContext upstreamTlsContext = null; if (cluster.hasLrsServer()) { @@ -1569,7 +1570,7 @@ private static StructOrError parseNonAggregateCluster( return StructOrError.fromError( "Cluster " + clusterName + ": only support LRS for the same management server"); } - lrsServerName = ""; + lrsServerInfo = serverInfo; } if (cluster.hasCircuitBreakers()) { List thresholds = cluster.getCircuitBreakers().getThresholdsList(); @@ -1621,7 +1622,7 @@ private static StructOrError parseNonAggregateCluster( edsResources.add(clusterName); } return StructOrError.fromStruct(CdsUpdate.forEds( - clusterName, edsServiceName, lrsServerName, maxConcurrentRequests, upstreamTlsContext)); + clusterName, edsServiceName, lrsServerInfo, maxConcurrentRequests, upstreamTlsContext)); } else if (type.equals(DiscoveryType.LOGICAL_DNS)) { if (!cluster.hasLoadAssignment()) { return StructOrError.fromError( @@ -1656,7 +1657,7 @@ private static StructOrError parseNonAggregateCluster( String dnsHostName = String.format("%s:%d", socketAddress.getAddress(), socketAddress.getPortValue()); return StructOrError.fromStruct(CdsUpdate.forLogicalDns( - clusterName, dnsHostName, lrsServerName, maxConcurrentRequests, upstreamTlsContext)); + clusterName, dnsHostName, lrsServerInfo, maxConcurrentRequests, upstreamTlsContext)); } return StructOrError.fromError( "Cluster " + clusterName + ": unsupported built-in discovery type: " + type); @@ -2094,15 +2095,14 @@ public void run() { @Override ClusterDropStats addClusterDropStats( - String clusterName, @Nullable String edsServiceName) { + final ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName) { ClusterDropStats dropCounter = loadStatsManager.getClusterDropStats(clusterName, edsServiceName); syncContext.execute(new Runnable() { @Override public void run() { if (!reportingLoad) { - // TODO(https://github.com/grpc/grpc-java/issues/8628): consume ServerInfo arg. - serverLrsClientMap.values().iterator().next().startLoadReporting(); + serverLrsClientMap.get(serverInfo).startLoadReporting(); reportingLoad = true; } } @@ -2112,7 +2112,7 @@ public void run() { @Override ClusterLocalityStats addClusterLocalityStats( - String clusterName, @Nullable String edsServiceName, + final ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName, Locality locality) { ClusterLocalityStats loadCounter = loadStatsManager.getClusterLocalityStats(clusterName, edsServiceName, locality); @@ -2120,8 +2120,7 @@ ClusterLocalityStats addClusterLocalityStats( @Override public void run() { if (!reportingLoad) { - // TODO(https://github.com/grpc/grpc-java/issues/8628): consume ServerInfo arg. - serverLrsClientMap.values().iterator().next().startLoadReporting(); + serverLrsClientMap.get(serverInfo).startLoadReporting(); reportingLoad = true; } } diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java index 330c4e2f7a5..60e6c696daf 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java @@ -35,6 +35,7 @@ import io.grpc.internal.ObjectPool; import io.grpc.util.ForwardingLoadBalancerHelper; import io.grpc.util.ForwardingSubchannel; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig; import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext; @@ -117,17 +118,12 @@ public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) { cluster = config.cluster; edsServiceName = config.edsServiceName; childLbHelper = new ClusterImplLbHelper( - callCounterProvider.getOrCreate(config.cluster, config.edsServiceName)); + callCounterProvider.getOrCreate(config.cluster, config.edsServiceName), + config.lrsServerInfo); childLb = config.childPolicy.getProvider().newLoadBalancer(childLbHelper); // Assume load report server does not change throughout cluster lifetime. - if (config.lrsServerName != null) { - if (config.lrsServerName.isEmpty()) { - dropStats = xdsClient.addClusterDropStats(cluster, edsServiceName); - } else { - logger.log(XdsLogLevel.WARNING, "Cluster {0} config error: can only report load " - + "to the same management server. Config lrsServerName {1} should be empty. ", - cluster, config.lrsServerName); - } + if (config.lrsServerInfo != null) { + dropStats = xdsClient.addClusterDropStats(config.lrsServerInfo, cluster, edsServiceName); } } childLbHelper.updateDropPolicies(config.dropCategories); @@ -183,9 +179,12 @@ private final class ClusterImplLbHelper extends ForwardingLoadBalancerHelper { private long maxConcurrentRequests = DEFAULT_PER_CLUSTER_MAX_CONCURRENT_REQUESTS; @Nullable private SslContextProviderSupplier sslContextProviderSupplier; + @Nullable + private final ServerInfo lrsServerInfo; - private ClusterImplLbHelper(AtomicLong inFlights) { + private ClusterImplLbHelper(AtomicLong inFlights, @Nullable ServerInfo lrsServerInfo) { this.inFlights = checkNotNull(inFlights, "inFlights"); + this.lrsServerInfo = lrsServerInfo; } @Override @@ -218,8 +217,8 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) { if (locality == null) { locality = Locality.create("", "", ""); } - final ClusterLocalityStats localityStats = xdsClient.addClusterLocalityStats( - cluster, edsServiceName, locality); + final ClusterLocalityStats localityStats = lrsServerInfo == null ? null + : xdsClient.addClusterLocalityStats(lrsServerInfo, cluster, edsServiceName, locality); Attributes attrs = args.getAttributes().toBuilder().set( ATTR_CLUSTER_LOCALITY_STATS, localityStats).build(); args = args.toBuilder().setAddresses(addresses).setAttributes(attrs).build(); @@ -228,7 +227,9 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) { return new ForwardingSubchannel() { @Override public void shutdown() { - localityStats.release(); + if (localityStats != null) { + localityStats.release(); + } delegate().shutdown(); } diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancerProvider.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancerProvider.java index 939734fe4f0..11e649474b7 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancerProvider.java +++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancerProvider.java @@ -26,6 +26,7 @@ import io.grpc.LoadBalancerRegistry; import io.grpc.NameResolver.ConfigOrError; import io.grpc.internal.ServiceConfigUtil.PolicySelection; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext; import java.util.ArrayList; @@ -73,9 +74,9 @@ static final class ClusterImplConfig { // Resource name used in discovering endpoints via EDS. Only valid for EDS clusters. @Nullable final String edsServiceName; - // Load report server name. Null if load reporting is disabled. + // Load report server info. Null if load reporting is disabled. @Nullable - final String lrsServerName; + final ServerInfo lrsServerInfo; // Cluster-level max concurrent request threshold. Null if not specified. @Nullable final Long maxConcurrentRequests; @@ -88,12 +89,12 @@ static final class ClusterImplConfig { final PolicySelection childPolicy; ClusterImplConfig(String cluster, @Nullable String edsServiceName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, List dropCategories, PolicySelection childPolicy, @Nullable UpstreamTlsContext tlsContext) { this.cluster = checkNotNull(cluster, "cluster"); this.edsServiceName = edsServiceName; - this.lrsServerName = lrsServerName; + this.lrsServerInfo = lrsServerInfo; this.maxConcurrentRequests = maxConcurrentRequests; this.tlsContext = tlsContext; this.dropCategories = Collections.unmodifiableList( @@ -106,7 +107,7 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("cluster", cluster) .add("edsServiceName", edsServiceName) - .add("lrsServerName", lrsServerName) + .add("lrsServerInfo", lrsServerInfo) .add("maxConcurrentRequests", maxConcurrentRequests) // Exclude tlsContext as its string representation is cumbersome. .add("dropCategories", dropCategories) diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java index 9ba7541e314..f4fcabcb21f 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java @@ -39,6 +39,7 @@ import io.grpc.internal.ServiceConfigUtil.PolicySelection; import io.grpc.util.ForwardingLoadBalancerHelper; import io.grpc.util.GracefulSwitchLoadBalancer; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig.DiscoveryMechanism; @@ -174,10 +175,10 @@ public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) { ClusterState state; if (instance.type == DiscoveryMechanism.Type.EDS) { state = new EdsClusterState(instance.cluster, instance.edsServiceName, - instance.lrsServerName, instance.maxConcurrentRequests, instance.tlsContext); + instance.lrsServerInfo, instance.maxConcurrentRequests, instance.tlsContext); } else { // logical DNS state = new LogicalDnsClusterState(instance.cluster, instance.dnsHostName, - instance.lrsServerName, instance.maxConcurrentRequests, instance.tlsContext); + instance.lrsServerInfo, instance.maxConcurrentRequests, instance.tlsContext); } clusterStates.put(instance.cluster, state); state.start(); @@ -305,7 +306,7 @@ private abstract class ClusterState { // Name of the cluster to be resolved. protected final String name; @Nullable - protected final String lrsServerName; + protected final ServerInfo lrsServerInfo; @Nullable protected final Long maxConcurrentRequests; @Nullable @@ -319,10 +320,10 @@ private abstract class ClusterState { protected ClusterResolutionResult result; protected boolean shutdown; - private ClusterState(String name, @Nullable String lrsServerName, + private ClusterState(String name, @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { this.name = name; - this.lrsServerName = lrsServerName; + this.lrsServerInfo = lrsServerInfo; this.maxConcurrentRequests = maxConcurrentRequests; this.tlsContext = tlsContext; } @@ -339,9 +340,9 @@ private final class EdsClusterState extends ClusterState implements EdsResourceW private final String edsServiceName; private EdsClusterState(String name, @Nullable String edsServiceName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { - super(name, lrsServerName, maxConcurrentRequests, tlsContext); + super(name, lrsServerInfo, maxConcurrentRequests, tlsContext); this.edsServiceName = edsServiceName; } @@ -423,7 +424,7 @@ public void run() { Collections.sort(priorities); Map priorityChildConfigs = generateEdsBasedPriorityChildConfigs( - name, edsServiceName, lrsServerName, maxConcurrentRequests, tlsContext, + name, edsServiceName, lrsServerInfo, maxConcurrentRequests, tlsContext, endpointLbPolicy, lbRegistry, prioritizedLocalityWeights, dropOverloads); status = Status.OK; resolved = true; @@ -479,9 +480,9 @@ private final class LogicalDnsClusterState extends ClusterState { private ScheduledHandle scheduledRefresh; private LogicalDnsClusterState(String name, String dnsHostName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { - super(name, lrsServerName, maxConcurrentRequests, tlsContext); + super(name, lrsServerInfo, maxConcurrentRequests, tlsContext); this.dnsHostName = checkNotNull(dnsHostName, "dnsHostName"); nameResolverFactory = checkNotNull(helper.getNameResolverRegistry().asFactory(), "nameResolverFactory"); @@ -568,7 +569,7 @@ public void run() { addresses.add(eag); } PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig( - name, lrsServerName, maxConcurrentRequests, tlsContext, lbRegistry, + name, lrsServerInfo, maxConcurrentRequests, tlsContext, lbRegistry, Collections.emptyList()); status = Status.OK; resolved = true; @@ -651,14 +652,14 @@ private static class ClusterResolutionResult { *

priority LB -> cluster_impl LB (single hardcoded priority) -> pick_first */ private static PriorityChildConfig generateDnsBasedPriorityChildConfig( - String cluster, @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + String cluster, @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext, LoadBalancerRegistry lbRegistry, List dropOverloads) { // Override endpoint-level LB policy with pick_first for logical DNS cluster. PolicySelection endpointLbPolicy = new PolicySelection(lbRegistry.getProvider("pick_first"), null); ClusterImplConfig clusterImplConfig = - new ClusterImplConfig(cluster, null, lrsServerName, maxConcurrentRequests, + new ClusterImplConfig(cluster, null, lrsServerInfo, maxConcurrentRequests, dropOverloads, endpointLbPolicy, tlsContext); LoadBalancerProvider clusterImplLbProvider = lbRegistry.getProvider(XdsLbPolicies.CLUSTER_IMPL_POLICY_NAME); @@ -674,7 +675,7 @@ private static PriorityChildConfig generateDnsBasedPriorityChildConfig( * -> round_robin (one per locality)) / ring_hash */ private static Map generateEdsBasedPriorityChildConfigs( - String cluster, @Nullable String edsServiceName, @Nullable String lrsServerName, + String cluster, @Nullable String edsServiceName, @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext, PolicySelection endpointLbPolicy, LoadBalancerRegistry lbRegistry, Map> prioritizedLocalityWeights, @@ -704,7 +705,7 @@ private static Map generateEdsBasedPriorityChildCon leafPolicy = new PolicySelection(weightedTargetLbProvider, weightedTargetConfig); } ClusterImplConfig clusterImplConfig = - new ClusterImplConfig(cluster, edsServiceName, lrsServerName, maxConcurrentRequests, + new ClusterImplConfig(cluster, edsServiceName, lrsServerInfo, maxConcurrentRequests, dropOverloads, leafPolicy, tlsContext); LoadBalancerProvider clusterImplLbProvider = lbRegistry.getProvider(XdsLbPolicies.CLUSTER_IMPL_POLICY_NAME); diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java index 33b150e667b..551c2c296fc 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java @@ -25,6 +25,7 @@ import io.grpc.LoadBalancerProvider; import io.grpc.NameResolver.ConfigOrError; import io.grpc.internal.ServiceConfigUtil.PolicySelection; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext; import java.util.List; import java.util.Map; @@ -107,9 +108,9 @@ static final class DiscoveryMechanism { final String cluster; // Type of the cluster. final Type type; - // Load reporting server name. Null if not enabled. + // Load reporting server info. Null if not enabled. @Nullable - final String lrsServerName; + final ServerInfo lrsServerInfo; // Cluster-level max concurrent request threshold. Null if not specified. @Nullable final Long maxConcurrentRequests; @@ -129,34 +130,34 @@ enum Type { } private DiscoveryMechanism(String cluster, Type type, @Nullable String edsServiceName, - @Nullable String dnsHostName, @Nullable String lrsServerName, + @Nullable String dnsHostName, @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { this.cluster = checkNotNull(cluster, "cluster"); this.type = checkNotNull(type, "type"); this.edsServiceName = edsServiceName; this.dnsHostName = dnsHostName; - this.lrsServerName = lrsServerName; + this.lrsServerInfo = lrsServerInfo; this.maxConcurrentRequests = maxConcurrentRequests; this.tlsContext = tlsContext; } static DiscoveryMechanism forEds(String cluster, @Nullable String edsServiceName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { - return new DiscoveryMechanism(cluster, Type.EDS, edsServiceName, null, lrsServerName, + return new DiscoveryMechanism(cluster, Type.EDS, edsServiceName, null, lrsServerInfo, maxConcurrentRequests, tlsContext); } static DiscoveryMechanism forLogicalDns(String cluster, String dnsHostName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { return new DiscoveryMechanism(cluster, Type.LOGICAL_DNS, null, dnsHostName, - lrsServerName, maxConcurrentRequests, tlsContext); + lrsServerInfo, maxConcurrentRequests, tlsContext); } @Override public int hashCode() { - return Objects.hash(cluster, type, lrsServerName, maxConcurrentRequests, tlsContext, + return Objects.hash(cluster, type, lrsServerInfo, maxConcurrentRequests, tlsContext, edsServiceName, dnsHostName); } @@ -173,7 +174,7 @@ public boolean equals(Object o) { && type == that.type && Objects.equals(edsServiceName, that.edsServiceName) && Objects.equals(dnsHostName, that.dnsHostName) - && Objects.equals(lrsServerName, that.lrsServerName) + && Objects.equals(lrsServerInfo, that.lrsServerInfo) && Objects.equals(maxConcurrentRequests, that.maxConcurrentRequests) && Objects.equals(tlsContext, that.tlsContext); } @@ -186,7 +187,7 @@ public String toString() { .add("type", type) .add("edsServiceName", edsServiceName) .add("dnsHostName", dnsHostName) - .add("lrsServerName", lrsServerName) + .add("lrsServerInfo", lrsServerInfo) // Exclude tlsContext as its string representation is cumbersome. .add("maxConcurrentRequests", maxConcurrentRequests); return toStringHelper.toString(); diff --git a/xds/src/main/java/io/grpc/xds/XdsClient.java b/xds/src/main/java/io/grpc/xds/XdsClient.java index 1daa257e54e..9a6e28b3f5e 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClient.java +++ b/xds/src/main/java/io/grpc/xds/XdsClient.java @@ -130,10 +130,10 @@ abstract static class CdsUpdate implements ResourceUpdate { @Nullable abstract String dnsHostName(); - // Load report server name for reporting loads via LRS. + // Load report server info for reporting loads via LRS. // Only valid for EDS or LOGICAL_DNS cluster. @Nullable - abstract String lrsServerName(); + abstract ServerInfo lrsServerInfo(); // Max number of concurrent requests can be sent to this cluster. // Only valid for EDS or LOGICAL_DNS cluster. @@ -161,7 +161,7 @@ static Builder forAggregate(String clusterName, List prioritizedClusterN } static Builder forEds(String clusterName, @Nullable String edsServiceName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext upstreamTlsContext) { return new AutoValue_XdsClient_CdsUpdate.Builder() .clusterName(clusterName) @@ -169,13 +169,13 @@ static Builder forEds(String clusterName, @Nullable String edsServiceName, .minRingSize(0) .maxRingSize(0) .edsServiceName(edsServiceName) - .lrsServerName(lrsServerName) + .lrsServerInfo(lrsServerInfo) .maxConcurrentRequests(maxConcurrentRequests) .upstreamTlsContext(upstreamTlsContext); } static Builder forLogicalDns(String clusterName, String dnsHostName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext upstreamTlsContext) { return new AutoValue_XdsClient_CdsUpdate.Builder() .clusterName(clusterName) @@ -183,7 +183,7 @@ static Builder forLogicalDns(String clusterName, String dnsHostName, .minRingSize(0) .maxRingSize(0) .dnsHostName(dnsHostName) - .lrsServerName(lrsServerName) + .lrsServerInfo(lrsServerInfo) .maxConcurrentRequests(maxConcurrentRequests) .upstreamTlsContext(upstreamTlsContext); } @@ -207,7 +207,7 @@ public final String toString() { .add("maxRingSize", maxRingSize()) .add("edsServiceName", edsServiceName()) .add("dnsHostName", dnsHostName()) - .add("lrsServerName", lrsServerName()) + .add("lrsServerInfo", lrsServerInfo()) .add("maxConcurrentRequests", maxConcurrentRequests()) // Exclude upstreamTlsContext as its string representation is cumbersome. .add("prioritizedClusterNames", prioritizedClusterNames()) @@ -246,7 +246,7 @@ Builder ringHashLbPolicy(long minRingSize, long maxRingSize) { protected abstract Builder dnsHostName(String dnsHostName); // Private, use one of the static factory methods instead. - protected abstract Builder lrsServerName(String lrsServerName); + protected abstract Builder lrsServerInfo(ServerInfo lrsServerInfo); // Private, use one of the static factory methods instead. protected abstract Builder maxConcurrentRequests(Long maxConcurrentRequests); @@ -569,8 +569,8 @@ void cancelEdsResourceWatch(String resourceName, EdsResourceWatcher watcher) { * use {@link ClusterDropStats#release} to release its hard reference when it is safe to * stop reporting dropped RPCs for the specified cluster in the future. */ - // TODO(https://github.com/grpc/grpc-java/issues/8628): add ServerInfo arg - ClusterDropStats addClusterDropStats(String clusterName, @Nullable String edsServiceName) { + ClusterDropStats addClusterDropStats( + ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName) { throw new UnsupportedOperationException(); } @@ -582,9 +582,9 @@ ClusterDropStats addClusterDropStats(String clusterName, @Nullable String edsSer * reference when it is safe to stop reporting RPC loads for the specified locality in the * future. */ - // TODO(https://github.com/grpc/grpc-java/issues/8628): add ServerInfo arg ClusterLocalityStats addClusterLocalityStats( - String clusterName, @Nullable String edsServiceName, Locality locality) { + ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName, + Locality locality) { throw new UnsupportedOperationException(); } diff --git a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java index 24586c70e91..388fc6a8b20 100644 --- a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java +++ b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java @@ -29,6 +29,7 @@ import io.grpc.Attributes; import io.grpc.ConnectivityState; import io.grpc.EquivalentAddressGroup; +import io.grpc.InsecureChannelCredentials; import io.grpc.LoadBalancer; import io.grpc.LoadBalancer.Helper; import io.grpc.LoadBalancer.PickResult; @@ -42,6 +43,7 @@ import io.grpc.Status.Code; import io.grpc.SynchronizationContext; import io.grpc.internal.ObjectPool; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.CdsLoadBalancerProvider.CdsConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig.DiscoveryMechanism; @@ -75,7 +77,8 @@ public class CdsLoadBalancer2Test { private static final String CLUSTER = "cluster-foo.googleapis.com"; private static final String EDS_SERVICE_NAME = "backend-service-1.googleapis.com"; private static final String DNS_HOST_NAME = "backend-service-dns.googleapis.com:443"; - private static final String LRS_SERVER_NAME = "lrs.googleapis.com"; + private static final ServerInfo LRS_SERVER_INFO = + ServerInfo.create("lrs.googleapis.com", InsecureChannelCredentials.create(), true); private final UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext("google_cloud_private_spiffe", true); @@ -143,7 +146,7 @@ public void tearDown() { @Test public void discoverTopLevelEdsCluster() { CdsUpdate update = - CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, 100L, upstreamTlsContext) + CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, 100L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(CLUSTER, update); assertThat(childBalancers).hasSize(1); @@ -153,14 +156,14 @@ public void discoverTopLevelEdsCluster() { assertThat(childLbConfig.discoveryMechanisms).hasSize(1); DiscoveryMechanism instance = Iterables.getOnlyElement(childLbConfig.discoveryMechanisms); assertDiscoveryMechanism(instance, CLUSTER, DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, - null, LRS_SERVER_NAME, 100L, upstreamTlsContext); + null, LRS_SERVER_INFO, 100L, upstreamTlsContext); assertThat(childLbConfig.lbPolicy.getProvider().getPolicyName()).isEqualTo("round_robin"); } @Test public void discoverTopLevelLogicalDnsCluster() { CdsUpdate update = - CdsUpdate.forLogicalDns(CLUSTER, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, upstreamTlsContext) + CdsUpdate.forLogicalDns(CLUSTER, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(CLUSTER, update); assertThat(childBalancers).hasSize(1); @@ -170,7 +173,7 @@ public void discoverTopLevelLogicalDnsCluster() { assertThat(childLbConfig.discoveryMechanisms).hasSize(1); DiscoveryMechanism instance = Iterables.getOnlyElement(childLbConfig.discoveryMechanisms); assertDiscoveryMechanism(instance, CLUSTER, DiscoveryMechanism.Type.LOGICAL_DNS, null, - DNS_HOST_NAME, LRS_SERVER_NAME, 100L, upstreamTlsContext); + DNS_HOST_NAME, LRS_SERVER_INFO, 100L, upstreamTlsContext); assertThat(childLbConfig.lbPolicy.getProvider().getPolicyName()).isEqualTo("round_robin"); } @@ -198,13 +201,13 @@ public void nonAggregateCluster_resourceUpdate() { assertDiscoveryMechanism(instance, CLUSTER, DiscoveryMechanism.Type.EDS, null, null, null, 100L, upstreamTlsContext); - update = CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, 200L, null) + update = CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, 200L, null) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(CLUSTER, update); childLbConfig = (ClusterResolverConfig) childBalancer.config; instance = Iterables.getOnlyElement(childLbConfig.discoveryMechanisms); assertDiscoveryMechanism(instance, CLUSTER, DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, - null, LRS_SERVER_NAME, 200L, null); + null, LRS_SERVER_INFO, 200L, null); } @Test @@ -253,7 +256,7 @@ public void discoverAggregateCluster() { CLUSTER, cluster1, cluster2, cluster3, cluster4); assertThat(childBalancers).isEmpty(); CdsUpdate update3 = - CdsUpdate.forEds(cluster3, EDS_SERVICE_NAME, LRS_SERVER_NAME, 200L, upstreamTlsContext) + CdsUpdate.forEds(cluster3, EDS_SERVICE_NAME, LRS_SERVER_INFO, 200L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster3, update3); assertThat(childBalancers).isEmpty(); @@ -263,7 +266,7 @@ public void discoverAggregateCluster() { xdsClient.deliverCdsUpdate(cluster2, update2); assertThat(childBalancers).isEmpty(); CdsUpdate update4 = - CdsUpdate.forEds(cluster4, null, LRS_SERVER_NAME, 300L, null) + CdsUpdate.forEds(cluster4, null, LRS_SERVER_INFO, 300L, null) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster4, update4); assertThat(childBalancers).hasSize(1); // all non-aggregate clusters discovered @@ -275,10 +278,10 @@ public void discoverAggregateCluster() { assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(0), cluster2, DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, null, 100L, null); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(1), cluster3, - DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_NAME, 200L, + DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_INFO, 200L, upstreamTlsContext); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(2), cluster4, - DiscoveryMechanism.Type.EDS, null, null, LRS_SERVER_NAME, 300L, null); + DiscoveryMechanism.Type.EDS, null, null, LRS_SERVER_INFO, 300L, null); assertThat(childLbConfig.lbPolicy.getProvider().getPolicyName()) .isEqualTo("ring_hash"); // dominated by top-level cluster's config assertThat(((RingHashConfig) childLbConfig.lbPolicy.getConfig()).minRingSize).isEqualTo(100L); @@ -314,21 +317,21 @@ public void aggregateCluster_descendantClustersRevoked() { xdsClient.deliverCdsUpdate(CLUSTER, update); assertThat(xdsClient.watchers.keySet()).containsExactly(CLUSTER, cluster1, cluster2); CdsUpdate update1 = - CdsUpdate.forEds(cluster1, EDS_SERVICE_NAME, LRS_SERVER_NAME, 200L, upstreamTlsContext) + CdsUpdate.forEds(cluster1, EDS_SERVICE_NAME, LRS_SERVER_INFO, 200L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster1, update1); CdsUpdate update2 = - CdsUpdate.forLogicalDns(cluster2, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, null) + CdsUpdate.forLogicalDns(cluster2, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, null) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster2, update2); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); ClusterResolverConfig childLbConfig = (ClusterResolverConfig) childBalancer.config; assertThat(childLbConfig.discoveryMechanisms).hasSize(2); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(0), cluster1, - DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_NAME, 200L, + DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_INFO, 200L, upstreamTlsContext); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(1), cluster2, - DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, null); + DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, null); // Revoke cluster1, should still be able to proceed with cluster2. xdsClient.deliverResourceNotExist(cluster1); @@ -336,7 +339,7 @@ public void aggregateCluster_descendantClustersRevoked() { childLbConfig = (ClusterResolverConfig) childBalancer.config; assertThat(childLbConfig.discoveryMechanisms).hasSize(1); assertDiscoveryMechanism(Iterables.getOnlyElement(childLbConfig.discoveryMechanisms), cluster2, - DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, null); + DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, null); verify(helper, never()).updateBalancingState( eq(ConnectivityState.TRANSIENT_FAILURE), any(SubchannelPicker.class)); @@ -362,21 +365,21 @@ public void aggregateCluster_rootClusterRevoked() { xdsClient.deliverCdsUpdate(CLUSTER, update); assertThat(xdsClient.watchers.keySet()).containsExactly(CLUSTER, cluster1, cluster2); CdsUpdate update1 = - CdsUpdate.forEds(cluster1, EDS_SERVICE_NAME, LRS_SERVER_NAME, 200L, upstreamTlsContext) + CdsUpdate.forEds(cluster1, EDS_SERVICE_NAME, LRS_SERVER_INFO, 200L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster1, update1); CdsUpdate update2 = - CdsUpdate.forLogicalDns(cluster2, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, null) + CdsUpdate.forLogicalDns(cluster2, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, null) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster2, update2); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); ClusterResolverConfig childLbConfig = (ClusterResolverConfig) childBalancer.config; assertThat(childLbConfig.discoveryMechanisms).hasSize(2); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(0), cluster1, - DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_NAME, 200L, + DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, null, LRS_SERVER_INFO, 200L, upstreamTlsContext); assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(1), cluster2, - DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_NAME, 100L, null); + DiscoveryMechanism.Type.LOGICAL_DNS, null, DNS_HOST_NAME, LRS_SERVER_INFO, 100L, null); xdsClient.deliverResourceNotExist(CLUSTER); assertThat(xdsClient.watchers.keySet()) @@ -416,7 +419,7 @@ public void aggregateCluster_intermediateClusterChanges() { xdsClient.deliverCdsUpdate(cluster2, update2); assertThat(xdsClient.watchers.keySet()).containsExactly(CLUSTER, cluster2, cluster3); CdsUpdate update3 = - CdsUpdate.forEds(cluster3, EDS_SERVICE_NAME, LRS_SERVER_NAME, 100L, upstreamTlsContext) + CdsUpdate.forEds(cluster3, EDS_SERVICE_NAME, LRS_SERVER_INFO, 100L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster3, update3); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); @@ -424,7 +427,7 @@ public void aggregateCluster_intermediateClusterChanges() { assertThat(childLbConfig.discoveryMechanisms).hasSize(1); DiscoveryMechanism instance = Iterables.getOnlyElement(childLbConfig.discoveryMechanisms); assertDiscoveryMechanism(instance, cluster3, DiscoveryMechanism.Type.EDS, EDS_SERVICE_NAME, - null, LRS_SERVER_NAME, 100L, upstreamTlsContext); + null, LRS_SERVER_INFO, 100L, upstreamTlsContext); // cluster2 revoked xdsClient.deliverResourceNotExist(cluster2); @@ -465,7 +468,7 @@ public void aggregateCluster_discoveryErrorAfterChildLbCreated_propagateToChildL .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(CLUSTER, update); CdsUpdate update1 = - CdsUpdate.forLogicalDns(cluster1, DNS_HOST_NAME, LRS_SERVER_NAME, 200L, null) + CdsUpdate.forLogicalDns(cluster1, DNS_HOST_NAME, LRS_SERVER_INFO, 200L, null) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(cluster1, update1); FakeLoadBalancer childLb = Iterables.getOnlyElement(childBalancers); @@ -490,7 +493,7 @@ public void handleNameResolutionErrorFromUpstream_beforeChildLbCreated_returnErr @Test public void handleNameResolutionErrorFromUpstream_afterChildLbCreated_fallThrough() { CdsUpdate update = - CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, 100L, upstreamTlsContext) + CdsUpdate.forEds(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, 100L, upstreamTlsContext) .roundRobinLbPolicy().build(); xdsClient.deliverCdsUpdate(CLUSTER, update); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); @@ -515,13 +518,13 @@ private static void assertPicker(SubchannelPicker picker, Status expectedStatus, private static void assertDiscoveryMechanism(DiscoveryMechanism instance, String name, DiscoveryMechanism.Type type, @Nullable String edsServiceName, @Nullable String dnsHostName, - @Nullable String lrsServerName, @Nullable Long maxConcurrentRequests, + @Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext) { assertThat(instance.cluster).isEqualTo(name); assertThat(instance.type).isEqualTo(type); assertThat(instance.edsServiceName).isEqualTo(edsServiceName); assertThat(instance.dnsHostName).isEqualTo(dnsHostName); - assertThat(instance.lrsServerName).isEqualTo(lrsServerName); + assertThat(instance.lrsServerInfo).isEqualTo(lrsServerInfo); assertThat(instance.maxConcurrentRequests).isEqualTo(maxConcurrentRequests); assertThat(instance.tlsContext).isEqualTo(tlsContext); } diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java index 2dbab1bcb9d..cb7b937bb5f 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java @@ -94,7 +94,9 @@ import io.envoyproxy.envoy.type.v3.FractionalPercent; import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType; import io.envoyproxy.envoy.type.v3.Int64Range; +import io.grpc.InsecureChannelCredentials; import io.grpc.Status.Code; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClientXdsClient.ResourceInvalidException; import io.grpc.xds.ClientXdsClient.StructOrError; import io.grpc.xds.Endpoints.LbEndpoint; @@ -126,6 +128,9 @@ @RunWith(JUnit4.class) public class ClientXdsClientDataTest { + private static final ServerInfo LRS_SERVER_INFO = + ServerInfo.create("lrs.googleapis.com", InsecureChannelCredentials.create(), true); + @SuppressWarnings("deprecation") // https://github.com/grpc/grpc-java/issues/7467 @Rule public final ExpectedException thrown = ExpectedException.none(); @@ -1239,7 +1244,8 @@ public void parseCluster_ringHashLbPolicy_defaultLbConfig() throws ResourceInval .setLbPolicy(LbPolicy.RING_HASH) .build(); - CdsUpdate update = ClientXdsClient.parseCluster(cluster, new HashSet(), null); + CdsUpdate update = ClientXdsClient.parseCluster( + cluster, new HashSet(), null, LRS_SERVER_INFO); assertThat(update.lbPolicy()).isEqualTo(CdsUpdate.LbPolicy.RING_HASH); assertThat(update.minRingSize()) .isEqualTo(ClientXdsClient.DEFAULT_RING_HASH_LB_POLICY_MIN_RING_SIZE); @@ -1266,7 +1272,7 @@ public void parseCluster_transportSocketMatches_exception() throws ResourceInval thrown.expect(ResourceInvalidException.class); thrown.expectMessage( "Cluster cluster-foo.googleapis.com: transport-socket-matches not supported."); - ClientXdsClient.parseCluster(cluster, new HashSet(), null); + ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test @@ -1291,7 +1297,7 @@ public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_minGreaterThanMa thrown.expect(ResourceInvalidException.class); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); - ClientXdsClient.parseCluster(cluster, new HashSet(), null); + ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test @@ -1318,7 +1324,7 @@ public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_tooLargeRingSize thrown.expect(ResourceInvalidException.class); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); - ClientXdsClient.parseCluster(cluster, new HashSet(), null); + ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java index 4a34538954c..9d0c735ba95 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java @@ -43,6 +43,7 @@ import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateProviderPluginInstance; import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext; import io.grpc.BindableService; +import io.grpc.ChannelCredentials; import io.grpc.Context; import io.grpc.Context.CancellableContext; import io.grpc.InsecureChannelCredentials; @@ -124,6 +125,9 @@ public abstract class ClientXdsClientTestBase { private static final String VERSION_3 = "44"; private static final Node NODE = Node.newBuilder().build(); private static final Any FAILING_ANY = MessageFactory.FAILING_ANY; + private static final ChannelCredentials CHANNEL_CREDENTIALS = InsecureChannelCredentials.create(); + private final ServerInfo lrsServerInfo = + ServerInfo.create(SERVER_URI, CHANNEL_CREDENTIALS, useProtocolV3()); private static final FakeClock.TaskFilter RPC_RETRY_TASK_FILTER = new FakeClock.TaskFilter() { @@ -284,8 +288,7 @@ ManagedChannel create(ServerInfo serverInfo) { Bootstrapper.BootstrapInfo bootstrapInfo = Bootstrapper.BootstrapInfo.builder() .servers(Arrays.asList( - Bootstrapper.ServerInfo.create( - SERVER_URI, InsecureChannelCredentials.create(), useProtocolV3()))) + Bootstrapper.ServerInfo.create(SERVER_URI, CHANNEL_CREDENTIALS, useProtocolV3()))) .node(EnvoyProtoData.Node.newBuilder().build()) .certProviders(ImmutableMap.of("cert-instance-name", CertificateProviderInfo.create("file-watcher", ImmutableMap.of()))) @@ -1393,7 +1396,7 @@ public void cdsResourceFound() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isNull(); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); assertThat(fakeClock.getPendingTasks(CDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty(); @@ -1422,7 +1425,7 @@ public void cdsResourceFound_ringHashLbPolicy() { assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.RING_HASH); assertThat(cdsUpdate.minRingSize()).isEqualTo(10L); assertThat(cdsUpdate.maxRingSize()).isEqualTo(100L); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); assertThat(fakeClock.getPendingTasks(CDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty(); @@ -1467,7 +1470,7 @@ public void cdsResponseWithCircuitBreakers() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isNull(); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isEqualTo(200L); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusterCircuitBreakers, VERSION_1, @@ -1617,7 +1620,7 @@ public void cachedCdsResource_data() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isNull(); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); call.verifyNoMoreRequest(); @@ -1659,7 +1662,7 @@ public void cdsResourceUpdated() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.LOGICAL_DNS); assertThat(cdsUpdate.dnsHostName()).isEqualTo(dnsHostAddr + ":" + dnsHostPort); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusterDns, VERSION_1, TIME_INCREMENT); @@ -1678,7 +1681,7 @@ public void cdsResourceUpdated() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isEqualTo(edsService); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isEqualTo(""); + assertThat(cdsUpdate.lrsServerInfo()).isEqualTo(lrsServerInfo); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusterEds, VERSION_2, TIME_INCREMENT * 2); @@ -1699,7 +1702,7 @@ public void cdsResourceDeleted() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isNull(); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, testClusterRoundRobin, VERSION_1, @@ -1751,7 +1754,7 @@ public void multipleCdsWatchers() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.LOGICAL_DNS); assertThat(cdsUpdate.dnsHostName()).isEqualTo(dnsHostAddr + ":" + dnsHostPort); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verify(watcher1).onChanged(cdsUpdateCaptor.capture()); @@ -1760,7 +1763,7 @@ public void multipleCdsWatchers() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isEqualTo(edsService); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isEqualTo(""); + assertThat(cdsUpdate.lrsServerInfo()).isEqualTo(lrsServerInfo); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); verify(watcher2).onChanged(cdsUpdateCaptor.capture()); @@ -1769,7 +1772,7 @@ public void multipleCdsWatchers() { assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); assertThat(cdsUpdate.edsServiceName()).isEqualTo(edsService); assertThat(cdsUpdate.lbPolicy()).isEqualTo(LbPolicy.ROUND_ROBIN); - assertThat(cdsUpdate.lrsServerName()).isEqualTo(""); + assertThat(cdsUpdate.lrsServerInfo()).isEqualTo(lrsServerInfo); assertThat(cdsUpdate.maxConcurrentRequests()).isNull(); assertThat(cdsUpdate.upstreamTlsContext()).isNull(); // Metadata of both clusters is stored. @@ -2013,11 +2016,11 @@ public void edsResourceDeletedByCds() { verify(cdsWatcher).onChanged(cdsUpdateCaptor.capture()); CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue(); assertThat(cdsUpdate.edsServiceName()).isEqualTo(null); - assertThat(cdsUpdate.lrsServerName()).isEqualTo(""); + assertThat(cdsUpdate.lrsServerInfo()).isEqualTo(lrsServerInfo); verify(cdsResourceWatcher).onChanged(cdsUpdateCaptor.capture()); cdsUpdate = cdsUpdateCaptor.getValue(); assertThat(cdsUpdate.edsServiceName()).isEqualTo(EDS_RESOURCE); - assertThat(cdsUpdate.lrsServerName()).isNull(); + assertThat(cdsUpdate.lrsServerInfo()).isNull(); verifyResourceMetadataAcked(CDS, resource, clusters.get(0), VERSION_1, TIME_INCREMENT); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusters.get(1), VERSION_1, TIME_INCREMENT); verifyResourceMetadataRequested(EDS, EDS_RESOURCE); @@ -2343,7 +2346,7 @@ public void streamClosedAndRetryRestartsResourceInitialFetchTimerForUnresolvedRe public void reportLoadStatsToServer() { xdsClient.watchLdsResource(LDS_RESOURCE, ldsResourceWatcher); String clusterName = "cluster-foo.googleapis.com"; - ClusterDropStats dropStats = xdsClient.addClusterDropStats(clusterName, null); + ClusterDropStats dropStats = xdsClient.addClusterDropStats(lrsServerInfo, clusterName, null); LrsRpcCall lrsCall = loadReportCalls.poll(); lrsCall.verifyNextReportClusters(Collections.emptyList()); // initial LRS request diff --git a/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java index dfcf101fcf5..582747aecb7 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java @@ -27,6 +27,7 @@ import io.grpc.ClientStreamTracer; import io.grpc.ConnectivityState; import io.grpc.EquivalentAddressGroup; +import io.grpc.InsecureChannelCredentials; import io.grpc.LoadBalancer; import io.grpc.LoadBalancer.CreateSubchannelArgs; import io.grpc.LoadBalancer.Helper; @@ -44,6 +45,7 @@ import io.grpc.internal.FakeClock; import io.grpc.internal.ObjectPool; import io.grpc.internal.ServiceConfigUtil.PolicySelection; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig; import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext; @@ -85,7 +87,8 @@ public class ClusterImplLoadBalancerTest { private static final String AUTHORITY = "api.google.com"; private static final String CLUSTER = "cluster-foo.googleapis.com"; private static final String EDS_SERVICE_NAME = "service.googleapis.com"; - private static final String LRS_SERVER_NAME = ""; + private static final ServerInfo LRS_SERVER_INFO = + ServerInfo.create("api.google.com", InsecureChannelCredentials.create(), true); private final SynchronizationContext syncContext = new SynchronizationContext( new Thread.UncaughtExceptionHandler() { @Override @@ -150,7 +153,7 @@ public void handleResolvedAddresses_propagateToChildPolicy() { FakeLoadBalancerProvider weightedTargetProvider = new FakeLoadBalancerProvider(XdsLbPolicies.WEIGHTED_TARGET_POLICY_NAME); Object weightedTargetConfig = new Object(); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -177,7 +180,7 @@ public void nameResolutionError_afterChildPolicyInstantiated_propagateToDownstre FakeLoadBalancerProvider weightedTargetProvider = new FakeLoadBalancerProvider(XdsLbPolicies.WEIGHTED_TARGET_POLICY_NAME); Object weightedTargetConfig = new Object(); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -196,7 +199,7 @@ public void recordLoadStats() { LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -247,7 +250,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() { LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.singletonList(DropOverload.create("throttle", 500_000)), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -276,7 +279,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() { assertThat(clusterStats.totalDroppedRequests()).isEqualTo(1L); // Config update updates drop policies. - config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, null, + config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.singletonList(DropOverload.create("lb", 1_000_000)), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); loadBalancer.handleResolvedAddresses( @@ -323,7 +326,7 @@ private void subtest_maxConcurrentRequests_appliedByLbConfig(boolean enableCircu LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, maxConcurrentRequests, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -365,7 +368,7 @@ private void subtest_maxConcurrentRequests_appliedByLbConfig(boolean enableCircu // Config update increments circuit breakers max_concurrent_requests threshold. maxConcurrentRequests = 101L; - config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, maxConcurrentRequests, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); deliverAddressesAndConfig(Collections.singletonList(endpoint), config); @@ -411,7 +414,7 @@ private void subtest_maxConcurrentRequests_appliedWithDefaultValue( LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality); @@ -457,7 +460,7 @@ public void endpointAddressesAttachedWithClusterName() { LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); // One locality with two endpoints. @@ -498,7 +501,7 @@ private void subtest_endpointAddressesAttachedWithTlsConfig(boolean enableSecuri LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider(); WeightedTargetConfig weightedTargetConfig = buildWeightedTargetConfig(ImmutableMap.of(locality, 10)); - ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), upstreamTlsContext); // One locality with two endpoints. @@ -525,7 +528,7 @@ private void subtest_endpointAddressesAttachedWithTlsConfig(boolean enableSecuri } // Removes UpstreamTlsContext from the config. - config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), null); deliverAddressesAndConfig(Arrays.asList(endpoint1, endpoint2), config); @@ -539,7 +542,7 @@ private void subtest_endpointAddressesAttachedWithTlsConfig(boolean enableSecuri // Config with a new UpstreamTlsContext. upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext("google_cloud_private_spiffe1", true); - config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_NAME, + config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO, null, Collections.emptyList(), new PolicySelection(weightedTargetProvider, weightedTargetConfig), upstreamTlsContext); deliverAddressesAndConfig(Arrays.asList(endpoint1, endpoint2), config); @@ -761,13 +764,15 @@ public Attributes getAttributes() { private final class FakeXdsClient extends XdsClient { @Override - ClusterDropStats addClusterDropStats(String clusterName, @Nullable String edsServiceName) { + ClusterDropStats addClusterDropStats( + ServerInfo lrsServerInfo, String clusterName, @Nullable String edsServiceName) { return loadStatsManager.getClusterDropStats(clusterName, edsServiceName); } @Override - ClusterLocalityStats addClusterLocalityStats(String clusterName, - @Nullable String edsServiceName, Locality locality) { + ClusterLocalityStats addClusterLocalityStats( + ServerInfo lrsServerInfo, String clusterName, @Nullable String edsServiceName, + Locality locality) { return loadStatsManager.getClusterLocalityStats(clusterName, edsServiceName, locality); } diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java index 26f1a2b3cf7..ccc1975265d 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java @@ -34,6 +34,7 @@ import io.grpc.ChannelLogger; import io.grpc.ConnectivityState; import io.grpc.EquivalentAddressGroup; +import io.grpc.InsecureChannelCredentials; import io.grpc.LoadBalancer; import io.grpc.LoadBalancer.Helper; import io.grpc.LoadBalancer.PickResult; @@ -56,6 +57,7 @@ import io.grpc.internal.GrpcUtil; import io.grpc.internal.ObjectPool; import io.grpc.internal.ServiceConfigUtil.PolicySelection; +import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig; import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig.DiscoveryMechanism; @@ -103,7 +105,8 @@ public class ClusterResolverLoadBalancerTest { private static final String EDS_SERVICE_NAME1 = "backend-service-foo.googleapis.com"; private static final String EDS_SERVICE_NAME2 = "backend-service-bar.googleapis.com"; private static final String DNS_HOST_NAME = "dns-service.googleapis.com"; - private static final String LRS_SERVER_NAME = "lrs.googleapis.com"; + private static final ServerInfo LRS_SERVER_INFO = + ServerInfo.create("lrs.googleapis.com", InsecureChannelCredentials.create(), true); private final Locality locality1 = Locality.create("test-region-1", "test-zone-1", "test-subzone-1"); private final Locality locality2 = @@ -113,11 +116,11 @@ public class ClusterResolverLoadBalancerTest { private final UpstreamTlsContext tlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext("google_cloud_private_spiffe", true); private final DiscoveryMechanism edsDiscoveryMechanism1 = - DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_NAME, 100L, tlsContext); + DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext); private final DiscoveryMechanism edsDiscoveryMechanism2 = - DiscoveryMechanism.forEds(CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_NAME, 200L, tlsContext); + DiscoveryMechanism.forEds(CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_INFO, 200L, tlsContext); private final DiscoveryMechanism logicalDnsDiscoveryMechanism = - DiscoveryMechanism.forLogicalDns(CLUSTER_DNS, DNS_HOST_NAME, LRS_SERVER_NAME, 300L, null); + DiscoveryMechanism.forLogicalDns(CLUSTER_DNS, DNS_HOST_NAME, LRS_SERVER_INFO, 300L, null); private final SynchronizationContext syncContext = new SynchronizationContext( new Thread.UncaughtExceptionHandler() { @@ -256,7 +259,7 @@ public void edsClustersWithRingHashEndpointLbPolicy() { .isEqualTo(CLUSTER_IMPL_POLICY_NAME); ClusterImplConfig clusterImplConfig = (ClusterImplConfig) priorityChildConfig.policySelection.getConfig(); - assertClusterImplConfig(clusterImplConfig, CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_NAME, 100L, + assertClusterImplConfig(clusterImplConfig, CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext, Collections.emptyList(), "ring_hash"); RingHashConfig ringHashConfig = (RingHashConfig) clusterImplConfig.childPolicy.getConfig(); @@ -320,7 +323,7 @@ public void onlyEdsClusters_receivedEndpoints() { .isEqualTo(CLUSTER_IMPL_POLICY_NAME); ClusterImplConfig clusterImplConfig1 = (ClusterImplConfig) priorityChildConfig1.policySelection.getConfig(); - assertClusterImplConfig(clusterImplConfig1, CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_NAME, 200L, + assertClusterImplConfig(clusterImplConfig1, CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_INFO, 200L, tlsContext, Collections.emptyList(), WEIGHTED_TARGET_POLICY_NAME); WeightedTargetConfig weightedTargetConfig1 = (WeightedTargetConfig) clusterImplConfig1.childPolicy.getConfig(); @@ -335,7 +338,7 @@ public void onlyEdsClusters_receivedEndpoints() { .isEqualTo(CLUSTER_IMPL_POLICY_NAME); ClusterImplConfig clusterImplConfig2 = (ClusterImplConfig) priorityChildConfig2.policySelection.getConfig(); - assertClusterImplConfig(clusterImplConfig2, CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_NAME, 200L, + assertClusterImplConfig(clusterImplConfig2, CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_INFO, 200L, tlsContext, Collections.emptyList(), WEIGHTED_TARGET_POLICY_NAME); WeightedTargetConfig weightedTargetConfig2 = (WeightedTargetConfig) clusterImplConfig2.childPolicy.getConfig(); @@ -358,7 +361,7 @@ public void onlyEdsClusters_receivedEndpoints() { .isEqualTo(CLUSTER_IMPL_POLICY_NAME); ClusterImplConfig clusterImplConfig3 = (ClusterImplConfig) priorityChildConfig3.policySelection.getConfig(); - assertClusterImplConfig(clusterImplConfig3, CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_NAME, 100L, + assertClusterImplConfig(clusterImplConfig3, CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext, Collections.emptyList(), WEIGHTED_TARGET_POLICY_NAME); WeightedTargetConfig weightedTargetConfig3 = (WeightedTargetConfig) clusterImplConfig3.childPolicy.getConfig(); @@ -549,7 +552,7 @@ public void onlyLogicalDnsCluster_endpointsResolved() { .isEqualTo(CLUSTER_IMPL_POLICY_NAME); ClusterImplConfig clusterImplConfig = (ClusterImplConfig) priorityChildConfig.policySelection.getConfig(); - assertClusterImplConfig(clusterImplConfig, CLUSTER_DNS, null, LRS_SERVER_NAME, 300L, null, + assertClusterImplConfig(clusterImplConfig, CLUSTER_DNS, null, LRS_SERVER_INFO, 300L, null, Collections.emptyList(), "pick_first"); assertAddressesEqual(Arrays.asList(endpoint1, endpoint2), childBalancer.addresses); } @@ -884,12 +887,12 @@ private static void assertPicker(SubchannelPicker picker, Status expectedStatus, } private static void assertClusterImplConfig(ClusterImplConfig config, String cluster, - @Nullable String edsServiceName, String lrsServerName, Long maxConcurrentRequests, + @Nullable String edsServiceName, ServerInfo lrsServerInfo, Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext, List dropCategories, String childPolicy) { assertThat(config.cluster).isEqualTo(cluster); assertThat(config.edsServiceName).isEqualTo(edsServiceName); - assertThat(config.lrsServerName).isEqualTo(lrsServerName); + assertThat(config.lrsServerInfo).isEqualTo(lrsServerInfo); assertThat(config.maxConcurrentRequests).isEqualTo(maxConcurrentRequests); assertThat(config.tlsContext).isEqualTo(tlsContext); assertThat(config.dropCategories).isEqualTo(dropCategories); From b3579db57480a49fcfd714505bbdb2faefacfee3 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Wed, 10 Nov 2021 08:38:44 -0800 Subject: [PATCH 0004/2009] xds: Migrate away deprecated fields in CsdsService (#8675) Migrate deprecate `xds_config` field to `generic_xds_configs` https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/status/v3/csds.proto#service-status-v3-clientconfig As per grpc/proposal#267. The c++ version is grpc/grpc#27794 --- .../java/io/grpc/xds/AbstractXdsClient.java | 3 +- .../java/io/grpc/xds/ClientXdsClient.java | 9 - .../main/java/io/grpc/xds/CsdsService.java | 154 +---- xds/src/main/java/io/grpc/xds/XdsClient.java | 8 - .../java/io/grpc/xds/CsdsServiceTest.java | 557 ++---------------- 5 files changed, 68 insertions(+), 663 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/AbstractXdsClient.java b/xds/src/main/java/io/grpc/xds/AbstractXdsClient.java index e29949eb8e5..61780c60a55 100644 --- a/xds/src/main/java/io/grpc/xds/AbstractXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/AbstractXdsClient.java @@ -333,7 +333,8 @@ String typeUrlV2() { } } - private static ResourceType fromTypeUrl(String typeUrl) { + @VisibleForTesting + static ResourceType fromTypeUrl(String typeUrl) { switch (typeUrl) { case ADS_TYPE_URL_LDS: // fall trough diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index c8172a87d18..4d45dc21d9e 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -2132,15 +2132,6 @@ public void run() { Bootstrapper.BootstrapInfo getBootstrapInfo() { return bootstrapInfo; } - - // TODO(https://github.com/grpc/grpc-java/issues/8629): remove this - @Override - String getCurrentVersion(ResourceType type) { - if (serverChannelMap.isEmpty()) { - return ""; - } - return serverChannelMap.values().iterator().next().getCurrentVersion(type); - } @Override public String toString() { diff --git a/xds/src/main/java/io/grpc/xds/CsdsService.java b/xds/src/main/java/io/grpc/xds/CsdsService.java index 5146930859d..89147536a6d 100644 --- a/xds/src/main/java/io/grpc/xds/CsdsService.java +++ b/xds/src/main/java/io/grpc/xds/CsdsService.java @@ -21,20 +21,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.util.Timestamps; import io.envoyproxy.envoy.admin.v3.ClientResourceStatus; -import io.envoyproxy.envoy.admin.v3.ClustersConfigDump; -import io.envoyproxy.envoy.admin.v3.ClustersConfigDump.DynamicCluster; -import io.envoyproxy.envoy.admin.v3.EndpointsConfigDump; -import io.envoyproxy.envoy.admin.v3.EndpointsConfigDump.DynamicEndpointConfig; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListener; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListenerState; -import io.envoyproxy.envoy.admin.v3.RoutesConfigDump; -import io.envoyproxy.envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig; import io.envoyproxy.envoy.service.status.v3.ClientConfig; +import io.envoyproxy.envoy.service.status.v3.ClientConfig.GenericXdsConfig; import io.envoyproxy.envoy.service.status.v3.ClientStatusDiscoveryServiceGrpc; import io.envoyproxy.envoy.service.status.v3.ClientStatusRequest; import io.envoyproxy.envoy.service.status.v3.ClientStatusResponse; -import io.envoyproxy.envoy.service.status.v3.PerXdsConfig; import io.grpc.ExperimentalApi; import io.grpc.Status; import io.grpc.StatusException; @@ -150,124 +141,33 @@ private ClientStatusResponse getConfigDumpForRequest(ClientStatusRequest request @VisibleForTesting static ClientConfig getClientConfigForXdsClient(XdsClient xdsClient) { - ListenersConfigDump ldsConfig = dumpLdsConfig( - xdsClient.getSubscribedResourcesMetadata(ResourceType.LDS), - xdsClient.getCurrentVersion(ResourceType.LDS)); - RoutesConfigDump rdsConfig = dumpRdsConfig( - xdsClient.getSubscribedResourcesMetadata(ResourceType.RDS)); - ClustersConfigDump cdsConfig = dumpCdsConfig( - xdsClient.getSubscribedResourcesMetadata(ResourceType.CDS), - xdsClient.getCurrentVersion(ResourceType.CDS)); - EndpointsConfigDump edsConfig = dumpEdsConfig( - xdsClient.getSubscribedResourcesMetadata(ResourceType.EDS)); - - return ClientConfig.newBuilder() - .setNode(xdsClient.getBootstrapInfo().node().toEnvoyProtoNode()) - .addXdsConfig(PerXdsConfig.newBuilder().setListenerConfig(ldsConfig)) - .addXdsConfig(PerXdsConfig.newBuilder().setRouteConfig(rdsConfig)) - .addXdsConfig(PerXdsConfig.newBuilder().setClusterConfig(cdsConfig)) - .addXdsConfig(PerXdsConfig.newBuilder().setEndpointConfig(edsConfig)) - .build(); - } - - @VisibleForTesting - static ListenersConfigDump dumpLdsConfig( - Map resourcesMetadata, String version) { - ListenersConfigDump.Builder ldsConfig = ListenersConfigDump.newBuilder(); - for (Map.Entry entry : resourcesMetadata.entrySet()) { - ldsConfig.addDynamicListeners(buildDynamicListener(entry.getKey(), entry.getValue())); - } - return ldsConfig.setVersionInfo(version).build(); - } - - @VisibleForTesting - static DynamicListener buildDynamicListener(String name, ResourceMetadata metadata) { - DynamicListener.Builder dynamicListener = DynamicListener.newBuilder() - .setName(name) - .setClientStatus(metadataStatusToClientStatus(metadata.getStatus())); - if (metadata.getErrorState() != null) { - dynamicListener.setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState())); - } - DynamicListenerState.Builder dynamicListenerState = DynamicListenerState.newBuilder() - .setVersionInfo(metadata.getVersion()) - .setLastUpdated(Timestamps.fromNanos(metadata.getUpdateTimeNanos())); - if (metadata.getRawResource() != null) { - dynamicListenerState.setListener(metadata.getRawResource()); - } - return dynamicListener.setActiveState(dynamicListenerState).build(); - } - - @VisibleForTesting - static RoutesConfigDump dumpRdsConfig(Map resourcesMetadata) { - RoutesConfigDump.Builder rdsConfig = RoutesConfigDump.newBuilder(); - for (ResourceMetadata metadata : resourcesMetadata.values()) { - rdsConfig.addDynamicRouteConfigs(buildDynamicRouteConfig(metadata)); - } - return rdsConfig.build(); - } - - @VisibleForTesting - static DynamicRouteConfig buildDynamicRouteConfig(ResourceMetadata metadata) { - DynamicRouteConfig.Builder dynamicRouteConfig = DynamicRouteConfig.newBuilder() - .setVersionInfo(metadata.getVersion()) - .setClientStatus(metadataStatusToClientStatus(metadata.getStatus())) - .setLastUpdated(Timestamps.fromNanos(metadata.getUpdateTimeNanos())); - if (metadata.getErrorState() != null) { - dynamicRouteConfig.setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState())); - } - if (metadata.getRawResource() != null) { - dynamicRouteConfig.setRouteConfig(metadata.getRawResource()); - } - return dynamicRouteConfig.build(); - } - - @VisibleForTesting - static ClustersConfigDump dumpCdsConfig( - Map resourcesMetadata, String version) { - ClustersConfigDump.Builder cdsConfig = ClustersConfigDump.newBuilder(); - for (ResourceMetadata metadata : resourcesMetadata.values()) { - cdsConfig.addDynamicActiveClusters(buildDynamicCluster(metadata)); - } - return cdsConfig.setVersionInfo(version).build(); - } - - @VisibleForTesting - static DynamicCluster buildDynamicCluster(ResourceMetadata metadata) { - DynamicCluster.Builder dynamicCluster = DynamicCluster.newBuilder() - .setVersionInfo(metadata.getVersion()) - .setClientStatus(metadataStatusToClientStatus(metadata.getStatus())) - .setLastUpdated(Timestamps.fromNanos(metadata.getUpdateTimeNanos())); - if (metadata.getErrorState() != null) { - dynamicCluster.setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState())); - } - if (metadata.getRawResource() != null) { - dynamicCluster.setCluster(metadata.getRawResource()); - } - return dynamicCluster.build(); - } - - @VisibleForTesting - static EndpointsConfigDump dumpEdsConfig(Map resourcesMetadata) { - EndpointsConfigDump.Builder edsConfig = EndpointsConfigDump.newBuilder(); - for (ResourceMetadata metadata : resourcesMetadata.values()) { - edsConfig.addDynamicEndpointConfigs(buildDynamicEndpointConfig(metadata)); - } - return edsConfig.build(); - } - - @VisibleForTesting - static DynamicEndpointConfig buildDynamicEndpointConfig(ResourceMetadata metadata) { - DynamicEndpointConfig.Builder dynamicRouteConfig = DynamicEndpointConfig.newBuilder() - .setVersionInfo(metadata.getVersion()) - .setClientStatus(metadataStatusToClientStatus(metadata.getStatus())) - .setLastUpdated(Timestamps.fromNanos(metadata.getUpdateTimeNanos())); - if (metadata.getErrorState() != null) { - dynamicRouteConfig.setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState())); - } - if (metadata.getRawResource() != null) { - dynamicRouteConfig.setEndpointConfig(metadata.getRawResource()); + ClientConfig.Builder builder = ClientConfig.newBuilder() + .setNode(xdsClient.getBootstrapInfo().node().toEnvoyProtoNode()); + for (ResourceType type : ResourceType.values()) { + if (type == ResourceType.UNKNOWN) { + continue; + } + Map metadataMap = xdsClient.getSubscribedResourcesMetadata(type); + for (String resourceName : metadataMap.keySet()) { + ResourceMetadata metadata = metadataMap.get(resourceName); + GenericXdsConfig.Builder genericXdsConfigBuilder = GenericXdsConfig.newBuilder() + .setTypeUrl(type.typeUrl()) + .setName(resourceName) + .setClientStatus(metadataStatusToClientStatus(metadata.getStatus())); + if (metadata.getRawResource() != null) { + genericXdsConfigBuilder + .setVersionInfo(metadata.getVersion()) + .setLastUpdated(Timestamps.fromNanos(metadata.getUpdateTimeNanos())) + .setXdsConfig(metadata.getRawResource()); + } + if (metadata.getStatus() == ResourceMetadataStatus.NACKED) { + genericXdsConfigBuilder + .setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState())); + } + builder.addGenericXdsConfigs(genericXdsConfigBuilder); + } } - return dynamicRouteConfig.build(); + return builder.build(); } @VisibleForTesting diff --git a/xds/src/main/java/io/grpc/xds/XdsClient.java b/xds/src/main/java/io/grpc/xds/XdsClient.java index 9a6e28b3f5e..65d4d67c427 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClient.java +++ b/xds/src/main/java/io/grpc/xds/XdsClient.java @@ -494,14 +494,6 @@ TlsContextManager getTlsContextManager() { throw new UnsupportedOperationException(); } - /** - * Returns the latest accepted version of the given resource type. - */ - // TODO(https://github.com/grpc/grpc-java/issues/8629): remove this - String getCurrentVersion(ResourceType type) { - throw new UnsupportedOperationException(); - } - Map getSubscribedResourcesMetadata(ResourceType type) { throw new UnsupportedOperationException(); } diff --git a/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java b/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java index 9a50e2e0599..7c6abee2835 100644 --- a/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java +++ b/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java @@ -17,7 +17,6 @@ package io.grpc.xds; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static io.grpc.xds.AbstractXdsClient.ResourceType.CDS; import static io.grpc.xds.AbstractXdsClient.ResourceType.EDS; import static io.grpc.xds.AbstractXdsClient.ResourceType.LDS; @@ -26,28 +25,17 @@ import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; -import com.google.protobuf.Timestamp; import io.envoyproxy.envoy.admin.v3.ClientResourceStatus; -import io.envoyproxy.envoy.admin.v3.ClustersConfigDump; -import io.envoyproxy.envoy.admin.v3.ClustersConfigDump.DynamicCluster; -import io.envoyproxy.envoy.admin.v3.EndpointsConfigDump; -import io.envoyproxy.envoy.admin.v3.EndpointsConfigDump.DynamicEndpointConfig; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListener; -import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListenerState; -import io.envoyproxy.envoy.admin.v3.RoutesConfigDump; -import io.envoyproxy.envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig; -import io.envoyproxy.envoy.admin.v3.UpdateFailureState; import io.envoyproxy.envoy.config.cluster.v3.Cluster; import io.envoyproxy.envoy.config.core.v3.Node; import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment; import io.envoyproxy.envoy.config.listener.v3.Listener; import io.envoyproxy.envoy.config.route.v3.RouteConfiguration; import io.envoyproxy.envoy.service.status.v3.ClientConfig; +import io.envoyproxy.envoy.service.status.v3.ClientConfig.GenericXdsConfig; import io.envoyproxy.envoy.service.status.v3.ClientStatusDiscoveryServiceGrpc; import io.envoyproxy.envoy.service.status.v3.ClientStatusRequest; import io.envoyproxy.envoy.service.status.v3.ClientStatusResponse; -import io.envoyproxy.envoy.service.status.v3.PerXdsConfig; import io.envoyproxy.envoy.type.matcher.v3.NodeMatcher; import io.grpc.InsecureChannelCredentials; import io.grpc.Status; @@ -92,11 +80,6 @@ Bootstrapper.BootstrapInfo getBootstrapInfo() { .build(); } - @Override - String getCurrentVersion(ResourceType type) { - return "getCurrentVersion." + type.name(); - } - @Override Map getSubscribedResourcesMetadata(ResourceType type) { return ImmutableMap.of(); @@ -266,23 +249,11 @@ public static class MetadataToProtoTests { private static final String RDS_RESOURCE = "route-configuration.googleapis.com"; private static final String CDS_RESOURCE = "cluster.googleapis.com"; private static final String EDS_RESOURCE = "cluster-load-assignment.googleapis.com"; - private static final String VERSION_ACK = "42"; - private static final String VERSION_NACK = "43"; - private static final String ERROR = "Parse error line 1\n Parse error line 2"; - - // Test timestamps. - private static final Timestamp TIMESTAMP_ZERO = Timestamp.getDefaultInstance(); + private static final String VERSION_ACK_LDS = "42"; + private static final String VERSION_ACK_RDS = "38"; + private static final String VERSION_ACK_CDS = "51"; + private static final String VERSION_ACK_EDS = "29"; private static final long NANOS_LAST_UPDATE = 1577923199_606042047L; - private static final Timestamp TIMESTAMP_LAST_UPDATE = Timestamp.newBuilder() - .setSeconds(1577923199L) // 2020-01-01T23:59:59Z - .setNanos(606042047) - .build(); - private static final long NANOS_FAILED_UPDATE = 1609545599_732105843L; - private static final Timestamp TIMESTAMP_FAILED_UPDATE = Timestamp.newBuilder() - .setSeconds(1609545599L) // 2021-01-01T23:59:59Z - .setNanos(732105843) - .build(); - // Raw resources. private static final Any RAW_LISTENER = Any.pack(Listener.newBuilder().setName(LDS_RESOURCE).build()); @@ -293,388 +264,15 @@ public static class MetadataToProtoTests { private static final Any RAW_CLUSTER_LOAD_ASSIGNMENT = Any.pack(ClusterLoadAssignment.newBuilder().setClusterName(EDS_RESOURCE).build()); - // Test metadata: no data received states. - private static final ResourceMetadata METADATA_UNKNOWN = - ResourceMetadata.newResourceMetadataUnknown(); - private static final ResourceMetadata METADATA_DOES_NOT_EXIST = - ResourceMetadata.newResourceMetadataDoesNotExist(); - private static final ResourceMetadata METADATA_REQUESTED = - ResourceMetadata.newResourceMetadataRequested(); - // Test metadata: resource acknowledged state, per resource type. private static final ResourceMetadata METADATA_ACKED_LDS = ResourceMetadata - .newResourceMetadataAcked(RAW_LISTENER, VERSION_ACK, NANOS_LAST_UPDATE); + .newResourceMetadataAcked(RAW_LISTENER, VERSION_ACK_LDS, NANOS_LAST_UPDATE); private static final ResourceMetadata METADATA_ACKED_RDS = ResourceMetadata - .newResourceMetadataAcked(RAW_ROUTE_CONFIGURATION, VERSION_ACK, NANOS_LAST_UPDATE); + .newResourceMetadataAcked(RAW_ROUTE_CONFIGURATION, VERSION_ACK_RDS, NANOS_LAST_UPDATE); private static final ResourceMetadata METADATA_ACKED_CDS = ResourceMetadata - .newResourceMetadataAcked(RAW_CLUSTER, VERSION_ACK, NANOS_LAST_UPDATE); + .newResourceMetadataAcked(RAW_CLUSTER, VERSION_ACK_CDS, NANOS_LAST_UPDATE); private static final ResourceMetadata METADATA_ACKED_EDS = ResourceMetadata - .newResourceMetadataAcked(RAW_CLUSTER_LOAD_ASSIGNMENT, VERSION_ACK, NANOS_LAST_UPDATE); - - // Test resources list. - private static final ImmutableMap RESOURCES_METADATA = - ImmutableMap.of("A", METADATA_UNKNOWN, "B", METADATA_REQUESTED); - - /* LDS tests */ - - @Test - public void dumpLdsConfig() { - ListenersConfigDump ldsConfig = CsdsService.dumpLdsConfig(RESOURCES_METADATA, VERSION_ACK); - assertThat(ldsConfig.getVersionInfo()).isEqualTo(VERSION_ACK); - assertThat(ldsConfig.getStaticListenersCount()).isEqualTo(0); - assertThat(ldsConfig.getDynamicListenersCount()).isEqualTo(2); - // Minimal check to confirm that resources generated from corresponding metadata. - DynamicListener listenerA = ldsConfig.getDynamicListeners(0); - assertThat(listenerA.getName()).isEqualTo("A"); - assertThat(listenerA.getClientStatus()).isEqualTo(ClientResourceStatus.UNKNOWN); - DynamicListener listenerB = ldsConfig.getDynamicListeners(1); - assertThat(listenerB.getName()).isEqualTo("B"); - assertThat(listenerB.getClientStatus()).isEqualTo(ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicListener_metadataUnknown() { - DynamicListener dynamicListener = - CsdsService.buildDynamicListener(LDS_RESOURCE, METADATA_UNKNOWN); - verifyDynamicListener(dynamicListener, ClientResourceStatus.UNKNOWN); - verifyDynamicListenerStateNoData(dynamicListener.getActiveState()); - } - - @Test - public void buildDynamicListener_metadataDoesNotExist() { - DynamicListener dynamicListener = - CsdsService.buildDynamicListener(LDS_RESOURCE, METADATA_DOES_NOT_EXIST); - verifyDynamicListener(dynamicListener, ClientResourceStatus.DOES_NOT_EXIST); - verifyDynamicListenerStateNoData(dynamicListener.getActiveState()); - } - - @Test - public void buildDynamicListener_metadataRequested() { - DynamicListener dynamicListener = - CsdsService.buildDynamicListener(LDS_RESOURCE, METADATA_REQUESTED); - verifyDynamicListener(dynamicListener, ClientResourceStatus.REQUESTED); - verifyDynamicListenerStateNoData(dynamicListener.getActiveState()); - } - - @Test - public void buildDynamicListener_metadataAcked() { - DynamicListener dynamicListener = - CsdsService.buildDynamicListener(LDS_RESOURCE, METADATA_ACKED_LDS); - verifyDynamicListener(dynamicListener, ClientResourceStatus.ACKED); - verifyDynamicListenerStateAccepted(dynamicListener.getActiveState()); - } - - @Test - public void buildDynamicListener_metadataNackedFromRequested() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_REQUESTED, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicListener dynamicListener = CsdsService.buildDynamicListener(LDS_RESOURCE, metadata); - verifyDynamicListener(dynamicListener, ClientResourceStatus.NACKED); - verifyErrorState(dynamicListener.getErrorState()); - verifyDynamicListenerStateNoData(dynamicListener.getActiveState()); - } - - @Test - public void buildDynamicListener_metadataNackedFromAcked() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_ACKED_LDS, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicListener dynamicListener = CsdsService.buildDynamicListener(LDS_RESOURCE, metadata); - verifyDynamicListener(dynamicListener, ClientResourceStatus.NACKED); - verifyErrorState(dynamicListener.getErrorState()); - verifyDynamicListenerStateAccepted(dynamicListener.getActiveState()); - } - - private void verifyDynamicListener( - DynamicListener dynamicListener, ClientResourceStatus status) { - assertWithMessage("name").that(dynamicListener.getName()).isEqualTo(LDS_RESOURCE); - assertWithMessage("active_state").that(dynamicListener.hasActiveState()).isTrue(); - assertWithMessage("warming_state").that(dynamicListener.hasWarmingState()).isFalse(); - assertWithMessage("draining_state").that(dynamicListener.hasDrainingState()).isFalse(); - assertWithMessage("error_state").that(dynamicListener.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicListener.getClientStatus()).isEqualTo(status); - } - - private void verifyDynamicListenerStateNoData(DynamicListenerState dynamicListenerState) { - assertWithMessage("version_info").that(dynamicListenerState.getVersionInfo()).isEmpty(); - assertWithMessage("listener").that(dynamicListenerState.hasListener()).isFalse(); - assertWithMessage("last_updated").that(dynamicListenerState.getLastUpdated()) - .isEqualTo(TIMESTAMP_ZERO); - } - - private void verifyDynamicListenerStateAccepted(DynamicListenerState dynamicListenerState) { - assertWithMessage("version_info").that(dynamicListenerState.getVersionInfo()) - .isEqualTo(VERSION_ACK); - assertWithMessage("listener").that(dynamicListenerState.hasListener()).isTrue(); - assertWithMessage("listener").that(dynamicListenerState.getListener()) - .isEqualTo(RAW_LISTENER); - assertWithMessage("last_updated").that(dynamicListenerState.getLastUpdated()) - .isEqualTo(TIMESTAMP_LAST_UPDATE); - } - - /* RDS tests */ - - @Test - public void dumpRdsConfig() { - RoutesConfigDump rdsConfig = CsdsService.dumpRdsConfig(RESOURCES_METADATA); - assertThat(rdsConfig.getStaticRouteConfigsCount()).isEqualTo(0); - assertThat(rdsConfig.getDynamicRouteConfigsCount()).isEqualTo(2); - // Minimal check to confirm that resources generated from corresponding metadata. - assertThat(rdsConfig.getDynamicRouteConfigs(0).getClientStatus()) - .isEqualTo(ClientResourceStatus.UNKNOWN); - assertThat(rdsConfig.getDynamicRouteConfigs(1).getClientStatus()) - .isEqualTo(ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicRouteConfig_metadataUnknown() { - verifyDynamicRouteConfigNoData( - CsdsService.buildDynamicRouteConfig(METADATA_UNKNOWN), - ClientResourceStatus.UNKNOWN); - } - - @Test - public void buildDynamicRouteConfig_metadataDoesNotExist() { - verifyDynamicRouteConfigNoData( - CsdsService.buildDynamicRouteConfig(METADATA_DOES_NOT_EXIST), - ClientResourceStatus.DOES_NOT_EXIST); - } - - @Test - public void buildDynamicRouteConfig_metadataRequested() { - verifyDynamicRouteConfigNoData( - CsdsService.buildDynamicRouteConfig(METADATA_REQUESTED), - ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicRouteConfig_metadataAcked() { - verifyDynamicRouteConfigAccepted( - CsdsService.buildDynamicRouteConfig(METADATA_ACKED_RDS), - ClientResourceStatus.ACKED); - } - - @Test - public void buildDynamicRouteConfig_metadataNackedFromRequested() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_REQUESTED, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata); - verifyDynamicRouteConfigNoData(dynamicRouteConfig, ClientResourceStatus.NACKED); - verifyErrorState(dynamicRouteConfig.getErrorState()); - } - - @Test - public void buildDynamicRouteConfig_metadataNackedFromAcked() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_ACKED_RDS, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata); - verifyDynamicRouteConfigAccepted(dynamicRouteConfig, ClientResourceStatus.NACKED); - verifyErrorState(dynamicRouteConfig.getErrorState()); - } - - private void verifyDynamicRouteConfigNoData( - DynamicRouteConfig dynamicRouteConfig, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicRouteConfig.getVersionInfo()).isEmpty(); - assertWithMessage("route_config").that(dynamicRouteConfig.hasRouteConfig()).isFalse(); - assertWithMessage("last_updated").that(dynamicRouteConfig.getLastUpdated()) - .isEqualTo(TIMESTAMP_ZERO); - assertWithMessage("error_state").that(dynamicRouteConfig.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicRouteConfig.getClientStatus()) - .isEqualTo(status); - } - - private void verifyDynamicRouteConfigAccepted( - DynamicRouteConfig dynamicRouteConfig, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicRouteConfig.getVersionInfo()) - .isEqualTo(VERSION_ACK); - assertWithMessage("route_config").that(dynamicRouteConfig.hasRouteConfig()).isTrue(); - assertWithMessage("route_config").that(dynamicRouteConfig.getRouteConfig()) - .isEqualTo(RAW_ROUTE_CONFIGURATION); - assertWithMessage("last_updated").that(dynamicRouteConfig.getLastUpdated()) - .isEqualTo(TIMESTAMP_LAST_UPDATE); - assertWithMessage("error_state").that(dynamicRouteConfig.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicRouteConfig.getClientStatus()) - .isEqualTo(status); - } - - /* CDS tests */ - - @Test - public void dumpCdsConfig() { - ClustersConfigDump cdsConfig = CsdsService.dumpCdsConfig(RESOURCES_METADATA, VERSION_ACK); - assertThat(cdsConfig.getVersionInfo()).isEqualTo(VERSION_ACK); - assertThat(cdsConfig.getStaticClustersCount()).isEqualTo(0); - assertThat(cdsConfig.getDynamicWarmingClustersCount()).isEqualTo(0); - assertThat(cdsConfig.getDynamicActiveClustersCount()).isEqualTo(2); - // Minimal check to confirm that resources generated from corresponding metadata. - assertThat(cdsConfig.getDynamicActiveClusters(0).getClientStatus()) - .isEqualTo(ClientResourceStatus.UNKNOWN); - assertThat(cdsConfig.getDynamicActiveClusters(1).getClientStatus()) - .isEqualTo(ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicCluster_metadataUnknown() { - verifyDynamicClusterNoData( - CsdsService.buildDynamicCluster(METADATA_UNKNOWN), - ClientResourceStatus.UNKNOWN); - } - - @Test - public void buildDynamicCluster_metadataDoesNotExist() { - verifyDynamicClusterNoData( - CsdsService.buildDynamicCluster(METADATA_DOES_NOT_EXIST), - ClientResourceStatus.DOES_NOT_EXIST); - } - - @Test - public void buildDynamicCluster_metadataRequested() { - verifyDynamicClusterNoData( - CsdsService.buildDynamicCluster(METADATA_REQUESTED), - ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicCluster_metadataAcked() { - verifyDynamicClusterAccepted( - CsdsService.buildDynamicCluster(METADATA_ACKED_CDS), - ClientResourceStatus.ACKED); - } - - @Test - public void buildDynamicCluster_metadataNackedFromRequested() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_REQUESTED, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicCluster dynamicCluster = CsdsService.buildDynamicCluster(metadata); - verifyDynamicClusterNoData(dynamicCluster, ClientResourceStatus.NACKED); - verifyErrorState(dynamicCluster.getErrorState()); - } - - @Test - public void buildDynamicCluster_metadataNackedFromAcked() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_ACKED_CDS, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicCluster dynamicCluster = CsdsService.buildDynamicCluster(metadata); - verifyDynamicClusterAccepted(dynamicCluster, ClientResourceStatus.NACKED); - verifyErrorState(dynamicCluster.getErrorState()); - } - - private void verifyDynamicClusterNoData( - DynamicCluster dynamicCluster, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicCluster.getVersionInfo()).isEmpty(); - assertWithMessage("route_config").that(dynamicCluster.hasCluster()).isFalse(); - assertWithMessage("last_updated").that(dynamicCluster.getLastUpdated()) - .isEqualTo(TIMESTAMP_ZERO); - assertWithMessage("error_state").that(dynamicCluster.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicCluster.getClientStatus()).isEqualTo(status); - } - - private void verifyDynamicClusterAccepted( - DynamicCluster dynamicCluster, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicCluster.getVersionInfo()) - .isEqualTo(VERSION_ACK); - assertWithMessage("route_config").that(dynamicCluster.hasCluster()).isTrue(); - assertWithMessage("route_config").that(dynamicCluster.getCluster()).isEqualTo(RAW_CLUSTER); - assertWithMessage("last_updated").that(dynamicCluster.getLastUpdated()) - .isEqualTo(TIMESTAMP_LAST_UPDATE); - assertWithMessage("error_state").that(dynamicCluster.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicCluster.getClientStatus()).isEqualTo(status); - } - - /* EDS tests */ - - @Test - public void dumpEdsConfig() { - EndpointsConfigDump edsConfig = CsdsService.dumpEdsConfig(RESOURCES_METADATA); - assertThat(edsConfig.getStaticEndpointConfigsCount()).isEqualTo(0); - assertThat(edsConfig.getDynamicEndpointConfigsCount()).isEqualTo(2); - // Minimal check to confirm that resources generated from corresponding metadata. - assertThat(edsConfig.getDynamicEndpointConfigs(0).getClientStatus()) - .isEqualTo(ClientResourceStatus.UNKNOWN); - assertThat(edsConfig.getDynamicEndpointConfigs(1).getClientStatus()) - .isEqualTo(ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicEndpointConfig_metadataUnknown() { - buildDynamicEndpointConfigNoData( - CsdsService.buildDynamicEndpointConfig(METADATA_UNKNOWN), - ClientResourceStatus.UNKNOWN); - } - - @Test - public void buildDynamicEndpointConfig_metadataDoesNotExist() { - buildDynamicEndpointConfigNoData( - CsdsService.buildDynamicEndpointConfig(METADATA_DOES_NOT_EXIST), - ClientResourceStatus.DOES_NOT_EXIST); - } - - @Test - public void buildDynamicEndpointConfig_metadataRequested() { - buildDynamicEndpointConfigNoData( - CsdsService.buildDynamicEndpointConfig(METADATA_REQUESTED), - ClientResourceStatus.REQUESTED); - } - - @Test - public void buildDynamicEndpointConfig_metadataAcked() { - verifyDynamicEndpointConfigAccepted( - CsdsService.buildDynamicEndpointConfig(METADATA_ACKED_EDS), - ClientResourceStatus.ACKED); - } - - @Test - public void buildDynamicEndpointConfig_metadataNackedFromRequested() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_REQUESTED, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicEndpointConfig dynamicEndpointConfig = - CsdsService.buildDynamicEndpointConfig(metadata); - buildDynamicEndpointConfigNoData(dynamicEndpointConfig, ClientResourceStatus.NACKED); - verifyErrorState(dynamicEndpointConfig.getErrorState()); - } - - @Test - public void buildDynamicEndpointConfig_metadataNackedFromAcked() { - ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked( - METADATA_ACKED_EDS, VERSION_NACK, NANOS_FAILED_UPDATE, ERROR); - DynamicEndpointConfig dynamicEndpointConfig = - CsdsService.buildDynamicEndpointConfig(metadata); - verifyDynamicEndpointConfigAccepted(dynamicEndpointConfig, ClientResourceStatus.NACKED); - verifyErrorState(dynamicEndpointConfig.getErrorState()); - } - - private void buildDynamicEndpointConfigNoData( - DynamicEndpointConfig dynamicEndpointConfig, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicEndpointConfig.getVersionInfo()).isEmpty(); - assertWithMessage("route_config").that(dynamicEndpointConfig.hasEndpointConfig()).isFalse(); - assertWithMessage("last_updated").that(dynamicEndpointConfig.getLastUpdated()) - .isEqualTo(TIMESTAMP_ZERO); - assertWithMessage("error_state").that(dynamicEndpointConfig.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicEndpointConfig.getClientStatus()) - .isEqualTo(status); - } - - private void verifyDynamicEndpointConfigAccepted( - DynamicEndpointConfig dynamicEndpointConfig, ClientResourceStatus status) { - assertWithMessage("version_info").that(dynamicEndpointConfig.getVersionInfo()) - .isEqualTo(VERSION_ACK); - assertWithMessage("route_config").that(dynamicEndpointConfig.hasEndpointConfig()).isTrue(); - assertWithMessage("route_config").that(dynamicEndpointConfig.getEndpointConfig()) - .isEqualTo(RAW_CLUSTER_LOAD_ASSIGNMENT); - assertWithMessage("last_updated").that(dynamicEndpointConfig.getLastUpdated()) - .isEqualTo(TIMESTAMP_LAST_UPDATE); - assertWithMessage("error_state").that(dynamicEndpointConfig.hasErrorState()) - .isEqualTo(status.equals(ClientResourceStatus.NACKED)); - assertWithMessage("client_status").that(dynamicEndpointConfig.getClientStatus()) - .isEqualTo(status); - } - - /* Common methods. */ + .newResourceMetadataAcked(RAW_CLUSTER_LOAD_ASSIGNMENT, VERSION_ACK_EDS, NANOS_LAST_UPDATE); @Test public void metadataStatusToClientStatus() { @@ -691,7 +289,7 @@ public void metadataStatusToClientStatus() { } @Test - public void getClientConfigForXdsClient_subscribedResourcesToPerXdsConfig() { + public void getClientConfigForXdsClient_subscribedResourcesToGenericXdsConfig() { ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(new XdsClient() { @Override Bootstrapper.BootstrapInfo getBootstrapInfo() { @@ -703,11 +301,6 @@ Bootstrapper.BootstrapInfo getBootstrapInfo() { .build(); } - @Override - String getCurrentVersion(ResourceType type) { - return "getCurrentVersion." + type.name(); - } - @Override Map getSubscribedResourcesMetadata(ResourceType type) { switch (type) { @@ -730,58 +323,35 @@ Map getSubscribedResourcesMetadata(ResourceType type) // Minimal verification to confirm that the data/metadata XdsClient provides, // is propagated to the correct resource types. - @SuppressWarnings("deprecation") - int xdsConfigCount = clientConfig.getXdsConfigCount(); + int xdsConfigCount = clientConfig.getGenericXdsConfigsCount(); assertThat(xdsConfigCount).isEqualTo(4); - EnumMap configDumps = mapConfigDumps(clientConfig); + EnumMap configDumps = mapConfigDumps(clientConfig); assertThat(configDumps.keySet()).containsExactly(LDS, RDS, CDS, EDS); // LDS. - // Both the version provided by XdsClient.getCurrentVersion(), - // and the resource name provided by XdsClient.getSubscribedResourcesMetadata() are used. - PerXdsConfig perXdsConfigLds = configDumps.get(LDS); - verifyPerXdsConfigEmptyFields(perXdsConfigLds); - ListenersConfigDump listenerConfig = perXdsConfigLds.getListenerConfig(); - assertThat(listenerConfig.getVersionInfo()).isEqualTo("getCurrentVersion.LDS"); - assertThat(listenerConfig.getDynamicListenersCount()).isEqualTo(1); - DynamicListener dynamicListener = listenerConfig.getDynamicListeners(0); - assertThat(dynamicListener.getName()).isEqualTo("subscribedResourceName.LDS"); - assertThat(dynamicListener.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); - assertThat(dynamicListener.getActiveState().getVersionInfo()).isEqualTo(VERSION_ACK); + GenericXdsConfig genericXdsConfigLds = configDumps.get(LDS); + assertThat(genericXdsConfigLds.getName()).isEqualTo("subscribedResourceName.LDS"); + assertThat(genericXdsConfigLds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); + assertThat(genericXdsConfigLds.getVersionInfo()).isEqualTo(VERSION_ACK_LDS); + assertThat(genericXdsConfigLds.getXdsConfig()).isEqualTo(RAW_LISTENER); // RDS. - // Neither the version provided by XdsClient.getCurrentVersion(), - // nor the resource name provided by XdsClient.getSubscribedResourcesMetadata() are used. - PerXdsConfig perXdsConfigRds = configDumps.get(RDS); - verifyPerXdsConfigEmptyFields(perXdsConfigRds); - RoutesConfigDump routeConfig = perXdsConfigRds.getRouteConfig(); - assertThat(routeConfig.getDynamicRouteConfigsCount()).isEqualTo(1); - DynamicRouteConfig dynamicRouteConfig = routeConfig.getDynamicRouteConfigs(0); - assertThat(dynamicRouteConfig.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); - assertThat(dynamicRouteConfig.getVersionInfo()).isEqualTo(VERSION_ACK); + GenericXdsConfig genericXdsConfigRds = configDumps.get(RDS); + assertThat(genericXdsConfigRds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); + assertThat(genericXdsConfigRds.getVersionInfo()).isEqualTo(VERSION_ACK_RDS); + assertThat(genericXdsConfigRds.getXdsConfig()).isEqualTo(RAW_ROUTE_CONFIGURATION); // CDS. - // Only the version provided by XdsClient.getCurrentVersion() is used, - // the resource name provided by XdsClient.getSubscribedResourcesMetadata() is ignored. - PerXdsConfig perXdsConfigCds = configDumps.get(CDS); - verifyPerXdsConfigEmptyFields(perXdsConfigRds); - ClustersConfigDump clusterConfig = perXdsConfigCds.getClusterConfig(); - assertThat(clusterConfig.getVersionInfo()).isEqualTo("getCurrentVersion.CDS"); - assertThat(clusterConfig.getDynamicActiveClustersCount()).isEqualTo(1); - DynamicCluster dynamicCluster = clusterConfig.getDynamicActiveClusters(0); - assertThat(dynamicCluster.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); - assertThat(dynamicCluster.getVersionInfo()).isEqualTo(VERSION_ACK); + GenericXdsConfig genericXdsConfigCds = configDumps.get(CDS); + assertThat(genericXdsConfigCds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); + assertThat(genericXdsConfigCds.getVersionInfo()).isEqualTo(VERSION_ACK_CDS); + assertThat(genericXdsConfigCds.getXdsConfig()).isEqualTo(RAW_CLUSTER); // RDS. - // Neither the version provided by XdsClient.getCurrentVersion(), - // nor the resource name provided by XdsClient.getSubscribedResourcesMetadata() are used. - PerXdsConfig perXdsConfigEds = configDumps.get(EDS); - verifyPerXdsConfigEmptyFields(perXdsConfigEds); - EndpointsConfigDump endpointConfig = perXdsConfigEds.getEndpointConfig(); - assertThat(endpointConfig.getDynamicEndpointConfigsCount()).isEqualTo(1); - DynamicEndpointConfig dynamicEndpointConfig = endpointConfig.getDynamicEndpointConfigs(0); - assertThat(dynamicEndpointConfig.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); - assertThat(dynamicEndpointConfig.getVersionInfo()).isEqualTo(VERSION_ACK); + GenericXdsConfig genericXdsConfigEds = configDumps.get(EDS); + assertThat(genericXdsConfigEds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); + assertThat(genericXdsConfigEds.getVersionInfo()).isEqualTo(VERSION_ACK_EDS); + assertThat(genericXdsConfigEds.getXdsConfig()).isEqualTo(RAW_CLUSTER_LOAD_ASSIGNMENT); } @Test @@ -790,15 +360,6 @@ public void getClientConfigForXdsClient_noSubscribedResources() { verifyClientConfigNode(clientConfig); verifyClientConfigNoResources(clientConfig); } - - private void verifyErrorState(UpdateFailureState errorState) { - // failed_configuration currently not supported. - assertWithMessage("failed_configuration").that(errorState.hasFailedConfiguration()).isFalse(); - assertWithMessage("last_update_attempt").that(errorState.getLastUpdateAttempt()) - .isEqualTo(TIMESTAMP_FAILED_UPDATE); - assertWithMessage("details").that(errorState.getDetails()).isEqualTo(ERROR); - assertWithMessage("version_info").that(errorState.getVersionInfo()).isEqualTo(VERSION_NACK); - } } /** @@ -806,26 +367,10 @@ private void verifyErrorState(UpdateFailureState errorState) { * config dumps correctly, perform a minimal verification of the general shape of ClientConfig. */ private static void verifyClientConfigNoResources(ClientConfig clientConfig) { - // Expect PerXdsConfig for all resource types to be present, but empty. - @SuppressWarnings("deprecation") - int xdsConfigCount = clientConfig.getXdsConfigCount(); - assertThat(xdsConfigCount).isEqualTo(4); - EnumMap configDumps = mapConfigDumps(clientConfig); - assertThat(configDumps.keySet()).containsExactly(LDS, RDS, CDS, EDS); - - ListenersConfigDump listenerConfig = configDumps.get(LDS).getListenerConfig(); - assertThat(listenerConfig.getVersionInfo()).isEqualTo("getCurrentVersion.LDS"); - assertThat(listenerConfig.getDynamicListenersCount()).isEqualTo(0); - - RoutesConfigDump routeConfig = configDumps.get(RDS).getRouteConfig(); - assertThat(routeConfig.getDynamicRouteConfigsCount()).isEqualTo(0); - - ClustersConfigDump clusterConfig = configDumps.get(CDS).getClusterConfig(); - assertThat(clusterConfig.getVersionInfo()).isEqualTo("getCurrentVersion.CDS"); - assertThat(clusterConfig.getDynamicActiveClustersCount()).isEqualTo(0); - - EndpointsConfigDump endpointConfig = configDumps.get(EDS).getEndpointConfig(); - assertThat(endpointConfig.getDynamicEndpointConfigsCount()).isEqualTo(0); + int xdsConfigCount = clientConfig.getGenericXdsConfigsCount(); + assertThat(xdsConfigCount).isEqualTo(0); + EnumMap configDumps = mapConfigDumps(clientConfig); + assertThat(configDumps).isEmpty(); } /** @@ -838,42 +383,18 @@ private static void verifyClientConfigNode(ClientConfig clientConfig) { assertThat(node).isEqualTo(BOOTSTRAP_NODE.toEnvoyProtoNode()); } - /** Verify PerXdsConfig fields that are expected to be omitted. */ - private static void verifyPerXdsConfigEmptyFields(PerXdsConfig perXdsConfig) { - assertThat(perXdsConfig.getStatusValue()).isEqualTo(0); - @SuppressWarnings("deprecation") - int clientStatusValue = perXdsConfig.getClientStatusValue(); - assertThat(clientStatusValue).isEqualTo(0); - } - - private static EnumMap mapConfigDumps(ClientConfig config) { - EnumMap xdsConfigMap = new EnumMap<>(ResourceType.class); - @SuppressWarnings("deprecation") - List xdsConfigList = config.getXdsConfigList(); - for (PerXdsConfig perXdsConfig : xdsConfigList) { - ResourceType type = perXdsConfigToResourceType(perXdsConfig); + private static EnumMap mapConfigDumps(ClientConfig config) { + EnumMap xdsConfigMap = new EnumMap<>(ResourceType.class); + List xdsConfigList = config.getGenericXdsConfigsList(); + for (GenericXdsConfig genericXdsConfig : xdsConfigList) { + ResourceType type = ResourceType.fromTypeUrl(genericXdsConfig.getTypeUrl()); assertThat(type).isNotEqualTo(ResourceType.UNKNOWN); assertThat(xdsConfigMap).doesNotContainKey(type); - xdsConfigMap.put(type, perXdsConfig); + xdsConfigMap.put(type, genericXdsConfig); } return xdsConfigMap; } - private static ResourceType perXdsConfigToResourceType(PerXdsConfig perXdsConfig) { - switch (perXdsConfig.getPerXdsConfigCase()) { - case LISTENER_CONFIG: - return LDS; - case CLUSTER_CONFIG: - return CDS; - case ROUTE_CONFIG: - return RDS; - case ENDPOINT_CONFIG: - return EDS; - default: - return ResourceType.UNKNOWN; - } - } - private static class FakeXdsClientPoolFactory implements XdsClientPoolFactory { @Nullable private final XdsClient xdsClient; From ad0971ef5fa614521e8a6973faa775e87d105e38 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Wed, 10 Nov 2021 11:27:42 -0800 Subject: [PATCH 0005/2009] xds: fix parsing RouteLookupClusterSpecifier mistake (#8641) - Partially revert the change of RlsProtoData.java in #8612 by removing `public` accessor - Have grpc-xds no longer strongly depend on grpc-rls. The application will need grpc-rls as runtime dependencies if they need route lookup feature in xds. - Parse RouteLookupServiceClusterSpecifierPlugin config to the Json/Map representation of `io.grpc.lookup.v1.RouteLookupClusterSpecifier` instead of `io.grpc.rls.RlsProtoData.RouteLookupConfig` --- .../main/java/io/grpc/rls/RlsProtoData.java | 26 ++--- xds/build.gradle | 2 +- .../main/java/io/grpc/xds/MessagePrinter.java | 21 +++- ...teLookupServiceClusterSpecifierPlugin.java | 107 ++++++------------ ...okupServiceClusterSpecifierPluginTest.java | 100 ++++++++-------- 5 files changed, 109 insertions(+), 147 deletions(-) diff --git a/rls/src/main/java/io/grpc/rls/RlsProtoData.java b/rls/src/main/java/io/grpc/rls/RlsProtoData.java index 5192e9cf075..32dc81829b3 100644 --- a/rls/src/main/java/io/grpc/rls/RlsProtoData.java +++ b/rls/src/main/java/io/grpc/rls/RlsProtoData.java @@ -25,7 +25,6 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.grpc.Internal; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import java.util.HashSet; import java.util.List; @@ -36,8 +35,7 @@ import javax.annotation.concurrent.Immutable; /** RlsProtoData is a collection of internal representation of RouteLookupService proto messages. */ -@Internal -public final class RlsProtoData { +final class RlsProtoData { private RlsProtoData() {} @@ -142,7 +140,7 @@ public String toString() { /** A config object for gRPC RouteLookupService. */ @Immutable - public static final class RouteLookupConfig { + static final class RouteLookupConfig { private static final long MAX_AGE_MILLIS = TimeUnit.MINUTES.toMillis(5); private static final long MAX_CACHE_SIZE = 5 * 1024 * 1024; @@ -164,8 +162,7 @@ public static final class RouteLookupConfig { @Nullable private final String defaultTarget; - /** Constructor. */ - public RouteLookupConfig( + RouteLookupConfig( List grpcKeyBuilders, String lookupService, long lookupServiceTimeoutInMillis, @@ -336,7 +333,7 @@ private static void checkUniqueName(List grpcKeyBuilders) { * is true, one of the specified names must be present for the keybuilder to match. */ @Immutable - public static final class NameMatcher { + static final class NameMatcher { private final String key; @@ -344,8 +341,7 @@ public static final class NameMatcher { private final boolean optional; - /** Constructor. */ - public NameMatcher(String key, List names, @Nullable Boolean optional) { + NameMatcher(String key, List names, @Nullable Boolean optional) { this.key = checkNotNull(key, "key"); this.names = ImmutableList.copyOf(checkNotNull(names, "names")); this.optional = optional != null ? optional : true; @@ -398,7 +394,7 @@ public String toString() { } /** GrpcKeyBuilder is a configuration to construct headers consumed by route lookup service. */ - public static final class GrpcKeyBuilder { + static final class GrpcKeyBuilder { private final ImmutableList names; @@ -407,7 +403,7 @@ public static final class GrpcKeyBuilder { private final ImmutableMap constantKeys; /** Constructor. All args should be nonnull. Headers should head unique keys. */ - public GrpcKeyBuilder( + GrpcKeyBuilder( List names, List headers, ExtraKeys extraKeys, Map constantKeys) { checkState(names != null && !names.isEmpty(), "names cannot be empty"); @@ -486,7 +482,7 @@ public String toString() { * required and includes the proto package name. The method name may be omitted, in which case * any method on the given service is matched. */ - public static final class Name { + static final class Name { private final String service; @@ -497,7 +493,7 @@ public Name(String service) { } /** The primary constructor. */ - public Name(String service, String method) { + Name(String service, String method) { checkState( !checkNotNull(service, "service").isEmpty(), "service must not be empty or null"); @@ -542,7 +538,7 @@ public String toString() { } @AutoValue - public abstract static class ExtraKeys { + abstract static class ExtraKeys { static final ExtraKeys DEFAULT = create(null, null, null); @Nullable abstract String host(); @@ -551,7 +547,7 @@ public abstract static class ExtraKeys { @Nullable abstract String method(); - public static ExtraKeys create( + static ExtraKeys create( @Nullable String host, @Nullable String service, @Nullable String method) { return new AutoValue_RlsProtoData_ExtraKeys(host, service, method); } diff --git a/xds/build.gradle b/xds/build.gradle index a8dbde3e0a1..3af4f75d62c 100644 --- a/xds/build.gradle +++ b/xds/build.gradle @@ -39,9 +39,9 @@ dependencies { libraries.autovalue_annotation, libraries.opencensus_proto, libraries.protobuf_util - implementation project(path: ':grpc-rls') def nettyDependency = implementation project(':grpc-netty') + testImplementation project(':grpc-rls') testImplementation project(':grpc-core').sourceSets.test.output annotationProcessor libraries.autovalue diff --git a/xds/src/main/java/io/grpc/xds/MessagePrinter.java b/xds/src/main/java/io/grpc/xds/MessagePrinter.java index 249e1f0e965..a2f51443e3d 100644 --- a/xds/src/main/java/io/grpc/xds/MessagePrinter.java +++ b/xds/src/main/java/io/grpc/xds/MessagePrinter.java @@ -16,7 +16,9 @@ package io.grpc.xds; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.TypeRegistry; import com.google.protobuf.util.JsonFormat; @@ -46,7 +48,7 @@ private static class LazyHolder { static final JsonFormat.Printer printer = newPrinter(); private static JsonFormat.Printer newPrinter() { - TypeRegistry registry = + TypeRegistry.Builder registry = TypeRegistry.newBuilder() .add(Listener.getDescriptor()) .add(io.envoyproxy.envoy.api.v2.Listener.getDescriptor()) @@ -71,9 +73,20 @@ private static JsonFormat.Printer newPrinter() { .add(io.envoyproxy.envoy.config.cluster.aggregate.v2alpha.ClusterConfig .getDescriptor()) .add(ClusterLoadAssignment.getDescriptor()) - .add(io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.getDescriptor()) - .build(); - return JsonFormat.printer().usingTypeRegistry(registry); + .add(io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.getDescriptor()); + try { + @SuppressWarnings("unchecked") + Class routeLookupClusterSpecifierClass = + (Class) + Class.forName("io.grpc.lookup.v1.RouteLookupClusterSpecifier"); + Descriptor descriptor = + (Descriptor) + routeLookupClusterSpecifierClass.getDeclaredMethod("getDescriptor").invoke(null); + registry.add(descriptor); + } catch (Exception e) { + // Ignore. In most cases RouteLookup is not required. + } + return JsonFormat.printer().usingTypeRegistry(registry.build()); } } diff --git a/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java b/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java index 8bec286925f..64464f03737 100644 --- a/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java +++ b/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java @@ -17,18 +17,14 @@ package io.grpc.xds; import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; -import com.google.protobuf.util.Durations; -import io.grpc.lookup.v1.GrpcKeyBuilder; -import io.grpc.lookup.v1.GrpcKeyBuilder.ExtraKeys; -import io.grpc.lookup.v1.GrpcKeyBuilder.Name; -import io.grpc.lookup.v1.NameMatcher; -import io.grpc.lookup.v1.RouteLookupConfig; -import io.grpc.rls.RlsProtoData; -import java.util.ArrayList; -import java.util.List; +import io.grpc.internal.JsonParser; +import io.grpc.internal.JsonUtil; +import java.io.IOException; +import java.util.Map; /** The ClusterSpecifierPlugin for RouteLookup policy. */ final class RouteLookupServiceClusterSpecifierPlugin implements ClusterSpecifierPlugin { @@ -49,84 +45,49 @@ public String[] typeUrls() { } @Override + @SuppressWarnings("unchecked") public ConfigOrError parsePlugin(Message rawProtoMessage) { if (!(rawProtoMessage instanceof Any)) { return ConfigOrError.fromError("Invalid config type: " + rawProtoMessage.getClass()); } - - Any anyMessage = (Any) rawProtoMessage; - RouteLookupConfig configProto; - try { - configProto = anyMessage.unpack(RouteLookupConfig.class); - } catch (InvalidProtocolBufferException e) { - return ConfigOrError.fromError("Invalid proto: " + e); - } try { - List keyBuildersProto = configProto.getGrpcKeybuildersList(); - List keyBuilders = - new ArrayList<>(keyBuildersProto.size()); - for (GrpcKeyBuilder keyBuilderProto : keyBuildersProto) { - List namesProto = keyBuilderProto.getNamesList(); - List names = new ArrayList<>(namesProto.size()); - for (Name nameProto : namesProto) { - if (nameProto.getMethod().isEmpty()) { - names.add(new RlsProtoData.GrpcKeyBuilder.Name(nameProto.getService())); - } else { - names.add( - new RlsProtoData.GrpcKeyBuilder.Name( - nameProto.getService(), nameProto.getMethod())); - } - } - - List headersProto = keyBuilderProto.getHeadersList(); - List headers = new ArrayList<>(headersProto.size()); - for (NameMatcher headerProto : headersProto) { - headers.add( - new RlsProtoData.NameMatcher( - headerProto.getKey(), headerProto.getNamesList(), - headerProto.getRequiredMatch())); - } - - String host = null; - String service = null; - String method = null; - if (keyBuilderProto.hasExtraKeys()) { - ExtraKeys extraKeysProto = keyBuilderProto.getExtraKeys(); - host = extraKeysProto.getHost(); - service = extraKeysProto.getService(); - method = extraKeysProto.getMethod(); - } - RlsProtoData.ExtraKeys extraKeys = - RlsProtoData.ExtraKeys.create(host, service, method); - - RlsProtoData.GrpcKeyBuilder keyBuilder = - new RlsProtoData.GrpcKeyBuilder( - names, headers, extraKeys, keyBuilderProto.getConstantKeysMap()); - keyBuilders.add(keyBuilder); + Any anyMessage = (Any) rawProtoMessage; + Class protoClass; + try { + protoClass = + (Class) + Class.forName("io.grpc.lookup.v1.RouteLookupClusterSpecifier"); + } catch (ClassNotFoundException e) { + return ConfigOrError.fromError("Dependency for 'io.grpc:grpc-rls' is missing: " + e); + } + Message configProto; + try { + configProto = anyMessage.unpack(protoClass); + } catch (InvalidProtocolBufferException e) { + return ConfigOrError.fromError("Invalid proto: " + e); + } + String jsonString = MessagePrinter.print(configProto); + try { + Map jsonMap = (Map) JsonParser.parse(jsonString); + Map config = JsonUtil.getObject(jsonMap, "routeLookupConfig"); + return ConfigOrError.fromConfig(RlsPluginConfig.create(config)); + } catch (IOException e) { + return ConfigOrError.fromError( + "Unable to parse RouteLookupClusterSpecifier: " + jsonString); } - RlsProtoData.RouteLookupConfig config = new RlsProtoData.RouteLookupConfig( - keyBuilders, - configProto.getLookupService(), - Durations.toMillis(configProto.getLookupServiceTimeout()), - configProto.hasMaxAge() ? Durations.toMillis(configProto.getMaxAge()) : null, - configProto.hasStaleAge() ? Durations.toMillis(configProto.getStaleAge()) : null, - configProto.getCacheSizeBytes(), - configProto.getValidTargetsList(), - configProto.getDefaultTarget()); - return ConfigOrError.fromConfig(RlsPluginConfig.create(config)); } catch (RuntimeException e) { - return ConfigOrError.fromError( - "Error parsing RouteLookupConfig: \n" + configProto + "\n reason: " + e); + return ConfigOrError.fromError("Error parsing RouteLookupConfig: " + e); } } @AutoValue abstract static class RlsPluginConfig implements PluginConfig { - abstract RlsProtoData.RouteLookupConfig config(); + abstract ImmutableMap config(); - static RlsPluginConfig create(RlsProtoData.RouteLookupConfig config) { - return new AutoValue_RouteLookupServiceClusterSpecifierPlugin_RlsPluginConfig(config); + static RlsPluginConfig create(Map config) { + return new AutoValue_RouteLookupServiceClusterSpecifierPlugin_RlsPluginConfig( + ImmutableMap.copyOf(config)); } @Override diff --git a/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java b/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java index 1bfe4a26f24..f8d1c2ef7c0 100644 --- a/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java +++ b/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java @@ -26,8 +26,8 @@ import io.grpc.lookup.v1.GrpcKeyBuilder.ExtraKeys; import io.grpc.lookup.v1.GrpcKeyBuilder.Name; import io.grpc.lookup.v1.NameMatcher; +import io.grpc.lookup.v1.RouteLookupClusterSpecifier; import io.grpc.lookup.v1.RouteLookupConfig; -import io.grpc.rls.RlsProtoData; import io.grpc.xds.RouteLookupServiceClusterSpecifierPlugin.RlsPluginConfig; import org.junit.Test; import org.junit.runner.RunWith; @@ -57,29 +57,38 @@ public void parseConfigWithAllFieldsGiven() { .addValidTargets("valid-target") .setDefaultTarget("default-target") .build(); + RouteLookupClusterSpecifier specifier = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig).build(); RlsPluginConfig config = - RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(routeLookupConfig)) + RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(specifier)) .config; assertThat(config.typeUrl()).isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupConfig"); assertThat(config.config()).isEqualTo( - new RlsProtoData.RouteLookupConfig( - ImmutableList.of( - new RlsProtoData.GrpcKeyBuilder( + ImmutableMap.builder() + .put( + "grpcKeybuilders", + ImmutableList.of(ImmutableMap.of( + "names", ImmutableList.of( - new RlsProtoData.GrpcKeyBuilder.Name("service1", "method1"), - new RlsProtoData.GrpcKeyBuilder.Name("service2", "method2")), + ImmutableMap.of("service", "service1", "method", "method1"), + ImmutableMap.of("service", "service2", "method", "method2")), + "headers", ImmutableList.of( - new RlsProtoData.NameMatcher("key1", ImmutableList.of("v1"), true)), - RlsProtoData.ExtraKeys.create("host1", "service1", "method1"), - ImmutableMap.of("key2", "value2") - )), - "rls-cbt.googleapis.com", - 1234, - 56789L, - 1000L, - 5000, - ImmutableList.of("valid-target"), - "default-target")); + ImmutableMap.of( + "key", "key1", "names", ImmutableList.of("v1"), + "requiredMatch", true)), + "extraKeys", + ImmutableMap.of("host", "host1", "service", "service1", "method", "method1"), + "constantKeys", + ImmutableMap.of("key2", "value2")))) + .put("lookupService", "rls-cbt.googleapis.com") + .put("lookupServiceTimeout", "1.234s") + .put("maxAge", "56.789s") + .put("staleAge", "1s") + .put("cacheSizeBytes", "5000") + .put("validTargets", ImmutableList.of("valid-target")) + .put("defaultTarget","default-target") + .build()); } @Test @@ -96,47 +105,30 @@ public void parseConfigWithOptionalFieldsUnspecified() { .setCacheSizeBytes(5000) .addValidTargets("valid-target") .build(); + RouteLookupClusterSpecifier specifier = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig).build(); RlsPluginConfig config = - RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(routeLookupConfig)) + RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(specifier)) .config; assertThat(config.typeUrl()).isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupConfig"); assertThat(config.config()).isEqualTo( - new RlsProtoData.RouteLookupConfig( - ImmutableList.of( - new RlsProtoData.GrpcKeyBuilder( + ImmutableMap.builder() + .put( + "grpcKeybuilders", + ImmutableList.of(ImmutableMap.of( + "names", ImmutableList.of( - new RlsProtoData.GrpcKeyBuilder.Name("service1"), - new RlsProtoData.GrpcKeyBuilder.Name("service2")), + ImmutableMap.of("service", "service1"), + ImmutableMap.of("service", "service2")), + "headers", ImmutableList.of( - new RlsProtoData.NameMatcher("key1", ImmutableList.of("v1"), true)), - RlsProtoData.ExtraKeys.create(null, null, null), - ImmutableMap.of() - )), - "rls-cbt.googleapis.com", - 1234, - null, - null, - 5000, - ImmutableList.of("valid-target"), - null)); - } - - @Test - public void parseInvalidConfig() { - RouteLookupConfig routeLookupConfig = RouteLookupConfig.newBuilder() - .addGrpcKeybuilders( - GrpcKeyBuilder.newBuilder() - .addNames(Name.newBuilder().setService("service1")) - .addNames(Name.newBuilder().setService("service2")) - .addHeaders( - NameMatcher.newBuilder().setKey("key1").addNames("v1").setRequiredMatch(true))) - .setLookupService("rls-cbt.googleapis.com") - .setLookupServiceTimeout(Durations.fromMillis(1234)) - .setCacheSizeBytes(-5000) // negative - .addValidTargets("valid-target") - .build(); - ConfigOrError configOrError = - RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(routeLookupConfig)); - assertThat(configOrError.errorDetail).contains("cacheSize must be positive"); + ImmutableMap.of( + "key", "key1", "names", ImmutableList.of("v1"), + "requiredMatch", true))))) + .put("lookupService", "rls-cbt.googleapis.com") + .put("lookupServiceTimeout", "1.234s") + .put("cacheSizeBytes", "5000") + .put("validTargets", ImmutableList.of("valid-target")) + .build()); } } From 881747a63df79a7baae252de86447c0997c76f69 Mon Sep 17 00:00:00 2001 From: yifeizhuang Date: Thu, 11 Nov 2021 10:07:14 -0800 Subject: [PATCH 0006/2009] xds: migrate udpa proto to xds directory (#8686) fix https://github.com/grpc/grpc-java/issues/8631: 1. import udpa protos form new git repo `https://github.com/cncf/xds.git` instead of `https://github.com/cncf/udpa.git` 2. use proto from xds directory not udpa directory in `https://github.com/cncf/xds.git`, details was here https://github.com/cncf/xds/issues/2#issuecomment-875838155 3. support both versions of TypeStruct 4. remove v1 orca service in old directory and use the new one v3, and refer to v3 in ORCA related area --- xds/build.gradle | 7 +- .../service/orca/v3}/OpenRcaServiceGrpc.java | 48 ++++---- .../java/io/grpc/xds/ClientXdsClient.java | 49 +++++--- .../OrcaMetricReportingServerInterceptor.java | 2 +- .../main/java/io/grpc/xds/OrcaOobUtil.java | 6 +- .../java/io/grpc/xds/OrcaPerRequestUtil.java | 2 +- .../io/grpc/xds/ClientXdsClientDataTest.java | 109 ++++++++++++++++++ ...aMetricReportingServerInterceptorTest.java | 2 +- .../java/io/grpc/xds/OrcaOobUtilTest.java | 6 +- .../io/grpc/xds/OrcaPerRequestUtilTest.java | 2 +- xds/third_party/{udpa => xds}/LICENSE | 0 xds/third_party/{udpa => xds}/import.sh | 24 ++-- .../main/proto/udpa/annotations/migrate.proto | 6 + .../proto/udpa/annotations/security.proto | 7 +- .../proto/udpa/annotations/sensitive.proto | 20 ++++ .../main/proto/udpa/annotations/status.proto | 6 + .../proto/udpa/annotations/versioning.proto | 6 + .../proto/udpa/type/v1/typed_struct.proto | 47 ++++++++ .../proto/xds/annotations/v3/migrate.proto | 46 ++++++++ .../proto/xds/annotations/v3/security.proto | 30 +++++ .../proto/xds/annotations/v3}/sensitive.proto | 8 +- .../proto/xds/annotations/v3/status.proto | 59 ++++++++++ .../proto/xds/annotations/v3/versioning.proto | 20 ++++ .../main/proto/xds/core/v3/authority.proto | 7 +- .../proto/xds/core/v3/collection_entry.proto | 7 +- .../proto/xds/core/v3/context_params.proto | 7 +- .../proto/xds/core/v3/resource_locator.proto | 7 +- .../proto/xds/core/v3/resource_name.proto | 7 +- .../xds/data/orca/v3}/orca_load_report.proto | 5 +- .../proto/xds/service/orca/v3}/orca.proto | 9 +- .../proto/xds/type/v3}/typed_struct.proto | 5 +- 31 files changed, 476 insertions(+), 90 deletions(-) rename xds/src/generated/main/grpc/com/github/{udpa/udpa/service/orca/v1 => xds/service/orca/v3}/OpenRcaServiceGrpc.java (83%) rename xds/third_party/{udpa => xds}/LICENSE (100%) rename xds/third_party/{udpa => xds}/import.sh (74%) rename xds/third_party/{udpa => xds}/src/main/proto/udpa/annotations/migrate.proto (86%) rename xds/third_party/{udpa => xds}/src/main/proto/udpa/annotations/security.proto (82%) create mode 100644 xds/third_party/xds/src/main/proto/udpa/annotations/sensitive.proto rename xds/third_party/{udpa => xds}/src/main/proto/udpa/annotations/status.proto (82%) rename xds/third_party/{udpa => xds}/src/main/proto/udpa/annotations/versioning.proto (72%) create mode 100644 xds/third_party/xds/src/main/proto/udpa/type/v1/typed_struct.proto create mode 100644 xds/third_party/xds/src/main/proto/xds/annotations/v3/migrate.proto create mode 100644 xds/third_party/xds/src/main/proto/xds/annotations/v3/security.proto rename xds/third_party/{udpa/src/main/proto/udpa/annotations => xds/src/main/proto/xds/annotations/v3}/sensitive.proto (76%) create mode 100644 xds/third_party/xds/src/main/proto/xds/annotations/v3/status.proto create mode 100644 xds/third_party/xds/src/main/proto/xds/annotations/v3/versioning.proto rename xds/third_party/{udpa => xds}/src/main/proto/xds/core/v3/authority.proto (67%) rename xds/third_party/{udpa => xds}/src/main/proto/xds/core/v3/collection_entry.proto (87%) rename xds/third_party/{udpa => xds}/src/main/proto/xds/core/v3/context_params.proto (76%) rename xds/third_party/{udpa => xds}/src/main/proto/xds/core/v3/resource_locator.proto (95%) rename xds/third_party/{udpa => xds}/src/main/proto/xds/core/v3/resource_name.proto (86%) rename xds/third_party/{udpa/src/main/proto/udpa/data/orca/v1 => xds/src/main/proto/xds/data/orca/v3}/orca_load_report.proto (90%) rename xds/third_party/{udpa/src/main/proto/udpa/service/orca/v1 => xds/src/main/proto/xds/service/orca/v3}/orca.proto (81%) rename xds/third_party/{udpa/src/main/proto/udpa/type/v1 => xds/src/main/proto/xds/type/v3}/typed_struct.proto (94%) diff --git a/xds/build.gradle b/xds/build.gradle index 3af4f75d62c..16b1c877906 100644 --- a/xds/build.gradle +++ b/xds/build.gradle @@ -71,7 +71,7 @@ sourceSets { proto { srcDir 'third_party/envoy/src/main/proto' srcDir 'third_party/protoc-gen-validate/src/main/proto' - srcDir 'third_party/udpa/src/main/proto' + srcDir 'third_party/xds/src/main/proto' srcDir 'third_party/googleapis/src/main/proto' srcDir 'third_party/istio/src/main/proto' } @@ -92,6 +92,7 @@ jar { javadoc { // Exclusions here should generally also be relocated exclude 'com/github/udpa/**' + exclude 'com/github/xds/**' exclude 'com/google/security/**' exclude 'io/envoyproxy/**' // Need to clean up the class structure to reduce how much is exposed @@ -115,6 +116,7 @@ shadowJar { } // Relocated packages commonly need exclusions in jacocoTestReport and javadoc relocate 'com.github.udpa', "${prefixName}.shaded.com.github.udpa" + relocate 'com.github.xds', "${prefixName}.shaded.com.github.xds" relocate 'com.google.api.expr', "${prefixName}.shaded.com.google.api.expr" relocate 'com.google.security', "${prefixName}.shaded.com.google.security" // TODO: missing java_package option in .proto @@ -124,6 +126,7 @@ shadowJar { relocate 'io.netty', 'io.grpc.netty.shaded.io.netty' // TODO: missing java_package option in .proto relocate 'udpa.annotations', "${prefixName}.shaded.udpa.annotations" + relocate 'xds.annotations', "${prefixName}.shaded.xds.annotations" exclude "**/*.proto" } @@ -159,11 +162,13 @@ jacocoTestReport { fileTree(dir: it, exclude: [ // Exclusions here should generally also be relocated '**/com/github/udpa/**', + '**/com/github/xds/**', '**/com/google/api/expr/**', '**/com/google/security/**', '**/envoy/annotations/**', '**/io/envoyproxy/**', '**/udpa/annotations/**', + '**/xds/annotations/**', ]) } } diff --git a/xds/src/generated/main/grpc/com/github/udpa/udpa/service/orca/v1/OpenRcaServiceGrpc.java b/xds/src/generated/main/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java similarity index 83% rename from xds/src/generated/main/grpc/com/github/udpa/udpa/service/orca/v1/OpenRcaServiceGrpc.java rename to xds/src/generated/main/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java index 78383dba2d3..52ec6898808 100644 --- a/xds/src/generated/main/grpc/com/github/udpa/udpa/service/orca/v1/OpenRcaServiceGrpc.java +++ b/xds/src/generated/main/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java @@ -1,4 +1,4 @@ -package com.github.udpa.udpa.service.orca.v1; +package com.github.xds.service.orca.v3; import static io.grpc.MethodDescriptor.generateFullMethodName; @@ -16,38 +16,38 @@ */ @javax.annotation.Generated( value = "by gRPC proto compiler", - comments = "Source: udpa/service/orca/v1/orca.proto") + comments = "Source: xds/service/orca/v3/orca.proto") @io.grpc.stub.annotations.GrpcGenerated public final class OpenRcaServiceGrpc { private OpenRcaServiceGrpc() {} - public static final String SERVICE_NAME = "udpa.service.orca.v1.OpenRcaService"; + public static final String SERVICE_NAME = "xds.service.orca.v3.OpenRcaService"; // Static method descriptors that strictly reflect the proto. - private static volatile io.grpc.MethodDescriptor getStreamCoreMetricsMethod; + private static volatile io.grpc.MethodDescriptor getStreamCoreMetricsMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "StreamCoreMetrics", - requestType = com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest.class, - responseType = com.github.udpa.udpa.data.orca.v1.OrcaLoadReport.class, + requestType = com.github.xds.service.orca.v3.OrcaLoadReportRequest.class, + responseType = com.github.xds.data.orca.v3.OrcaLoadReport.class, methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - public static io.grpc.MethodDescriptor getStreamCoreMetricsMethod() { - io.grpc.MethodDescriptor getStreamCoreMetricsMethod; + public static io.grpc.MethodDescriptor getStreamCoreMetricsMethod() { + io.grpc.MethodDescriptor getStreamCoreMetricsMethod; if ((getStreamCoreMetricsMethod = OpenRcaServiceGrpc.getStreamCoreMetricsMethod) == null) { synchronized (OpenRcaServiceGrpc.class) { if ((getStreamCoreMetricsMethod = OpenRcaServiceGrpc.getStreamCoreMetricsMethod) == null) { OpenRcaServiceGrpc.getStreamCoreMetricsMethod = getStreamCoreMetricsMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "StreamCoreMetrics")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest.getDefaultInstance())) + com.github.xds.service.orca.v3.OrcaLoadReportRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - com.github.udpa.udpa.data.orca.v1.OrcaLoadReport.getDefaultInstance())) + com.github.xds.data.orca.v3.OrcaLoadReport.getDefaultInstance())) .setSchemaDescriptor(new OpenRcaServiceMethodDescriptorSupplier("StreamCoreMetrics")) .build(); } @@ -116,8 +116,8 @@ public static abstract class OpenRcaServiceImplBase implements io.grpc.BindableS /** */ - public void streamCoreMetrics(com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void streamCoreMetrics(com.github.xds.service.orca.v3.OrcaLoadReportRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getStreamCoreMetricsMethod(), responseObserver); } @@ -127,8 +127,8 @@ public void streamCoreMetrics(com.github.udpa.udpa.service.orca.v1.OrcaLoadRepor getStreamCoreMetricsMethod(), io.grpc.stub.ServerCalls.asyncServerStreamingCall( new MethodHandlers< - com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest, - com.github.udpa.udpa.data.orca.v1.OrcaLoadReport>( + com.github.xds.service.orca.v3.OrcaLoadReportRequest, + com.github.xds.data.orca.v3.OrcaLoadReport>( this, METHODID_STREAM_CORE_METRICS))) .build(); } @@ -160,8 +160,8 @@ protected OpenRcaServiceStub build( /** */ - public void streamCoreMetrics(com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void streamCoreMetrics(com.github.xds.service.orca.v3.OrcaLoadReportRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncServerStreamingCall( getChannel().newCall(getStreamCoreMetricsMethod(), getCallOptions()), request, responseObserver); } @@ -193,8 +193,8 @@ protected OpenRcaServiceBlockingStub build( /** */ - public java.util.Iterator streamCoreMetrics( - com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest request) { + public java.util.Iterator streamCoreMetrics( + com.github.xds.service.orca.v3.OrcaLoadReportRequest request) { return io.grpc.stub.ClientCalls.blockingServerStreamingCall( getChannel(), getStreamCoreMetricsMethod(), getCallOptions(), request); } @@ -245,8 +245,8 @@ private static final class MethodHandlers implements public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { switch (methodId) { case METHODID_STREAM_CORE_METRICS: - serviceImpl.streamCoreMetrics((com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.streamCoreMetrics((com.github.xds.service.orca.v3.OrcaLoadReportRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; default: throw new AssertionError(); @@ -270,7 +270,7 @@ private static abstract class OpenRcaServiceBaseDescriptorSupplier @java.lang.Override public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { - return com.github.udpa.udpa.service.orca.v1.OrcaProto.getDescriptor(); + return com.github.xds.service.orca.v3.OrcaProto.getDescriptor(); } @java.lang.Override diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index 4d45dc21d9e..0a11ad47288 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -162,8 +162,10 @@ final class ClientXdsClient extends XdsClient implements XdsResponseHandler, Res "type.googleapis.com/envoy.config.cluster.aggregate.v2alpha.ClusterConfig"; private static final String TYPE_URL_CLUSTER_CONFIG = "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig"; - private static final String TYPE_URL_TYPED_STRUCT = + private static final String TYPE_URL_TYPED_STRUCT_UDPA = "type.googleapis.com/udpa.type.v1.TypedStruct"; + private static final String TYPE_URL_TYPED_STRUCT = + "type.googleapis.com/xds.type.v3.TypedStruct"; private static final String TYPE_URL_FILTER_CONFIG = "type.googleapis.com/envoy.config.route.v3.FilterConfig"; // TODO(zdapeng): need to discuss how to handle unsupported values. @@ -908,16 +910,21 @@ static StructOrError parseHttpFilter( } Message rawConfig = httpFilter.getTypedConfig(); String typeUrl = httpFilter.getTypedConfig().getTypeUrl(); - if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) { - TypedStruct typedStruct; - try { - typedStruct = httpFilter.getTypedConfig().unpack(TypedStruct.class); - } catch (InvalidProtocolBufferException e) { - return StructOrError.fromError( - "HttpFilter [" + filterName + "] contains invalid proto: " + e); + + try { + if (typeUrl.equals(TYPE_URL_TYPED_STRUCT_UDPA)) { + TypedStruct typedStruct = httpFilter.getTypedConfig().unpack(TypedStruct.class); + typeUrl = typedStruct.getTypeUrl(); + rawConfig = typedStruct.getValue(); + } else if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) { + com.github.xds.type.v3.TypedStruct newTypedStruct = + httpFilter.getTypedConfig().unpack(com.github.xds.type.v3.TypedStruct.class); + typeUrl = newTypedStruct.getTypeUrl(); + rawConfig = newTypedStruct.getValue(); } - typeUrl = typedStruct.getTypeUrl(); - rawConfig = typedStruct.getValue(); + } catch (InvalidProtocolBufferException e) { + return StructOrError.fromError( + "HttpFilter [" + filterName + "] contains invalid proto: " + e); } Filter filter = filterRegistry.get(typeUrl); if ((isForClient && !(filter instanceof ClientInterceptorBuilder)) @@ -991,16 +998,20 @@ static StructOrError> parseOverrideFilterConfigs( typeUrl = anyConfig.getTypeUrl(); } Message rawConfig = anyConfig; - if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) { - TypedStruct typedStruct; - try { - typedStruct = anyConfig.unpack(TypedStruct.class); - } catch (InvalidProtocolBufferException e) { - return StructOrError.fromError( - "FilterConfig [" + name + "] contains invalid proto: " + e); + try { + if (typeUrl.equals(TYPE_URL_TYPED_STRUCT_UDPA)) { + TypedStruct typedStruct = anyConfig.unpack(TypedStruct.class); + typeUrl = typedStruct.getTypeUrl(); + rawConfig = typedStruct.getValue(); + } else if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) { + com.github.xds.type.v3.TypedStruct newTypedStruct = + anyConfig.unpack(com.github.xds.type.v3.TypedStruct.class); + typeUrl = newTypedStruct.getTypeUrl(); + rawConfig = newTypedStruct.getValue(); } - typeUrl = typedStruct.getTypeUrl(); - rawConfig = typedStruct.getValue(); + } catch (InvalidProtocolBufferException e) { + return StructOrError.fromError( + "FilterConfig [" + name + "] contains invalid proto: " + e); } Filter filter = filterRegistry.get(typeUrl); if (filter == null) { diff --git a/xds/src/main/java/io/grpc/xds/OrcaMetricReportingServerInterceptor.java b/xds/src/main/java/io/grpc/xds/OrcaMetricReportingServerInterceptor.java index 8a503bd35f9..9c79ed11bc3 100644 --- a/xds/src/main/java/io/grpc/xds/OrcaMetricReportingServerInterceptor.java +++ b/xds/src/main/java/io/grpc/xds/OrcaMetricReportingServerInterceptor.java @@ -16,7 +16,7 @@ package io.grpc.xds; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; +import com.github.xds.data.orca.v3.OrcaLoadReport; import com.google.common.annotations.VisibleForTesting; import io.grpc.Context; import io.grpc.Contexts; diff --git a/xds/src/main/java/io/grpc/xds/OrcaOobUtil.java b/xds/src/main/java/io/grpc/xds/OrcaOobUtil.java index 1b5acd8c080..8970a68bf65 100644 --- a/xds/src/main/java/io/grpc/xds/OrcaOobUtil.java +++ b/xds/src/main/java/io/grpc/xds/OrcaOobUtil.java @@ -22,9 +22,9 @@ import static io.grpc.ConnectivityState.READY; import static io.grpc.ConnectivityState.SHUTDOWN; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; -import com.github.udpa.udpa.service.orca.v1.OpenRcaServiceGrpc; -import com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest; +import com.github.xds.data.orca.v3.OrcaLoadReport; +import com.github.xds.service.orca.v3.OpenRcaServiceGrpc; +import com.github.xds.service.orca.v3.OrcaLoadReportRequest; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; diff --git a/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java b/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java index 156d53f638e..4b4cff92064 100644 --- a/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java +++ b/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; +import com.github.xds.data.orca.v3.OrcaLoadReport; import com.google.common.annotations.VisibleForTesting; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java index cb7b937bb5f..e14d6db45ac 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java @@ -18,14 +18,18 @@ import static com.google.common.truth.Truth.assertThat; +import com.github.xds.type.v3.TypedStruct; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; import com.google.protobuf.StringValue; +import com.google.protobuf.Struct; import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt64Value; +import com.google.protobuf.Value; import com.google.protobuf.util.Durations; import com.google.re2j.Pattern; import io.envoyproxy.envoy.config.cluster.v3.Cluster; @@ -94,7 +98,9 @@ import io.envoyproxy.envoy.type.v3.FractionalPercent; import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType; import io.envoyproxy.envoy.type.v3.Int64Range; +import io.grpc.ClientInterceptor; import io.grpc.InsecureChannelCredentials; +import io.grpc.LoadBalancer; import io.grpc.Status.Code; import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClientXdsClient.ResourceInvalidException; @@ -116,7 +122,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -879,6 +887,107 @@ public void parseHttpFilter_unsupportedButOptional() { assertThat(ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, true)).isNull(); } + private static class SimpleFilterConfig implements FilterConfig { + private final Message message; + + public SimpleFilterConfig(Message rawProtoMessage) { + message = rawProtoMessage; + } + + public Message getConfig() { + return message; + } + + @Override + public String typeUrl() { + return null; + } + } + + private static class TestFilter implements io.grpc.xds.Filter, + io.grpc.xds.Filter.ClientInterceptorBuilder { + @Override + public String[] typeUrls() { + return new String[]{"test-url"}; + } + + @Override + public ConfigOrError parseFilterConfig(Message rawProtoMessage) { + return ConfigOrError.fromConfig(new SimpleFilterConfig(rawProtoMessage)); + } + + @Override + public ConfigOrError parseFilterConfigOverride( + Message rawProtoMessage) { + return ConfigOrError.fromConfig(new SimpleFilterConfig(rawProtoMessage)); + } + + @Nullable + @Override + public ClientInterceptor buildClientInterceptor(FilterConfig config, + @Nullable FilterConfig overrideConfig, + LoadBalancer.PickSubchannelArgs args, + ScheduledExecutorService scheduler) { + return null; + } + } + + @Test + public void parseHttpFilter_typedStructMigration() { + filterRegistry.register(new TestFilter()); + Struct rawStruct = Struct.newBuilder() + .putFields("name", Value.newBuilder().setStringValue("default").build()) + .build(); + HttpFilter httpFilter = HttpFilter.newBuilder() + .setIsOptional(true) + .setTypedConfig(Any.pack( + com.github.udpa.udpa.type.v1.TypedStruct.newBuilder() + .setTypeUrl("test-url") + .setValue(rawStruct) + .build())).build(); + FilterConfig config = ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, + true).getStruct(); + assertThat(((SimpleFilterConfig)config).getConfig()).isEqualTo(rawStruct); + + HttpFilter httpFilterNewTypeStruct = HttpFilter.newBuilder() + .setIsOptional(true) + .setTypedConfig(Any.pack( + TypedStruct.newBuilder() + .setTypeUrl("test-url") + .setValue(rawStruct) + .build())).build(); + config = ClientXdsClient.parseHttpFilter(httpFilterNewTypeStruct, filterRegistry, + true).getStruct(); + assertThat(((SimpleFilterConfig)config).getConfig()).isEqualTo(rawStruct); + } + + @Test + public void parseOverrideHttpFilter_typedStructMigration() { + filterRegistry.register(new TestFilter()); + Struct rawStruct0 = Struct.newBuilder() + .putFields("name", Value.newBuilder().setStringValue("default0").build()) + .build(); + Struct rawStruct1 = Struct.newBuilder() + .putFields("name", Value.newBuilder().setStringValue("default1").build()) + .build(); + Map rawFilterMap = ImmutableMap.of( + "struct-0", Any.pack( + com.github.udpa.udpa.type.v1.TypedStruct.newBuilder() + .setTypeUrl("test-url") + .setValue(rawStruct0) + .build()), + "struct-1", Any.pack( + TypedStruct.newBuilder() + .setTypeUrl("test-url") + .setValue(rawStruct1) + .build()) + ); + Map map = ClientXdsClient.parseOverrideFilterConfigs(rawFilterMap, + filterRegistry).getStruct(); + assertThat(((SimpleFilterConfig)map.get("struct-0")).getConfig()).isEqualTo(rawStruct0); + assertThat(((SimpleFilterConfig)map.get("struct-1")).getConfig()).isEqualTo(rawStruct1); + } + @Test public void parseHttpFilter_unsupportedAndRequired() { HttpFilter httpFilter = HttpFilter.newBuilder() diff --git a/xds/src/test/java/io/grpc/xds/OrcaMetricReportingServerInterceptorTest.java b/xds/src/test/java/io/grpc/xds/OrcaMetricReportingServerInterceptorTest.java index b59871f5437..4a2074b91d8 100644 --- a/xds/src/test/java/io/grpc/xds/OrcaMetricReportingServerInterceptorTest.java +++ b/xds/src/test/java/io/grpc/xds/OrcaMetricReportingServerInterceptorTest.java @@ -18,7 +18,7 @@ import static com.google.common.truth.Truth.assertThat; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; +import com.github.xds.data.orca.v3.OrcaLoadReport; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientCall; diff --git a/xds/src/test/java/io/grpc/xds/OrcaOobUtilTest.java b/xds/src/test/java/io/grpc/xds/OrcaOobUtilTest.java index b3cf80ee617..5f5bc5a69aa 100644 --- a/xds/src/test/java/io/grpc/xds/OrcaOobUtilTest.java +++ b/xds/src/test/java/io/grpc/xds/OrcaOobUtilTest.java @@ -34,9 +34,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; -import com.github.udpa.udpa.service.orca.v1.OpenRcaServiceGrpc; -import com.github.udpa.udpa.service.orca.v1.OrcaLoadReportRequest; +import com.github.xds.data.orca.v3.OrcaLoadReport; +import com.github.xds.service.orca.v3.OpenRcaServiceGrpc; +import com.github.xds.service.orca.v3.OrcaLoadReportRequest; import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.util.Durations; import io.grpc.Attributes; diff --git a/xds/src/test/java/io/grpc/xds/OrcaPerRequestUtilTest.java b/xds/src/test/java/io/grpc/xds/OrcaPerRequestUtilTest.java index bee68c9e634..a6e7c6aca20 100644 --- a/xds/src/test/java/io/grpc/xds/OrcaPerRequestUtilTest.java +++ b/xds/src/test/java/io/grpc/xds/OrcaPerRequestUtilTest.java @@ -27,7 +27,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import com.github.udpa.udpa.data.orca.v1.OrcaLoadReport; +import com.github.xds.data.orca.v3.OrcaLoadReport; import io.grpc.ClientStreamTracer; import io.grpc.Metadata; import io.grpc.xds.OrcaPerRequestUtil.OrcaPerRequestReportListener; diff --git a/xds/third_party/udpa/LICENSE b/xds/third_party/xds/LICENSE similarity index 100% rename from xds/third_party/udpa/LICENSE rename to xds/third_party/xds/LICENSE diff --git a/xds/third_party/udpa/import.sh b/xds/third_party/xds/import.sh similarity index 74% rename from xds/third_party/udpa/import.sh rename to xds/third_party/xds/import.sh index b96e4ea6da6..36889a52bba 100755 --- a/xds/third_party/udpa/import.sh +++ b/xds/third_party/xds/import.sh @@ -18,21 +18,29 @@ set -e BRANCH=main # import VERSION from one of the google internal CLs -VERSION=5459f2c994033b0afed7e4a70ac7e90c90c1ffee -GIT_REPO="https://github.com/cncf/udpa.git" -GIT_BASE_DIR=udpa -SOURCE_PROTO_BASE_DIR=udpa +VERSION=cb28da3451f158a947dfc45090fe92b07b243bc1 +GIT_REPO="https://github.com/cncf/xds.git" +GIT_BASE_DIR=xds +SOURCE_PROTO_BASE_DIR=xds TARGET_PROTO_BASE_DIR=src/main/proto # Sorted alphabetically. FILES=( udpa/annotations/migrate.proto +xds/annotations/v3/migrate.proto udpa/annotations/security.proto +xds/annotations/v3/security.proto +udpa/annotations/security.proto +xds/annotations/v3/security.proto udpa/annotations/sensitive.proto +xds/annotations/v3/sensitive.proto udpa/annotations/status.proto +xds/annotations/v3/status.proto udpa/annotations/versioning.proto -udpa/data/orca/v1/orca_load_report.proto -udpa/service/orca/v1/orca.proto +xds/annotations/v3/versioning.proto +xds/data/orca/v3/orca_load_report.proto +xds/service/orca/v3/orca.proto udpa/type/v1/typed_struct.proto +xds/type/v3/typed_struct.proto xds/core/v3/authority.proto xds/core/v3/collection_entry.proto xds/core/v3/context_params.proto @@ -40,9 +48,9 @@ xds/core/v3/resource_locator.proto xds/core/v3/resource_name.proto ) -pushd `git rev-parse --show-toplevel`/xds/third_party/udpa +pushd `git rev-parse --show-toplevel`/xds/third_party/xds -# clone the udpa github repo in a tmp directory +# clone the xds github repo in a tmp directory tmpdir="$(mktemp -d)" trap "rm -rf $tmpdir" EXIT diff --git a/xds/third_party/udpa/src/main/proto/udpa/annotations/migrate.proto b/xds/third_party/xds/src/main/proto/udpa/annotations/migrate.proto similarity index 86% rename from xds/third_party/udpa/src/main/proto/udpa/annotations/migrate.proto rename to xds/third_party/xds/src/main/proto/udpa/annotations/migrate.proto index 1c42a6404dc..5289cb8a742 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/annotations/migrate.proto +++ b/xds/third_party/xds/src/main/proto/udpa/annotations/migrate.proto @@ -1,9 +1,15 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + syntax = "proto3"; package udpa.annotations; import "google/protobuf/descriptor.proto"; +option go_package = "github.com/cncf/xds/go/annotations"; + // Magic number in this file derived from top 28bit of SHA256 digest of // "udpa.annotation.migrate". diff --git a/xds/third_party/udpa/src/main/proto/udpa/annotations/security.proto b/xds/third_party/xds/src/main/proto/udpa/annotations/security.proto similarity index 82% rename from xds/third_party/udpa/src/main/proto/udpa/annotations/security.proto rename to xds/third_party/xds/src/main/proto/udpa/annotations/security.proto index 7191fe30c82..52801d30d1e 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/annotations/security.proto +++ b/xds/third_party/xds/src/main/proto/udpa/annotations/security.proto @@ -1,13 +1,16 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + syntax = "proto3"; package udpa.annotations; import "udpa/annotations/status.proto"; -import "google/protobuf/any.proto"; import "google/protobuf/descriptor.proto"; -import "validate/validate.proto"; +option go_package = "github.com/cncf/xds/go/annotations"; // All annotations in this file are experimental and subject to change. Their // only consumer today is the Envoy APIs and SecuritAnnotationValidator protoc diff --git a/xds/third_party/xds/src/main/proto/udpa/annotations/sensitive.proto b/xds/third_party/xds/src/main/proto/udpa/annotations/sensitive.proto new file mode 100644 index 00000000000..ab822fb4884 --- /dev/null +++ b/xds/third_party/xds/src/main/proto/udpa/annotations/sensitive.proto @@ -0,0 +1,20 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + +syntax = "proto3"; + +package udpa.annotations; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/cncf/xds/go/annotations"; + +extend google.protobuf.FieldOptions { + // Magic number is the 28 most significant bits in the sha256sum of "udpa.annotations.sensitive". + // When set to true, `sensitive` indicates that this field contains sensitive data, such as + // personally identifiable information, passwords, or private keys, and should be redacted for + // display by tools aware of this annotation. Note that that this has no effect on standard + // Protobuf functions such as `TextFormat::PrintToString`. + bool sensitive = 76569463; +} diff --git a/xds/third_party/udpa/src/main/proto/udpa/annotations/status.proto b/xds/third_party/xds/src/main/proto/udpa/annotations/status.proto similarity index 82% rename from xds/third_party/udpa/src/main/proto/udpa/annotations/status.proto rename to xds/third_party/xds/src/main/proto/udpa/annotations/status.proto index 9832ffd3a2f..76cfd4dcfef 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/annotations/status.proto +++ b/xds/third_party/xds/src/main/proto/udpa/annotations/status.proto @@ -1,9 +1,15 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + syntax = "proto3"; package udpa.annotations; import "google/protobuf/descriptor.proto"; +option go_package = "github.com/cncf/xds/go/annotations"; + // Magic number in this file derived from top 28bit of SHA256 digest of // "udpa.annotation.status". extend google.protobuf.FileOptions { diff --git a/xds/third_party/udpa/src/main/proto/udpa/annotations/versioning.proto b/xds/third_party/xds/src/main/proto/udpa/annotations/versioning.proto similarity index 72% rename from xds/third_party/udpa/src/main/proto/udpa/annotations/versioning.proto rename to xds/third_party/xds/src/main/proto/udpa/annotations/versioning.proto index 16f6dc30cad..dcb7c85fd4f 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/annotations/versioning.proto +++ b/xds/third_party/xds/src/main/proto/udpa/annotations/versioning.proto @@ -1,9 +1,15 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + syntax = "proto3"; package udpa.annotations; import "google/protobuf/descriptor.proto"; +option go_package = "github.com/cncf/xds/go/annotations"; + extend google.protobuf.MessageOptions { // Magic number derived from 0x78 ('x') 0x44 ('D') 0x53 ('S') VersioningAnnotation versioning = 7881811; diff --git a/xds/third_party/xds/src/main/proto/udpa/type/v1/typed_struct.proto b/xds/third_party/xds/src/main/proto/udpa/type/v1/typed_struct.proto new file mode 100644 index 00000000000..f96625d926f --- /dev/null +++ b/xds/third_party/xds/src/main/proto/udpa/type/v1/typed_struct.proto @@ -0,0 +1,47 @@ +// THIS FILE IS DEPRECATED +// Users should instead use the corresponding proto in the xds tree. +// No new changes will be accepted here. + +syntax = "proto3"; + +package udpa.type.v1; + +option java_outer_classname = "TypedStructProto"; +option java_multiple_files = true; +option java_package = "com.github.udpa.udpa.type.v1"; +option go_package = "github.com/cncf/xds/go/udpa/type/v1"; + +import "validate/validate.proto"; +import "google/protobuf/struct.proto"; + +// A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that +// describes the type of the serialized message. This is very similar to google.protobuf.Any, +// instead of having protocol buffer binary, this employs google.protobuf.Struct as value. +// +// This message is intended to be embedded inside Any, so it shouldn't be directly referred +// from other UDPA messages. +// +// When packing an opaque extension config, packing the expected type into Any is preferred +// wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor +// is not available, for example if: +// - A control plane sends opaque message that is originally from external source in human readable +// format such as JSON or YAML. +// - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot +// serialize the message in protocol buffer binary format. +// - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension +// uses. This has to be indicated in the DPLB capability negotiation. +// +// When a DPLB receives a TypedStruct in Any, it should: +// - Check if the type_url of the TypedStruct matches the type the extension expects. +// - Convert value to the type described in type_url and perform validation. +// TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link +// protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). +message TypedStruct { + // A URL that uniquely identifies the type of the serialize protocol buffer message. + // This has same semantics and format described in google.protobuf.Any: + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + string type_url = 1; + + // A JSON representation of the above specified type. + google.protobuf.Struct value = 2; +} diff --git a/xds/third_party/xds/src/main/proto/xds/annotations/v3/migrate.proto b/xds/third_party/xds/src/main/proto/xds/annotations/v3/migrate.proto new file mode 100644 index 00000000000..13859274c85 --- /dev/null +++ b/xds/third_party/xds/src/main/proto/xds/annotations/v3/migrate.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +package xds.annotations.v3; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/cncf/xds/go/xds/annotations/v3"; + +// Magic number in this file derived from top 28bit of SHA256 digest of +// "xds.annotation.v3.migrate". +extend google.protobuf.MessageOptions { + MigrateAnnotation message_migrate = 112948430; +} +extend google.protobuf.FieldOptions { + FieldMigrateAnnotation field_migrate = 112948430; +} +extend google.protobuf.EnumOptions { + MigrateAnnotation enum_migrate = 112948430; +} +extend google.protobuf.EnumValueOptions { + MigrateAnnotation enum_value_migrate = 112948430; +} +extend google.protobuf.FileOptions { + FileMigrateAnnotation file_migrate = 112948430; +} + +message MigrateAnnotation { + // Rename the message/enum/enum value in next version. + string rename = 1; +} + +message FieldMigrateAnnotation { + // Rename the field in next version. + string rename = 1; + + // Add the field to a named oneof in next version. If this already exists, the + // field will join its siblings under the oneof, otherwise a new oneof will be + // created with the given name. + string oneof_promotion = 2; +} + +message FileMigrateAnnotation { + // Move all types in the file to another package, this implies changing proto + // file path. + string move_to_package = 2; +} diff --git a/xds/third_party/xds/src/main/proto/xds/annotations/v3/security.proto b/xds/third_party/xds/src/main/proto/xds/annotations/v3/security.proto new file mode 100644 index 00000000000..f1f9f40da0a --- /dev/null +++ b/xds/third_party/xds/src/main/proto/xds/annotations/v3/security.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package xds.annotations.v3; + +import "xds/annotations/v3/status.proto"; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/cncf/xds/go/xds/annotations/v3"; + +// All annotations in this file are experimental and subject to change. Their +// only consumer today is the Envoy APIs and SecuritAnnotationValidator protoc +// plugin in this repository. +option (xds.annotations.v3.file_status).work_in_progress = true; + +extend google.protobuf.FieldOptions { + // Magic number is the 28 most significant bits in the sha256sum of + // "xds.annotations.v3.security". + FieldSecurityAnnotation security = 99044135; +} + +// These annotations indicate metadata for the purpose of understanding the +// security significance of fields. +message FieldSecurityAnnotation { + // Field should be set in the presence of untrusted downstreams. + bool configure_for_untrusted_downstream = 1; + + // Field should be set in the presence of untrusted upstreams. + bool configure_for_untrusted_upstream = 2; +} diff --git a/xds/third_party/udpa/src/main/proto/udpa/annotations/sensitive.proto b/xds/third_party/xds/src/main/proto/xds/annotations/v3/sensitive.proto similarity index 76% rename from xds/third_party/udpa/src/main/proto/udpa/annotations/sensitive.proto rename to xds/third_party/xds/src/main/proto/xds/annotations/v3/sensitive.proto index 8dc921f24b5..e2cc0b792ef 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/annotations/sensitive.proto +++ b/xds/third_party/xds/src/main/proto/xds/annotations/v3/sensitive.proto @@ -1,14 +1,16 @@ syntax = "proto3"; -package udpa.annotations; +package xds.annotations.v3; import "google/protobuf/descriptor.proto"; +option go_package = "github.com/cncf/xds/go/xds/annotations/v3"; + extend google.protobuf.FieldOptions { - // Magic number is the 28 most significant bits in the sha256sum of "udpa.annotations.sensitive". + // Magic number is the 28 most significant bits in the sha256sum of "xds.annotations.v3.sensitive". // When set to true, `sensitive` indicates that this field contains sensitive data, such as // personally identifiable information, passwords, or private keys, and should be redacted for // display by tools aware of this annotation. Note that that this has no effect on standard // Protobuf functions such as `TextFormat::PrintToString`. - bool sensitive = 76569463; + bool sensitive = 61008053; } diff --git a/xds/third_party/xds/src/main/proto/xds/annotations/v3/status.proto b/xds/third_party/xds/src/main/proto/xds/annotations/v3/status.proto new file mode 100644 index 00000000000..367e784f671 --- /dev/null +++ b/xds/third_party/xds/src/main/proto/xds/annotations/v3/status.proto @@ -0,0 +1,59 @@ +syntax = "proto3"; + +package xds.annotations.v3; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/cncf/xds/go/xds/annotations/v3"; + +// Magic number in this file derived from top 28bit of SHA256 digest of +// "xds.annotations.v3.status". +extend google.protobuf.FileOptions { + FileStatusAnnotation file_status = 226829418; +} + +extend google.protobuf.MessageOptions { + MessageStatusAnnotation message_status = 226829418; +} + +extend google.protobuf.FieldOptions { + FieldStatusAnnotation field_status = 226829418; +} + +message FileStatusAnnotation { + // The entity is work-in-progress and subject to breaking changes. + bool work_in_progress = 1; +} + +message MessageStatusAnnotation { + // The entity is work-in-progress and subject to breaking changes. + bool work_in_progress = 1; +} + +message FieldStatusAnnotation { + // The entity is work-in-progress and subject to breaking changes. + bool work_in_progress = 1; +} + +enum PackageVersionStatus { + // Unknown package version status. + UNKNOWN = 0; + + // This version of the package is frozen. + FROZEN = 1; + + // This version of the package is the active development version. + ACTIVE = 2; + + // This version of the package is the candidate for the next major version. It + // is typically machine generated from the active development version. + NEXT_MAJOR_VERSION_CANDIDATE = 3; +} + +message StatusAnnotation { + // The entity is work-in-progress and subject to breaking changes. + bool work_in_progress = 1; + + // The entity belongs to a package with the given version status. + PackageVersionStatus package_version_status = 2; +} diff --git a/xds/third_party/xds/src/main/proto/xds/annotations/v3/versioning.proto b/xds/third_party/xds/src/main/proto/xds/annotations/v3/versioning.proto new file mode 100644 index 00000000000..b6440f1949b --- /dev/null +++ b/xds/third_party/xds/src/main/proto/xds/annotations/v3/versioning.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package xds.annotations.v3; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/cncf/xds/go/xds/annotations/v3"; + +extend google.protobuf.MessageOptions { + // Magic number is the 28 most significant bits in the sha256sum of + // "xds.annotations.v3.versioning". + VersioningAnnotation versioning = 92389011; +} + +message VersioningAnnotation { + // Track the previous message type. E.g. this message might be + // xds.foo.v3alpha.Foo and it was previously xds.bar.v2.Bar. This + // information is consumed by UDPA via proto descriptors. + string previous_message_type = 1; +} diff --git a/xds/third_party/udpa/src/main/proto/xds/core/v3/authority.proto b/xds/third_party/xds/src/main/proto/xds/core/v3/authority.proto similarity index 67% rename from xds/third_party/udpa/src/main/proto/xds/core/v3/authority.proto rename to xds/third_party/xds/src/main/proto/xds/core/v3/authority.proto index 49daf4b8cb6..d666c38eafa 100644 --- a/xds/third_party/udpa/src/main/proto/xds/core/v3/authority.proto +++ b/xds/third_party/xds/src/main/proto/xds/core/v3/authority.proto @@ -2,15 +2,16 @@ syntax = "proto3"; package xds.core.v3; -import "udpa/annotations/status.proto"; +import "xds/annotations/v3/status.proto"; import "validate/validate.proto"; option java_outer_classname = "AuthorityProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.xds.core.v3"; +option java_package = "com.github.xds.core.v3"; +option go_package = "github.com/cncf/xds/go/xds/core/v3"; -option (udpa.annotations.file_status).work_in_progress = true; +option (xds.annotations.v3.file_status).work_in_progress = true; // xDS authority information. message Authority { diff --git a/xds/third_party/udpa/src/main/proto/xds/core/v3/collection_entry.proto b/xds/third_party/xds/src/main/proto/xds/core/v3/collection_entry.proto similarity index 87% rename from xds/third_party/udpa/src/main/proto/xds/core/v3/collection_entry.proto rename to xds/third_party/xds/src/main/proto/xds/core/v3/collection_entry.proto index 4ece240ca3e..043a9c421f2 100644 --- a/xds/third_party/udpa/src/main/proto/xds/core/v3/collection_entry.proto +++ b/xds/third_party/xds/src/main/proto/xds/core/v3/collection_entry.proto @@ -4,16 +4,17 @@ package xds.core.v3; import "google/protobuf/any.proto"; -import "udpa/annotations/status.proto"; +import "xds/annotations/v3/status.proto"; import "xds/core/v3/resource_locator.proto"; import "validate/validate.proto"; option java_outer_classname = "CollectionEntryProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.xds.core.v3"; +option java_package = "com.github.xds.core.v3"; +option go_package = "github.com/cncf/xds/go/xds/core/v3"; -option (udpa.annotations.file_status).work_in_progress = true; +option (xds.annotations.v3.file_status).work_in_progress = true; // xDS collection resource wrapper. This encapsulates a xDS resource when // appearing inside a list collection resource. List collection resources are diff --git a/xds/third_party/udpa/src/main/proto/xds/core/v3/context_params.proto b/xds/third_party/xds/src/main/proto/xds/core/v3/context_params.proto similarity index 76% rename from xds/third_party/udpa/src/main/proto/xds/core/v3/context_params.proto rename to xds/third_party/xds/src/main/proto/xds/core/v3/context_params.proto index 8f27c1ca7e5..2a0c079e5d9 100644 --- a/xds/third_party/udpa/src/main/proto/xds/core/v3/context_params.proto +++ b/xds/third_party/xds/src/main/proto/xds/core/v3/context_params.proto @@ -2,13 +2,14 @@ syntax = "proto3"; package xds.core.v3; -import "udpa/annotations/status.proto"; +import "xds/annotations/v3/status.proto"; option java_outer_classname = "ContextParamsProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.xds.core.v3"; +option java_package = "com.github.xds.core.v3"; +option go_package = "github.com/cncf/xds/go/xds/core/v3"; -option (udpa.annotations.file_status).work_in_progress = true; +option (xds.annotations.v3.file_status).work_in_progress = true; // Additional parameters that can be used to select resource variants. These include any // global context parameters, per-resource type client feature capabilities and per-resource diff --git a/xds/third_party/udpa/src/main/proto/xds/core/v3/resource_locator.proto b/xds/third_party/xds/src/main/proto/xds/core/v3/resource_locator.proto similarity index 95% rename from xds/third_party/udpa/src/main/proto/xds/core/v3/resource_locator.proto rename to xds/third_party/xds/src/main/proto/xds/core/v3/resource_locator.proto index d7334394ae2..9b40d52fc43 100644 --- a/xds/third_party/udpa/src/main/proto/xds/core/v3/resource_locator.proto +++ b/xds/third_party/xds/src/main/proto/xds/core/v3/resource_locator.proto @@ -2,16 +2,17 @@ syntax = "proto3"; package xds.core.v3; -import "udpa/annotations/status.proto"; +import "xds/annotations/v3/status.proto"; import "xds/core/v3/context_params.proto"; import "validate/validate.proto"; option java_outer_classname = "ResourceLocatorProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.xds.core.v3"; +option java_package = "com.github.xds.core.v3"; +option go_package = "github.com/cncf/xds/go/xds/core/v3"; -option (udpa.annotations.file_status).work_in_progress = true; +option (xds.annotations.v3.file_status).work_in_progress = true; // xDS resource locators identify a xDS resource name and instruct the // data-plane load balancer on how the resource may be located. diff --git a/xds/third_party/udpa/src/main/proto/xds/core/v3/resource_name.proto b/xds/third_party/xds/src/main/proto/xds/core/v3/resource_name.proto similarity index 86% rename from xds/third_party/udpa/src/main/proto/xds/core/v3/resource_name.proto rename to xds/third_party/xds/src/main/proto/xds/core/v3/resource_name.proto index 103c7de8640..0f3d9974079 100644 --- a/xds/third_party/udpa/src/main/proto/xds/core/v3/resource_name.proto +++ b/xds/third_party/xds/src/main/proto/xds/core/v3/resource_name.proto @@ -2,16 +2,17 @@ syntax = "proto3"; package xds.core.v3; -import "udpa/annotations/status.proto"; +import "xds/annotations/v3/status.proto"; import "xds/core/v3/context_params.proto"; import "validate/validate.proto"; option java_outer_classname = "ResourceNameProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.xds.core.v3"; +option java_package = "com.github.xds.core.v3"; +option go_package = "github.com/cncf/xds/go/xds/core/v3"; -option (udpa.annotations.file_status).work_in_progress = true; +option (xds.annotations.v3.file_status).work_in_progress = true; // xDS resource name. This has a canonical xdstp:// URI representation: // diff --git a/xds/third_party/udpa/src/main/proto/udpa/data/orca/v1/orca_load_report.proto b/xds/third_party/xds/src/main/proto/xds/data/orca/v3/orca_load_report.proto similarity index 90% rename from xds/third_party/udpa/src/main/proto/udpa/data/orca/v1/orca_load_report.proto rename to xds/third_party/xds/src/main/proto/xds/data/orca/v3/orca_load_report.proto index 3105b094724..9b8f03827dc 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/data/orca/v1/orca_load_report.proto +++ b/xds/third_party/xds/src/main/proto/xds/data/orca/v3/orca_load_report.proto @@ -1,10 +1,11 @@ syntax = "proto3"; -package udpa.data.orca.v1; +package xds.data.orca.v3; option java_outer_classname = "OrcaLoadReportProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.udpa.data.orca.v1"; +option java_package = "com.github.xds.data.orca.v3"; +option go_package = "github.com/cncf/xds/go/xds/data/orca/v3"; import "validate/validate.proto"; diff --git a/xds/third_party/udpa/src/main/proto/udpa/service/orca/v1/orca.proto b/xds/third_party/xds/src/main/proto/xds/service/orca/v3/orca.proto similarity index 81% rename from xds/third_party/udpa/src/main/proto/udpa/service/orca/v1/orca.proto rename to xds/third_party/xds/src/main/proto/xds/service/orca/v3/orca.proto index d48cccfeacb..addf62f1ce5 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/service/orca/v1/orca.proto +++ b/xds/third_party/xds/src/main/proto/xds/service/orca/v3/orca.proto @@ -1,12 +1,13 @@ syntax = "proto3"; -package udpa.service.orca.v1; +package xds.service.orca.v3; option java_outer_classname = "OrcaProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.udpa.service.orca.v1"; +option java_package = "com.github.xds.service.orca.v3"; +option go_package = "github.com/cncf/xds/go/xds/service/orca/v3"; -import "udpa/data/orca/v1/orca_load_report.proto"; +import "xds/data/orca/v3/orca_load_report.proto"; import "google/protobuf/duration.proto"; @@ -24,7 +25,7 @@ import "validate/validate.proto"; // streaming service, client needs to terminate current RPC and initiate // a new call to change backend reporting frequency. service OpenRcaService { - rpc StreamCoreMetrics(OrcaLoadReportRequest) returns (stream udpa.data.orca.v1.OrcaLoadReport); + rpc StreamCoreMetrics(OrcaLoadReportRequest) returns (stream xds.data.orca.v3.OrcaLoadReport); } message OrcaLoadReportRequest { diff --git a/xds/third_party/udpa/src/main/proto/udpa/type/v1/typed_struct.proto b/xds/third_party/xds/src/main/proto/xds/type/v3/typed_struct.proto similarity index 94% rename from xds/third_party/udpa/src/main/proto/udpa/type/v1/typed_struct.proto rename to xds/third_party/xds/src/main/proto/xds/type/v3/typed_struct.proto index e46a2cb5757..5d7226c4bf6 100644 --- a/xds/third_party/udpa/src/main/proto/udpa/type/v1/typed_struct.proto +++ b/xds/third_party/xds/src/main/proto/xds/type/v3/typed_struct.proto @@ -1,10 +1,11 @@ syntax = "proto3"; -package udpa.type.v1; +package xds.type.v3; option java_outer_classname = "TypedStructProto"; option java_multiple_files = true; -option java_package = "com.github.udpa.udpa.type.v1"; +option java_package = "com.github.xds.type.v3"; +option go_package = "github.com/cncf/xds/go/xds/type/v3"; import "validate/validate.proto"; import "google/protobuf/struct.proto"; From 71c5eb07d3e618d1ee22b87946390d6e67c8492d Mon Sep 17 00:00:00 2001 From: yifeizhuang Date: Fri, 12 Nov 2021 16:54:35 -0800 Subject: [PATCH 0007/2009] Update README etc to reference 1.42.1 (#8694) --- README.md | 36 ++++++++++++------------ cronet/README.md | 2 +- documentation/android-channel-builder.md | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index aa3c61b9c47..d11c2850805 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,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.42.0/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.42.0/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.42.1/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.42.1/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -43,17 +43,17 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.42.0 + 1.42.1 io.grpc grpc-protobuf - 1.42.0 + 1.42.1 io.grpc grpc-stub - 1.42.0 + 1.42.1 org.apache.tomcat @@ -65,23 +65,23 @@ 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 -implementation 'io.grpc:grpc-netty-shaded:1.42.0' -implementation 'io.grpc:grpc-protobuf:1.42.0' -implementation 'io.grpc:grpc-stub:1.42.0' +implementation 'io.grpc:grpc-netty-shaded:1.42.1' +implementation 'io.grpc:grpc-protobuf:1.42.1' +implementation 'io.grpc:grpc-stub:1.42.1' 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.42.0' -implementation 'io.grpc:grpc-protobuf-lite:1.42.0' -implementation 'io.grpc:grpc-stub:1.42.0' +implementation 'io.grpc:grpc-okhttp:1.42.1' +implementation 'io.grpc:grpc-protobuf-lite:1.42.1' +implementation 'io.grpc:grpc-stub:1.42.1' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.42.0 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.42.1 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -111,9 +111,9 @@ For protobuf-based codegen integrated with the Maven build system, you can use protobuf-maven-plugin 0.6.1 - com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier} + com.google.protobuf:protoc:3.17.2:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.42.0:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier} @@ -139,11 +139,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.17.3" + artifact = "com.google.protobuf:protoc:3.17.2" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.42.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' } } generateProtoTasks { @@ -172,11 +172,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.17.3" + artifact = "com.google.protobuf:protoc:3.17.2" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.42.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' } } generateProtoTasks { diff --git a/cronet/README.md b/cronet/README.md index 9a9f8fbe6c4..a682c5bcee8 100644 --- a/cronet/README.md +++ b/cronet/README.md @@ -26,7 +26,7 @@ In your app module's `build.gradle` file, include a dependency on both `grpc-cro Google Play Services Client Library for Cronet ``` -implementation 'io.grpc:grpc-cronet:1.42.0' +implementation 'io.grpc:grpc-cronet:1.42.1' implementation 'com.google.android.gms:play-services-cronet:16.0.0' ``` diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md index 7e56e391038..d9541c56623 100644 --- a/documentation/android-channel-builder.md +++ b/documentation/android-channel-builder.md @@ -36,8 +36,8 @@ In your `build.gradle` file, include a dependency on both `grpc-android` and `grpc-okhttp`: ``` -implementation 'io.grpc:grpc-android:1.42.0' -implementation 'io.grpc:grpc-okhttp:1.42.0' +implementation 'io.grpc:grpc-android:1.42.1' +implementation 'io.grpc:grpc-okhttp:1.42.1' ``` You also need permission to access the device's network state in your From b746bab97b6910aa55bd8f0a40d8f5b8b51501cb Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Fri, 12 Nov 2021 17:40:07 -0800 Subject: [PATCH 0008/2009] buildscripts: rename xds-k8s to psm-security as part of tech-debt cleanup and name clarity (#8695) --- buildscripts/kokoro/{xds-k8s.cfg => psm-security.cfg} | 2 +- buildscripts/kokoro/{xds-k8s.sh => psm-security.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename buildscripts/kokoro/{xds-k8s.cfg => psm-security.cfg} (81%) rename buildscripts/kokoro/{xds-k8s.sh => psm-security.sh} (100%) diff --git a/buildscripts/kokoro/xds-k8s.cfg b/buildscripts/kokoro/psm-security.cfg similarity index 81% rename from buildscripts/kokoro/xds-k8s.cfg rename to buildscripts/kokoro/psm-security.cfg index bdbd968d7a3..f2cfd7babff 100644 --- a/buildscripts/kokoro/xds-k8s.cfg +++ b/buildscripts/kokoro/psm-security.cfg @@ -1,7 +1,7 @@ # Config file for internal CI # Location of the continuous shell script in repository. -build_file: "grpc-java/buildscripts/kokoro/xds-k8s.sh" +build_file: "grpc-java/buildscripts/kokoro/psm-security.sh" timeout_mins: 180 action { diff --git a/buildscripts/kokoro/xds-k8s.sh b/buildscripts/kokoro/psm-security.sh similarity index 100% rename from buildscripts/kokoro/xds-k8s.sh rename to buildscripts/kokoro/psm-security.sh From a2398ce5dbe2eacf841d7af9c9aa5e912e8db0aa Mon Sep 17 00:00:00 2001 From: Mohan Li <67390330+mohanli-ml@users.noreply.github.com> Date: Mon, 15 Nov 2021 15:46:56 -0800 Subject: [PATCH 0009/2009] alts: Make GoogleDefaultChannelCredentials take a CallCredentials (#8548) DirectPath is going to support non-default service account. This commit allows users to pass CallCredentials to GoogleDefaultChannelCredentials. See design in go/directpath-file-credential-google-default-creds --- .../alts/GoogleDefaultChannelCredentials.java | 79 +++++++++++++------ 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java index b7d79435f00..fe8c005da45 100644 --- a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java +++ b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java @@ -44,30 +44,65 @@ private GoogleDefaultChannelCredentials() {} * as fallback. */ public static ChannelCredentials create() { - ChannelCredentials nettyCredentials = - InternalNettyChannelCredentials.create(createClientFactory()); - CallCredentials callCredentials; - try { - callCredentials = MoreCallCredentials.from(GoogleCredentials.getApplicationDefault()); - } catch (IOException e) { - callCredentials = new FailingCallCredentials( - Status.UNAUTHENTICATED - .withDescription("Failed to get Google default credentials") - .withCause(e)); - } - return CompositeChannelCredentials.create(nettyCredentials, callCredentials); + return newBuilder().build(); } - private static InternalProtocolNegotiator.ClientFactory createClientFactory() { - SslContext sslContext; - try { - sslContext = GrpcSslContexts.forClient().build(); - } catch (SSLException e) { - throw new RuntimeException(e); + /** + * Returns a new instance of {@link Builder}. + * + * @since 1.42.0 + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Builder for {@link GoogleDefaultChannelCredentials} instances. + * + * @since 1.42.0 + */ + public static final class Builder { + private CallCredentials callCredentials; + + private Builder() {} + + /** Constructs GoogleDefaultChannelCredentials with a given call credential. */ + public Builder callCredentials(CallCredentials callCreds) { + callCredentials = callCreds; + return this; + } + + /** Builds a GoogleDefaultChannelCredentials instance. */ + public ChannelCredentials build() { + ChannelCredentials nettyCredentials = + InternalNettyChannelCredentials.create(createClientFactory()); + if (callCredentials != null) { + return CompositeChannelCredentials.create(nettyCredentials, callCredentials); + } + CallCredentials callCreds; + try { + callCreds = MoreCallCredentials.from(GoogleCredentials.getApplicationDefault()); + } catch (IOException e) { + callCreds = + new FailingCallCredentials( + Status.UNAUTHENTICATED + .withDescription("Failed to get Google default credentials") + .withCause(e)); + } + return CompositeChannelCredentials.create(nettyCredentials, callCreds); + } + + private static InternalProtocolNegotiator.ClientFactory createClientFactory() { + SslContext sslContext; + try { + sslContext = GrpcSslContexts.forClient().build(); + } catch (SSLException e) { + throw new RuntimeException(e); + } + return new GoogleDefaultProtocolNegotiatorFactory( + /* targetServiceAccounts= */ ImmutableList.of(), + SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL), + sslContext); } - return new GoogleDefaultProtocolNegotiatorFactory( - /* targetServiceAccounts= */ ImmutableList.of(), - SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL), - sslContext); } } From 5a3b8e2141a9992f71361bd605ebc6f1184742e2 Mon Sep 17 00:00:00 2001 From: beatrausch <30717474+beatrausch@users.noreply.github.com> Date: Wed, 17 Nov 2021 03:29:29 +0100 Subject: [PATCH 0010/2009] okhttp: introduced new TLS1.2 cipher suites and internal okhttp implementation for TLS1.3 prepared (#8650) This introduces new TLS 1.2 cipher suites (#8610) and prepares the internal okhttp implementation for TLS1.3. A new method for creating internal ConnectionSpec was added to be able to use the newly introduced cipher suites in the OkHttpChannelBuilder. Okhttp cipher suites synchronized with the ones from netty. --- .../io/grpc/okhttp/OkHttpChannelBuilder.java | 47 +++++++++++++++--- .../io/grpc/okhttp/internal/CipherSuite.java | 22 +++++++++ .../grpc/okhttp/internal/ConnectionSpec.java | 49 ++++++++++--------- .../io/grpc/okhttp/internal/TlsVersion.java | 5 +- 4 files changed, 92 insertions(+), 31 deletions(-) diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index af5ebe2886c..b3e90d158fa 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -105,15 +105,22 @@ private enum NegotiationType { new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .cipherSuites( // The following items should be sync with Netty's Http2SecurityUtil.CIPHERS. - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) - .tlsVersions(TlsVersion.TLS_1_2) + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + + // TLS 1.3 does not work so far. See issues: + // https://github.com/grpc/grpc-java/issues/7765 + // + // TLS 1.3 + //CipherSuite.TLS_AES_128_GCM_SHA256, + //CipherSuite.TLS_AES_256_GCM_SHA384, + //CipherSuite.TLS_CHACHA20_POLY1305_SHA256 + ) + .tlsVersions(/*TlsVersion.TLS_1_3,*/ TlsVersion.TLS_1_2) .supportsTlsExtensions(true) .build(); @@ -396,6 +403,32 @@ public OkHttpChannelBuilder connectionSpec( return this; } + /** + * Sets the connection specification used for secure connections. + * + *

By default a modern, HTTP/2-compatible spec will be used. + * + *

This method is only used when building a secure connection. For plaintext + * connection, use {@link #usePlaintext()} instead. + * + * @param tlsVersions List of tls versions. + * @param cipherSuites List of cipher suites. + */ + public OkHttpChannelBuilder tlsConnectionSpec( + String[] tlsVersions, String[] cipherSuites) { + Preconditions.checkState(!freezeSecurityConfiguration, + "Cannot change security when using ChannelCredentials"); + Preconditions.checkNotNull(tlsVersions, "tls versions must not null"); + Preconditions.checkNotNull(cipherSuites, "ciphers must not null"); + + this.connectionSpec = new ConnectionSpec.Builder(true) + .supportsTlsExtensions(true) + .tlsVersions(tlsVersions) + .cipherSuites(cipherSuites) + .build(); + return this; + } + /** Sets the negotiation type for the HTTP/2 connection to plaintext. */ @Override public OkHttpChannelBuilder usePlaintext() { diff --git a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/CipherSuite.java b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/CipherSuite.java index 70fa796f248..1a9aab284bb 100644 --- a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/CipherSuite.java +++ b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/CipherSuite.java @@ -354,6 +354,22 @@ public enum CipherSuite { // TLS_ECDHE_ECDSA_WITH_AES_256_CCM("TLS_ECDHE_ECDSA_WITH_AES_256_CCM", 0xc0ad, 7251, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", 0xc0ae, 7251, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8("TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", 0xc0af, 7251, MAX_VALUE, MAX_VALUE), + + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 0xcca8), + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 0xcca9), + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256("TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 0xccaa), + // TLS_PSK_WITH_CHACHA20_POLY1305_SHA256("TLS_PSK_WITH_CHACHA20_POLY1305_SHA256", 0xccab), + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256("TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 0xccac), + // TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256("TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 0xccad), + // TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256("TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256", 0xccae), + + // TLS 1.3 https://tools.ietf.org/html/rfc8446 + TLS_AES_128_GCM_SHA256("TLS_AES_128_GCM_SHA256", 0x1301), + TLS_AES_256_GCM_SHA384("TLS_AES_256_GCM_SHA384", 0x1302), + TLS_CHACHA20_POLY1305_SHA256("TLS_CHACHA20_POLY1305_SHA256", 0x1303), + TLS_AES_128_CCM_SHA256("TLS_AES_128_CCM_SHA256", 0x1304), + TLS_AES_128_CCM_8_SHA256("TLS_AES_128_CCM_8_SHA256", 0x1305), + ; final String javaName; @@ -372,6 +388,12 @@ private CipherSuite( this.javaName = javaName; } + @SuppressWarnings("UnusedVariable") + private CipherSuite( + String javaName, int value) { + this.javaName = javaName; + } + public static CipherSuite forJavaName(String javaName) { return javaName.startsWith("SSL_") ? valueOf("TLS_" + javaName.substring(4)) diff --git a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/ConnectionSpec.java b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/ConnectionSpec.java index 457e9c301f3..b84a1ff94ee 100644 --- a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/ConnectionSpec.java +++ b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/ConnectionSpec.java @@ -30,40 +30,43 @@ */ public final class ConnectionSpec { - // This is a subset of the cipher suites supported in Chrome 37, current as of 2014-10-5. - // All of these suites are available on Android 5.0; earlier releases support a subset of - // these suites. https://github.com/square/okhttp/issues/330 + // This is nearly equal to the cipher suites supported in Chrome 72, current as of 2019-02-24. + // See https://tinyurl.com/okhttp-cipher-suites for availability. private static final CipherSuite[] APPROVED_CIPHER_SUITES = new CipherSuite[] { - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - - // Note that the following cipher suites are all on HTTP/2's bad cipher suites list. We'll - // continue to include them until better suites are commonly available. For example, none - // of the better cipher suites listed above shipped with Android 4.4 or Java 7. - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, + // TLSv1.3. + CipherSuite.TLS_AES_128_GCM_SHA256, + CipherSuite.TLS_AES_256_GCM_SHA384, + CipherSuite.TLS_CHACHA20_POLY1305_SHA256, + + // TLSv1.0, TLSv1.1, TLSv1.2. + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + + // Note that the following cipher suites are all on HTTP/2's bad cipher suites list. We'll + // continue to include them until better suites are commonly available. + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA }; /** A modern TLS connection with extensions like SNI and ALPN available. */ public static final ConnectionSpec MODERN_TLS = new Builder(true) .cipherSuites(APPROVED_CIPHER_SUITES) - .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0) + .tlsVersions(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2) .supportsTlsExtensions(true) .build(); /** A backwards-compatible fallback connection for interop with obsolete servers. */ public static final ConnectionSpec COMPATIBLE_TLS = new Builder(MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_0) + .tlsVersions(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0) .supportsTlsExtensions(true) .build(); diff --git a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/TlsVersion.java b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/TlsVersion.java index 548f4acbc5b..6692c80fad4 100644 --- a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/TlsVersion.java +++ b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/TlsVersion.java @@ -26,6 +26,7 @@ * {@link SSLSocket#setEnabledProtocols}. */ public enum TlsVersion { + TLS_1_3("TLSv1.3"), // 2016. TLS_1_2("TLSv1.2"), // 2008. TLS_1_1("TLSv1.1"), // 2006. TLS_1_0("TLSv1"), // 1999. @@ -39,7 +40,9 @@ private TlsVersion(String javaName) { } public static TlsVersion forJavaName(String javaName) { - if ("TLSv1.2".equals(javaName)) { + if ("TLSv1.3".equals(javaName)) { + return TLS_1_3; + } else if ("TLSv1.2".equals(javaName)) { return TLS_1_2; } else if ("TLSv1.1".equals(javaName)) { return TLS_1_1; From dd0db6cf41df21965bb7c0f166cdf279c31290ad Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Wed, 17 Nov 2021 19:54:40 -0800 Subject: [PATCH 0011/2009] xds: terminate XdsServer start() thread when shutdownNow() is called `XdsServerWrapper.start()` [blocks](https://github.com/grpc/grpc-java/blob/master/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java#L162) until `LdsResourceWatcher`'s callback is called. If no callback is called due to whatever issue of the XdsClient, the server start() will be stuck forever, even we call `shutdownNow()`. Changing the `shutdownNow()` behavior to unblock `start()` immediately. --- .../java/io/grpc/xds/XdsServerWrapper.java | 1 + .../io/grpc/xds/XdsServerWrapperTest.java | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java index dab3cd798f7..6eefcf63411 100644 --- a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java +++ b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java @@ -224,6 +224,7 @@ public void run() { delegate.shutdownNow(); } internalShutdown(); + initialStartFuture.set(new IOException("server is forcefully shut down")); } }); return this; diff --git a/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java b/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java index 1bd102db42d..bfb16c9745e 100644 --- a/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java @@ -76,6 +76,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -116,6 +117,11 @@ selectorManager, new FakeXdsClientPoolFactory(xdsClient), filterRegistry, executor.getScheduledExecutorService()); } + @After + public void tearDown() { + xdsServerWrapper.shutdownNow(); + } + @Test public void testBootstrap_notV3() throws Exception { Bootstrapper.BootstrapInfo b = @@ -324,6 +330,33 @@ public void run() { assertThat(xdsServerWrapper.isTerminated()).isTrue(); } + @Test + public void shutdownNow_startThreadShouldNotLeak() throws Exception { + final SettableFuture start = SettableFuture.create(); + Executors.newSingleThreadExecutor() + .execute( + new Runnable() { + @Override + public void run() { + try { + start.set(xdsServerWrapper.start()); + } catch (Exception ex) { + start.setException(ex); + } + } + }); + assertThat(xdsClient.ldsResource.get(5, TimeUnit.SECONDS)) + .isEqualTo("grpc/server?udpa.resource.listening_address=0.0.0.0:1"); + xdsServerWrapper.shutdownNow(); + try { + start.get(5, TimeUnit.SECONDS); + fail("should have thrown but not"); + } catch (ExecutionException ex) { + assertThat(ex).hasCauseThat().isInstanceOf(IOException.class); + assertThat(ex).hasCauseThat().hasMessageThat().isEqualTo("server is forcefully shut down"); + } + } + @Test public void initialStartIoException() throws Exception { final SettableFuture start = SettableFuture.create(); From 8382bd8e04347478bcf483319fb0b376f726023d Mon Sep 17 00:00:00 2001 From: yifeizhuang Date: Thu, 18 Nov 2021 14:30:35 -0800 Subject: [PATCH 0012/2009] xds: fix clusterImplLoadBalancer NPE when lrs is null (#8713) --- .../main/java/io/grpc/xds/ClusterImplLoadBalancer.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java index 60e6c696daf..b4fc017d2d1 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java @@ -319,9 +319,11 @@ public PickResult pickSubchannel(PickSubchannelArgs args) { } final ClusterLocalityStats stats = result.getSubchannel().getAttributes().get(ATTR_CLUSTER_LOCALITY_STATS); - ClientStreamTracer.Factory tracerFactory = new CountingStreamTracerFactory( - stats, inFlights, result.getStreamTracerFactory()); - return PickResult.withSubchannel(result.getSubchannel(), tracerFactory); + if (stats != null) { + ClientStreamTracer.Factory tracerFactory = new CountingStreamTracerFactory( + stats, inFlights, result.getStreamTracerFactory()); + return PickResult.withSubchannel(result.getSubchannel(), tracerFactory); + } } return result; } From a5f1fb51b81bce57bc0dc286501e9887f8e7c681 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Fri, 19 Nov 2021 10:12:39 -0800 Subject: [PATCH 0013/2009] core: have JsonUtil support parsing String value as number (#8711) As documented in https://developers.google.com/protocol-buffers/docs/proto3#json, the canonical proto-to-json converter converts int64 (Java long) values to string values in Json rather than Json numbers (Java Double). Conversely, either Json string value or number value are accepted to be converted to int64 proto value. To better support service configs defined by protobuf messages, support parsing String values as numbers in `JsonUtil`. --- .../io/grpc/internal/DnsNameResolver.java | 2 +- .../main/java/io/grpc/internal/JsonUtil.java | 81 ++++++++--- .../io/grpc/internal/ServiceConfigUtil.java | 6 +- .../java/io/grpc/internal/JsonUtilTest.java | 133 ++++++++++++++++++ 4 files changed, 195 insertions(+), 27 deletions(-) create mode 100644 core/src/test/java/io/grpc/internal/JsonUtilTest.java diff --git a/core/src/main/java/io/grpc/internal/DnsNameResolver.java b/core/src/main/java/io/grpc/internal/DnsNameResolver.java index bc994a01035..5418a0bd32d 100644 --- a/core/src/main/java/io/grpc/internal/DnsNameResolver.java +++ b/core/src/main/java/io/grpc/internal/DnsNameResolver.java @@ -434,7 +434,7 @@ final int getPort() { @Nullable private static final Double getPercentageFromChoice(Map serviceConfigChoice) { - return JsonUtil.getNumber(serviceConfigChoice, SERVICE_CONFIG_CHOICE_PERCENTAGE_KEY); + return JsonUtil.getNumberAsDouble(serviceConfigChoice, SERVICE_CONFIG_CHOICE_PERCENTAGE_KEY); } @Nullable diff --git a/core/src/main/java/io/grpc/internal/JsonUtil.java b/core/src/main/java/io/grpc/internal/JsonUtil.java index d80b4ed44c4..117135fe634 100644 --- a/core/src/main/java/io/grpc/internal/JsonUtil.java +++ b/core/src/main/java/io/grpc/internal/JsonUtil.java @@ -96,57 +96,92 @@ public static List getListOfStrings(Map obj, String key) { /** * Gets a number from an object for the given key. If the key is not present, this returns null. - * If the value is not a Double, throws an exception. + * If the value does not represent a double, throws an exception. */ @Nullable - public static Double getNumber(Map obj, String key) { + public static Double getNumberAsDouble(Map obj, String key) { assert key != null; if (!obj.containsKey(key)) { return null; } Object value = obj.get(key); - if (!(value instanceof Double)) { - throw new ClassCastException( - String.format("value '%s' for key '%s' in '%s' is not Double", value, key, obj)); + if (value instanceof Double) { + return (Double) value; + } + if (value instanceof String) { + try { + return Double.parseDouble((String) value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' is not a double", value, key)); + } } - return (Double) value; + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' in '%s' is not a number", value, key, obj)); } /** * Gets a number from an object for the given key, casted to an integer. If the key is not - * present, this returns null. If the value is not a Double or loses precision when cast to an - * integer, throws an exception. + * present, this returns null. If the value does not represent an integer, throws an exception. */ + @Nullable public static Integer getNumberAsInteger(Map obj, String key) { - Double d = getNumber(obj, key); - if (d == null) { + assert key != null; + if (!obj.containsKey(key)) { return null; } - int i = d.intValue(); - if (i != d) { - throw new ClassCastException("Number expected to be integer: " + d); + Object value = obj.get(key); + if (value instanceof Double) { + Double d = (Double) value; + int i = d.intValue(); + if (i != d) { + throw new ClassCastException("Number expected to be integer: " + d); + } + return i; + } + if (value instanceof String) { + try { + return Integer.parseInt((String) value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' is not an integer", value, key)); + } } - return i; + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' is not an integer", value, key)); } /** * Gets a number from an object for the given key, casted to an long. If the key is not - * present, this returns null. If the value is not a Double or loses precision when cast to an - * long, throws an exception. + * present, this returns null. If the value does not represent a long integer, throws an + * exception. */ public static Long getNumberAsLong(Map obj, String key) { - Double d = getNumber(obj, key); - if (d == null) { + assert key != null; + if (!obj.containsKey(key)) { return null; } - long l = d.longValue(); - if (l != d) { - throw new ClassCastException("Number expected to be long: " + d); + Object value = obj.get(key); + if (value instanceof Double) { + Double d = (Double) value; + long l = d.longValue(); + if (l != d) { + throw new ClassCastException("Number expected to be long: " + d); + } + return l; + } + if (value instanceof String) { + try { + return Long.parseLong((String) value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' is not a long integer", value, key)); + } } - return l; + throw new IllegalArgumentException( + String.format("value '%s' for key '%s' is not a long integer", value, key)); } - /** * Gets a string from an object for the given key. If the key is not present, this returns null. * If the value is not a String, throws an exception. diff --git a/core/src/main/java/io/grpc/internal/ServiceConfigUtil.java b/core/src/main/java/io/grpc/internal/ServiceConfigUtil.java index 294e9dbcf73..34d44f7f549 100644 --- a/core/src/main/java/io/grpc/internal/ServiceConfigUtil.java +++ b/core/src/main/java/io/grpc/internal/ServiceConfigUtil.java @@ -113,8 +113,8 @@ static Throttle getThrottlePolicy(@Nullable Map serviceConfig) { } // TODO(dapengzhang0): check if this is null. - float maxTokens = JsonUtil.getNumber(throttling, "maxTokens").floatValue(); - float tokenRatio = JsonUtil.getNumber(throttling, "tokenRatio").floatValue(); + float maxTokens = JsonUtil.getNumberAsDouble(throttling, "maxTokens").floatValue(); + float tokenRatio = JsonUtil.getNumberAsDouble(throttling, "tokenRatio").floatValue(); checkState(maxTokens > 0f, "maxToken should be greater than zero"); checkState(tokenRatio > 0f, "tokenRatio should be greater than zero"); return new Throttle(maxTokens, tokenRatio); @@ -137,7 +137,7 @@ static Long getMaxBackoffNanosFromRetryPolicy(Map retryPolicy) { @Nullable static Double getBackoffMultiplierFromRetryPolicy(Map retryPolicy) { - return JsonUtil.getNumber(retryPolicy, "backoffMultiplier"); + return JsonUtil.getNumberAsDouble(retryPolicy, "backoffMultiplier"); } @Nullable diff --git a/core/src/test/java/io/grpc/internal/JsonUtilTest.java b/core/src/test/java/io/grpc/internal/JsonUtilTest.java new file mode 100644 index 00000000000..960800c97c0 --- /dev/null +++ b/core/src/test/java/io/grpc/internal/JsonUtilTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2021, gRPC Authors All rights reserved. + * + * 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.internal; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link JsonUtil}. */ +@RunWith(JUnit4.class) +public class JsonUtilTest { + @Test + public void getNumber() { + Map map = new HashMap<>(); + map.put("key_number_1", 1D); + map.put("key_string_2.0", "2.0"); + map.put("key_string_3", "3"); + map.put("key_string_nan", "NaN"); + map.put("key_number_5.5", 5.5D); + map.put("key_string_six", "six"); + map.put("key_string_infinity", "Infinity"); + map.put("key_string_minus_infinity", "-Infinity"); + map.put("key_string_exponent", "2.998e8"); + map.put("key_string_minus_zero", "-0"); + + assertThat(JsonUtil.getNumberAsDouble(map, "key_number_1")).isEqualTo(1D); + assertThat(JsonUtil.getNumberAsInteger(map, "key_number_1")).isEqualTo(1); + assertThat(JsonUtil.getNumberAsLong(map, "key_number_1")).isEqualTo(1L); + + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_2.0")).isEqualTo(2D); + try { + JsonUtil.getNumberAsInteger(map, "key_string_2.0"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value '2.0' for key 'key_string_2.0' is not an integer"); + } + try { + JsonUtil.getNumberAsLong(map, "key_string_2.0"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value '2.0' for key 'key_string_2.0' is not a long integer"); + } + + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_3")).isEqualTo(3D); + assertThat(JsonUtil.getNumberAsInteger(map, "key_string_3")).isEqualTo(3); + assertThat(JsonUtil.getNumberAsLong(map, "key_string_3")).isEqualTo(3L); + + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_nan")).isNaN(); + try { + JsonUtil.getNumberAsInteger(map, "key_string_nan"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value 'NaN' for key 'key_string_nan' is not an integer"); + } + try { + JsonUtil.getNumberAsLong(map, "key_string_nan"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value 'NaN' for key 'key_string_nan' is not a long integer"); + } + + assertThat(JsonUtil.getNumberAsDouble(map, "key_number_5.5")).isEqualTo(5.5D); + try { + JsonUtil.getNumberAsInteger(map, "key_number_5.5"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo("Number expected to be integer: 5.5"); + } + try { + JsonUtil.getNumberAsLong(map, "key_number_5.5"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo("Number expected to be long: 5.5"); + } + + try { + JsonUtil.getNumberAsDouble(map, "key_string_six"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value 'six' for key 'key_string_six' is not a double"); + } + try { + JsonUtil.getNumberAsInteger(map, "key_string_six"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value 'six' for key 'key_string_six' is not an integer"); + } + try { + JsonUtil.getNumberAsLong(map, "key_string_six"); + fail("expecting to throw but did not"); + } catch (RuntimeException e) { + assertThat(e).hasMessageThat().isEqualTo( + "value 'six' for key 'key_string_six' is not a long integer"); + } + + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_infinity")).isPositiveInfinity(); + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_minus_infinity")).isNegativeInfinity(); + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_exponent")).isEqualTo(2.998e8D); + + assertThat(JsonUtil.getNumberAsDouble(map, "key_string_minus_zero")).isZero(); + assertThat(JsonUtil.getNumberAsInteger(map, "key_string_minus_zero")).isEqualTo(0); + assertThat(JsonUtil.getNumberAsLong(map, "key_string_minus_zero")).isEqualTo(0L); + + assertThat(JsonUtil.getNumberAsDouble(map, "key_nonexistent")).isNull(); + assertThat(JsonUtil.getNumberAsInteger(map, "key_nonexistent")).isNull(); + assertThat(JsonUtil.getNumberAsLong(map, "key_nonexistent")).isNull(); + } +} From 5f3a5f8b375367571c0660e0b9e46c38a4175b6e Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Mon, 22 Nov 2021 09:02:35 -0800 Subject: [PATCH 0014/2009] xds: support xdstp scheme in resource URIs for federation (#8716) Implement applying `server_listener_resource_name_template` and `client_listener_resource_name_template` with xdstp scheme, extracting authorities from xdstp resource URI and lookup authorities map in bootstrap. --- .../main/java/io/grpc/xds/Bootstrapper.java | 9 +- .../java/io/grpc/xds/BootstrapperImpl.java | 2 +- .../java/io/grpc/xds/ClientXdsClient.java | 21 +++- .../java/io/grpc/xds/XdsNameResolver.java | 62 ++++++++-- .../io/grpc/xds/XdsNameResolverProvider.java | 7 +- .../java/io/grpc/xds/XdsServerWrapper.java | 8 +- .../io/grpc/xds/ClientXdsClientTestBase.java | 75 +++++++++++- .../java/io/grpc/xds/XdsNameResolverTest.java | 113 ++++++++++++++++-- .../io/grpc/xds/XdsServerWrapperTest.java | 32 +++++ 9 files changed, 295 insertions(+), 34 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/Bootstrapper.java b/xds/src/main/java/io/grpc/xds/Bootstrapper.java index 862f8691080..57cdc6f324b 100644 --- a/xds/src/main/java/io/grpc/xds/Bootstrapper.java +++ b/xds/src/main/java/io/grpc/xds/Bootstrapper.java @@ -16,6 +16,8 @@ package io.grpc.xds; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -33,6 +35,8 @@ @Internal public abstract class Bootstrapper { + static final String XDSTP_SCHEME = "xdstp:"; + /** * Returns system-loaded bootstrap configuration. */ @@ -104,12 +108,13 @@ abstract static class AuthorityInfo { *

If the same server is listed in multiple authorities, the entries will be de-duped (i.e., * resources for both authorities will be fetched on the same ADS stream). * - *

If empty, the top-level server list {@link BootstrapInfo#servers()} will be used. + *

Defaults to the top-level server list {@link BootstrapInfo#servers()}. Must not be empty. */ abstract ImmutableList xdsServers(); static AuthorityInfo create( String clientListenerResourceNameTemplate, List xdsServers) { + checkArgument(!xdsServers.isEmpty(), "xdsServers must not be empty"); return new AutoValue_Bootstrapper_AuthorityInfo( clientListenerResourceNameTemplate, ImmutableList.copyOf(xdsServers)); } @@ -121,7 +126,7 @@ static AuthorityInfo create( @AutoValue @Internal public abstract static class BootstrapInfo { - /** Returns the list of xDS servers to be connected to. */ + /** Returns the list of xDS servers to be connected to. Must not be empty. */ abstract ImmutableList servers(); /** Returns the node identifier to be included in xDS requests. */ diff --git a/xds/src/main/java/io/grpc/xds/BootstrapperImpl.java b/xds/src/main/java/io/grpc/xds/BootstrapperImpl.java index 35ff5e55a42..23b14357096 100644 --- a/xds/src/main/java/io/grpc/xds/BootstrapperImpl.java +++ b/xds/src/main/java/io/grpc/xds/BootstrapperImpl.java @@ -229,7 +229,7 @@ BootstrapInfo bootstrap(Map rawData) throws XdsInitializationExceptio JsonUtil.getString(rawAuthority, "client_listener_resource_name_template"); logger.log( XdsLogLevel.INFO, "client_listener_resource_name_template: {0}", clientListnerTemplate); - String prefix = "xdstp://" + authorityName + "/"; + String prefix = XDSTP_SCHEME + "//" + authorityName + "/"; if (clientListnerTemplate == null) { clientListnerTemplate = prefix + "envoy.config.listener.v3.Listener/%s"; } else if (!clientListnerTemplate.startsWith(prefix)) { diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index 0a11ad47288..2b676553838 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static io.grpc.xds.Bootstrapper.XDSTP_SCHEME; import com.github.udpa.udpa.type.v1.TypedStruct; import com.google.common.annotations.VisibleForTesting; @@ -70,6 +71,7 @@ import io.grpc.internal.BackoffPolicy; import io.grpc.internal.TimeProvider; import io.grpc.xds.AbstractXdsClient.ResourceType; +import io.grpc.xds.Bootstrapper.AuthorityInfo; import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.Endpoints.LbEndpoint; @@ -98,6 +100,7 @@ import io.grpc.xds.internal.Matchers.FractionMatcher; import io.grpc.xds.internal.Matchers.HeaderMatcher; import java.net.InetSocketAddress; +import java.net.URI; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; @@ -2267,8 +2270,12 @@ private final class ResourceSubscriber { ResourceSubscriber(ResourceType type, String resource) { syncContext.throwIfNotInThisSynchronizationContext(); this.type = type; + // TODO(zdapeng): Validate authority in resource URI for new-style resource name + // when parsing XDS response. + // TODO(zdapeng): Canonicalize the resource name by sorting the context params in normal + // lexicographic order. this.resource = resource; - this.serverInfo = getServerInfo(); + this.serverInfo = getServerInfo(resource); // Initialize metadata in UNKNOWN state to cover the case when resource subscriber, // is created but not yet requested because the client is in backoff. this.metadata = ResourceMetadata.newResourceMetadataUnknown(); @@ -2280,8 +2287,16 @@ private final class ResourceSubscriber { restartTimer(); } - // TODO(zdapeng): add resourceName arg and support xdstp:// resources - private ServerInfo getServerInfo() { + private ServerInfo getServerInfo(String resource) { + if (resource.startsWith(XDSTP_SCHEME)) { + URI uri = URI.create(resource); + String authority = uri.getAuthority(); + if (authority == null) { + authority = ""; + } + AuthorityInfo authorityInfo = bootstrapInfo.authorities().get(authority); + return authorityInfo.xdsServers().get(0); + } return bootstrapInfo.servers().get(0); // use first server } diff --git a/xds/src/main/java/io/grpc/xds/XdsNameResolver.java b/xds/src/main/java/io/grpc/xds/XdsNameResolver.java index 4cd52c8b3f9..b6b66327525 100644 --- a/xds/src/main/java/io/grpc/xds/XdsNameResolver.java +++ b/xds/src/main/java/io/grpc/xds/XdsNameResolver.java @@ -18,12 +18,14 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static io.grpc.xds.Bootstrapper.XDSTP_SCHEME; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; +import com.google.common.net.UrlEscapers; import com.google.gson.Gson; import com.google.protobuf.util.Durations; import io.grpc.Attributes; @@ -45,6 +47,8 @@ import io.grpc.SynchronizationContext; import io.grpc.internal.GrpcUtil; import io.grpc.internal.ObjectPool; +import io.grpc.xds.Bootstrapper.AuthorityInfo; +import io.grpc.xds.Bootstrapper.BootstrapInfo; import io.grpc.xds.Filter.ClientInterceptorBuilder; import io.grpc.xds.Filter.FilterConfig; import io.grpc.xds.Filter.NamedFilterConfig; @@ -101,7 +105,9 @@ final class XdsNameResolver extends NameResolver { private final InternalLogId logId; private final XdsLogger logger; - private final String authority; + @Nullable + private final String targetAuthority; + private final String serviceAuthority; private final ServiceConfigParser serviceConfigParser; private final SynchronizationContext syncContext; private final ScheduledExecutorService scheduler; @@ -120,20 +126,23 @@ final class XdsNameResolver extends NameResolver { private CallCounterProvider callCounterProvider; private ResolveState resolveState; - XdsNameResolver(String name, ServiceConfigParser serviceConfigParser, + XdsNameResolver( + @Nullable String targetAuthority, String name, ServiceConfigParser serviceConfigParser, SynchronizationContext syncContext, ScheduledExecutorService scheduler, @Nullable Map bootstrapOverride) { - this(name, serviceConfigParser, syncContext, scheduler, + this(targetAuthority, name, serviceConfigParser, syncContext, scheduler, SharedXdsClientPoolProvider.getDefaultProvider(), ThreadSafeRandomImpl.instance, FilterRegistry.getDefaultRegistry(), bootstrapOverride); } @VisibleForTesting - XdsNameResolver(String name, ServiceConfigParser serviceConfigParser, + XdsNameResolver( + @Nullable String targetAuthority, String name, ServiceConfigParser serviceConfigParser, SynchronizationContext syncContext, ScheduledExecutorService scheduler, XdsClientPoolFactory xdsClientPoolFactory, ThreadSafeRandom random, FilterRegistry filterRegistry, @Nullable Map bootstrapOverride) { - authority = GrpcUtil.checkAuthority(checkNotNull(name, "name")); + this.targetAuthority = targetAuthority; + serviceAuthority = GrpcUtil.checkAuthority(checkNotNull(name, "name")); this.serviceConfigParser = checkNotNull(serviceConfigParser, "serviceConfigParser"); this.syncContext = checkNotNull(syncContext, "syncContext"); this.scheduler = checkNotNull(scheduler, "scheduler"); @@ -149,7 +158,7 @@ final class XdsNameResolver extends NameResolver { @Override public String getServiceAuthority() { - return authority; + return serviceAuthority; } @Override @@ -163,11 +172,33 @@ public void start(Listener2 listener) { return; } xdsClient = xdsClientPool.getObject(); + BootstrapInfo bootstrapInfo = xdsClient.getBootstrapInfo(); + String listenerNameTemplate; + if (targetAuthority == null) { + listenerNameTemplate = bootstrapInfo.clientDefaultListenerResourceNameTemplate(); + } else { + AuthorityInfo authorityInfo = bootstrapInfo.authorities().get(targetAuthority); + if (authorityInfo == null) { + listener.onError(Status.INVALID_ARGUMENT.withDescription( + "invalid target URI: target authority not found in the bootstrap")); + return; + } + listenerNameTemplate = authorityInfo.clientListenerResourceNameTemplate(); + } + String replacement = serviceAuthority; + if (listenerNameTemplate.startsWith(XDSTP_SCHEME)) { + replacement = UrlEscapers.urlFragmentEscaper().escape(replacement); + } + String ldsResourceName = expandPercentS(listenerNameTemplate, replacement); callCounterProvider = SharedCallCounterMap.getInstance(); - resolveState = new ResolveState(); + resolveState = new ResolveState(ldsResourceName); resolveState.start(); } + private static String expandPercentS(String template, String replacement) { + return template.replace("%s", replacement); + } + @Override public void shutdown() { logger.log(XdsLogLevel.INFO, "Shutdown"); @@ -624,12 +655,17 @@ private class ResolveState implements LdsResourceWatcher { .setServiceConfig(emptyServiceConfig) // let channel take action for no config selector .build(); + private final String ldsResourceName; private boolean stopped; @Nullable private Set existingClusters; // clusters to which new requests can be routed @Nullable private RouteDiscoveryState routeDiscoveryState; + ResolveState(String ldsResourceName) { + this.ldsResourceName = ldsResourceName; + } + @Override public void onChanged(final LdsUpdate update) { syncContext.execute(new Runnable() { @@ -686,23 +722,23 @@ public void run() { } private void start() { - logger.log(XdsLogLevel.INFO, "Start watching LDS resource {0}", authority); - xdsClient.watchLdsResource(authority, this); + logger.log(XdsLogLevel.INFO, "Start watching LDS resource {0}", ldsResourceName); + xdsClient.watchLdsResource(ldsResourceName, this); } private void stop() { - logger.log(XdsLogLevel.INFO, "Stop watching LDS resource {0}", authority); + logger.log(XdsLogLevel.INFO, "Stop watching LDS resource {0}", ldsResourceName); stopped = true; cleanUpRouteDiscoveryState(); - xdsClient.cancelLdsResourceWatch(authority, this); + xdsClient.cancelLdsResourceWatch(ldsResourceName, this); } private void updateRoutes(List virtualHosts, long httpMaxStreamDurationNano, @Nullable List filterConfigs) { - VirtualHost virtualHost = findVirtualHostForHostName(virtualHosts, authority); + VirtualHost virtualHost = findVirtualHostForHostName(virtualHosts, ldsResourceName); if (virtualHost == null) { logger.log(XdsLogLevel.WARNING, - "Failed to find virtual host matching hostname {0}", authority); + "Failed to find virtual host matching hostname {0}", ldsResourceName); cleanUpRoutes(); return; } diff --git a/xds/src/main/java/io/grpc/xds/XdsNameResolverProvider.java b/xds/src/main/java/io/grpc/xds/XdsNameResolverProvider.java index 03d88a9752e..a02e27c37c7 100644 --- a/xds/src/main/java/io/grpc/xds/XdsNameResolverProvider.java +++ b/xds/src/main/java/io/grpc/xds/XdsNameResolverProvider.java @@ -74,9 +74,10 @@ public XdsNameResolver newNameResolver(URI targetUri, Args args) { targetPath, targetUri); String name = targetPath.substring(1); - return new XdsNameResolver(name, args.getServiceConfigParser(), - args.getSynchronizationContext(), args.getScheduledExecutorService(), - bootstrapOverride); + return new XdsNameResolver( + targetUri.getAuthority(), name, args.getServiceConfigParser(), + args.getSynchronizationContext(), args.getScheduledExecutorService(), + bootstrapOverride); } return null; } diff --git a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java index 6eefcf63411..0946f621487 100644 --- a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java +++ b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java @@ -18,11 +18,13 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static io.grpc.xds.Bootstrapper.XDSTP_SCHEME; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.net.UrlEscapers; import com.google.common.util.concurrent.SettableFuture; import io.grpc.Attributes; import io.grpc.InternalServerInterceptors; @@ -192,7 +194,11 @@ private void internalStart() { xdsClient = xdsClientPool.returnObject(xdsClient); return; } - discoveryState = new DiscoveryState(listenerTemplate.replaceAll("%s", listenerAddress)); + String replacement = listenerAddress; + if (listenerTemplate.startsWith(XDSTP_SCHEME)) { + replacement = UrlEscapers.urlFragmentEscaper().escape(replacement); + } + discoveryState = new DiscoveryState(listenerTemplate.replaceAll("%s", replacement)); } @Override diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java index 9d0c735ba95..6fdf5e1b811 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java @@ -59,6 +59,7 @@ import io.grpc.internal.TimeProvider; import io.grpc.testing.GrpcCleanupRule; import io.grpc.xds.AbstractXdsClient.ResourceType; +import io.grpc.xds.Bootstrapper.AuthorityInfo; import io.grpc.xds.Bootstrapper.CertificateProviderInfo; import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClientXdsClient.XdsChannelFactory; @@ -114,6 +115,8 @@ @RunWith(JUnit4.class) public abstract class ClientXdsClientTestBase { private static final String SERVER_URI = "trafficdirector.googleapis.com"; + private static final String SERVER_URI_CUSTOME_AUTHORITY = "trafficdirector2.googleapis.com"; + private static final String SERVER_URI_EMPTY_AUTHORITY = "trafficdirector3.googleapis.com"; private static final String LDS_RESOURCE = "listener.googleapis.com"; private static final String RDS_RESOURCE = "route-configuration.googleapis.com"; private static final String CDS_RESOURCE = "cluster.googleapis.com"; @@ -250,6 +253,8 @@ public long currentTimeNanos() { private TlsContextManager tlsContextManager; private ManagedChannel channel; + private ManagedChannel channelForCustomAuthority; + private ManagedChannel channelForEmptyAuthority; private ClientXdsClient xdsClient; private boolean originalEnableFaultInjection; private boolean originalEnableRbac; @@ -281,7 +286,24 @@ public void setUp() throws IOException { XdsChannelFactory xdsChannelFactory = new XdsChannelFactory() { @Override ManagedChannel create(ServerInfo serverInfo) { - return channel; + if (serverInfo.target().equals(SERVER_URI)) { + return channel; + } + if (serverInfo.target().equals(SERVER_URI_CUSTOME_AUTHORITY)) { + if (channelForCustomAuthority == null) { + channelForCustomAuthority = cleanupRule.register( + InProcessChannelBuilder.forName(serverName).directExecutor().build()); + } + return channelForCustomAuthority; + } + if (serverInfo.target().equals(SERVER_URI_EMPTY_AUTHORITY)) { + if (channelForEmptyAuthority == null) { + channelForEmptyAuthority = cleanupRule.register( + InProcessChannelBuilder.forName(serverName).directExecutor().build()); + } + return channelForEmptyAuthority; + } + throw new IllegalArgumentException("Can not create channel for " + serverInfo); } }; @@ -290,6 +312,17 @@ ManagedChannel create(ServerInfo serverInfo) { .servers(Arrays.asList( Bootstrapper.ServerInfo.create(SERVER_URI, CHANNEL_CREDENTIALS, useProtocolV3()))) .node(EnvoyProtoData.Node.newBuilder().build()) + .authorities(ImmutableMap.of( + "authority.xds.com", + AuthorityInfo.create( + "xdstp://authority.xds.com/envoy.config.listener.v3.Listener/%s", + ImmutableList.of(Bootstrapper.ServerInfo.create( + SERVER_URI_CUSTOME_AUTHORITY, CHANNEL_CREDENTIALS, useProtocolV3()))), + "", + AuthorityInfo.create( + "xdstp:///envoy.config.listener.v3.Listener/%s", + ImmutableList.of(Bootstrapper.ServerInfo.create( + SERVER_URI_EMPTY_AUTHORITY, CHANNEL_CREDENTIALS, useProtocolV3()))))) .certProviders(ImmutableMap.of("cert-instance-name", CertificateProviderInfo.create("file-watcher", ImmutableMap.of()))) .build(); @@ -706,6 +739,46 @@ public void ldsResourceUpdated() { .isEqualTo(RDS_RESOURCE); verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_2, TIME_INCREMENT * 2); verifySubscribedResourcesMetadataSizes(1, 0, 0, 0); + assertThat(channelForCustomAuthority).isNull(); + assertThat(channelForEmptyAuthority).isNull(); + } + + @Test + public void ldsResourceUpdated_withXdstpResourceName() { + String ldsResourceName = + "xdstp://authority.xds.com/envoy.config.listener.v3.Listener/listener1"; + DiscoveryRpcCall call = startResourceWatcher(LDS, ldsResourceName, ldsResourceWatcher); + assertThat(channelForCustomAuthority).isNotNull(); + verifyResourceMetadataRequested(LDS, ldsResourceName); + + Any testListenerVhosts = Any.pack(mf.buildListenerWithApiListener(ldsResourceName, + mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(VHOST_SIZE)))); + call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000"); + call.verifyRequest(LDS, ldsResourceName, VERSION_1, "0000", NODE); + verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture()); + assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts()) + .hasSize(VHOST_SIZE); + verifyResourceMetadataAcked( + LDS, ldsResourceName, testListenerVhosts, VERSION_1, TIME_INCREMENT); + } + + @Test + public void ldsResourceUpdated_withXdstpResourceName_withEmptyAuthority() { + String ldsResourceName = + "xdstp:///envoy.config.listener.v3.Listener/listener1"; + DiscoveryRpcCall call = startResourceWatcher(LDS, ldsResourceName, ldsResourceWatcher); + assertThat(channelForEmptyAuthority).isNotNull(); + verifyResourceMetadataRequested(LDS, ldsResourceName); + + Any testListenerVhosts = Any.pack(mf.buildListenerWithApiListener(ldsResourceName, + mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(VHOST_SIZE)))); + call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000"); + call.verifyRequest(LDS, ldsResourceName, VERSION_1, "0000", NODE); + verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture()); + assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts()) + .hasSize(VHOST_SIZE); + verifyResourceMetadataAcked( + LDS, ldsResourceName, testListenerVhosts, VERSION_1, TIME_INCREMENT); } @Test diff --git a/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java b/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java index babaa2b3034..7968b7fb366 100644 --- a/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -45,6 +46,7 @@ import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptors; import io.grpc.Deadline; +import io.grpc.InsecureChannelCredentials; import io.grpc.InternalConfigSelector; import io.grpc.InternalConfigSelector.Result; import io.grpc.Metadata; @@ -67,6 +69,10 @@ import io.grpc.internal.PickSubchannelArgsImpl; import io.grpc.internal.ScParser; import io.grpc.testing.TestMethodDescriptors; +import io.grpc.xds.Bootstrapper.AuthorityInfo; +import io.grpc.xds.Bootstrapper.BootstrapInfo; +import io.grpc.xds.Bootstrapper.ServerInfo; +import io.grpc.xds.EnvoyProtoData.Node; import io.grpc.xds.FaultConfig.FaultAbort; import io.grpc.xds.FaultConfig.FaultDelay; import io.grpc.xds.Filter.FilterConfig; @@ -132,6 +138,12 @@ public ConfigOrError parseServiceConfig(Map rawServiceConfig) { private final CallInfo call1 = new CallInfo("HelloService", "hi"); private final CallInfo call2 = new CallInfo("GreetService", "bye"); private final TestChannel channel = new TestChannel(); + private BootstrapInfo bootstrapInfo = BootstrapInfo.builder() + .servers(ImmutableList.of(ServerInfo.create( + "td.googleapis.com", InsecureChannelCredentials.create(), true))) + .node(Node.newBuilder().build()) + .build(); + private String expectedLdsResourceName = AUTHORITY; @Mock private ThreadSafeRandom mockRandom; @@ -152,7 +164,7 @@ public void setUp() { FilterRegistry filterRegistry = FilterRegistry.newRegistry().register( new FaultFilter(mockRandom, new AtomicLong()), RouterFilter.INSTANCE); - resolver = new XdsNameResolver(AUTHORITY, serviceConfigParser, syncContext, scheduler, + resolver = new XdsNameResolver(null, AUTHORITY, serviceConfigParser, syncContext, scheduler, xdsClientPoolFactory, mockRandom, filterRegistry, null); } @@ -185,7 +197,7 @@ public ObjectPool getOrCreate() throws XdsInitializationException { throw new XdsInitializationException("Fail to read bootstrap file"); } }; - resolver = new XdsNameResolver(AUTHORITY, serviceConfigParser, syncContext, scheduler, + resolver = new XdsNameResolver(null, AUTHORITY, serviceConfigParser, syncContext, scheduler, xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); resolver.start(mockListener); verify(mockListener).onError(errorCaptor.capture()); @@ -195,6 +207,79 @@ public ObjectPool getOrCreate() throws XdsInitializationException { assertThat(error.getCause()).hasMessageThat().isEqualTo("Fail to read bootstrap file"); } + @Test + public void resolving_withTargetAuthorityNotFound() { + resolver = new XdsNameResolver( + "notfound.google.com", AUTHORITY, serviceConfigParser, syncContext, scheduler, + xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); + resolver.start(mockListener); + verify(mockListener).onError(errorCaptor.capture()); + Status error = errorCaptor.getValue(); + assertThat(error.getCode()).isEqualTo(Code.INVALID_ARGUMENT); + assertThat(error.getDescription()).isEqualTo( + "invalid target URI: target authority not found in the bootstrap"); + } + + @Test + public void resolving_noTargetAuthority_templateWithoutXdstp() { + bootstrapInfo = BootstrapInfo.builder() + .servers(ImmutableList.of(ServerInfo.create( + "td.googleapis.com", InsecureChannelCredentials.create(), true))) + .node(Node.newBuilder().build()) + .clientDefaultListenerResourceNameTemplate("%s/id=1") + .build(); + String serviceAuthority = "[::FFFF:129.144.52.38]:80"; + expectedLdsResourceName = "[::FFFF:129.144.52.38]:80/id=1"; + resolver = new XdsNameResolver( + null, serviceAuthority, serviceConfigParser, syncContext, scheduler, xdsClientPoolFactory, + mockRandom, FilterRegistry.getDefaultRegistry(), null); + resolver.start(mockListener); + verify(mockListener, never()).onError(any(Status.class)); + } + + @Test + public void resolving_noTargetAuthority_templateWithXdstp() { + bootstrapInfo = BootstrapInfo.builder() + .servers(ImmutableList.of(ServerInfo.create( + "td.googleapis.com", InsecureChannelCredentials.create(), true))) + .node(Node.newBuilder().build()) + .clientDefaultListenerResourceNameTemplate( + "xdstp://xds.authority.com/envoy.config.listener.v3.Listener/%s?id=1") + .build(); + String serviceAuthority = "[::FFFF:129.144.52.38]:80"; + expectedLdsResourceName = + "xdstp://xds.authority.com/envoy.config.listener.v3.Listener/" + + "%5B::FFFF:129.144.52.38%5D:80?id=1"; + resolver = new XdsNameResolver( + null, serviceAuthority, serviceConfigParser, syncContext, scheduler, + xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); + resolver.start(mockListener); + verify(mockListener, never()).onError(any(Status.class)); + } + + @Test + public void resolving_targetAuthorityInAuthoritiesMap() { + String targetAuthority = "xds.authority.com"; + String serviceAuthority = "[::FFFF:129.144.52.38]:80"; + bootstrapInfo = BootstrapInfo.builder() + .servers(ImmutableList.of(ServerInfo.create( + "td.googleapis.com", InsecureChannelCredentials.create(), true))) + .node(Node.newBuilder().build()) + .authorities( + ImmutableMap.of(targetAuthority, AuthorityInfo.create( + "xdstp://" + targetAuthority + "/envoy.config.listener.v3.Listener/%s", + ImmutableList.of(ServerInfo.create( + "td.googleapis.com", InsecureChannelCredentials.create(), true))))) + .build(); + expectedLdsResourceName = + "xdstp://xds.authority.com/envoy.config.listener.v3.Listener/%5B::FFFF:129.144.52.38%5D:80"; + resolver = new XdsNameResolver( + "xds.authority.com", serviceAuthority, serviceConfigParser, syncContext, scheduler, + xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); + resolver.start(mockListener); + verify(mockListener, never()).onError(any(Status.class)); + } + @Test public void resolving_ldsResourceNotFound() { resolver.start(mockListener); @@ -435,7 +520,7 @@ public void resolved_fallbackToHttpMaxStreamDurationAsTimeout() { public void retryPolicyInPerMethodConfigGeneratedByResolverIsValid() { ServiceConfigParser realParser = new ScParser( true, 5, 5, new AutoConfiguredLoadBalancerFactory("pick-first")); - resolver = new XdsNameResolver(AUTHORITY, realParser, syncContext, scheduler, + resolver = new XdsNameResolver(null, AUTHORITY, realParser, syncContext, scheduler, xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); resolver.start(mockListener); FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient(); @@ -638,7 +723,7 @@ public void resolved_rpcHashingByChannelId() { // A different resolver/Channel. resolver.shutdown(); reset(mockListener); - resolver = new XdsNameResolver(AUTHORITY, serviceConfigParser, syncContext, scheduler, + resolver = new XdsNameResolver(null, AUTHORITY, serviceConfigParser, syncContext, scheduler, xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null); resolver.start(mockListener); xdsClient = (FakeXdsClient) resolver.getXdsClient(); @@ -1698,8 +1783,11 @@ public void routeMatching_withHeaders() { } private final class FakeXdsClientPoolFactory implements XdsClientPoolFactory { + Map bootstrap; + @Override public void setBootstrapOverride(Map bootstrap) { + this.bootstrap = bootstrap; } @Override @@ -1731,11 +1819,16 @@ private class FakeXdsClient extends XdsClient { private LdsResourceWatcher ldsWatcher; private RdsResourceWatcher rdsWatcher; + @Override + BootstrapInfo getBootstrapInfo() { + return bootstrapInfo; + } + @Override void watchLdsResource(String resourceName, LdsResourceWatcher watcher) { assertThat(ldsResource).isNull(); assertThat(ldsWatcher).isNull(); - assertThat(resourceName).isEqualTo(AUTHORITY); + assertThat(resourceName).isEqualTo(expectedLdsResourceName); ldsResource = resourceName; ldsWatcher = watcher; } @@ -1744,7 +1837,7 @@ void watchLdsResource(String resourceName, LdsResourceWatcher watcher) { void cancelLdsResourceWatch(String resourceName, LdsResourceWatcher watcher) { assertThat(ldsResource).isNotNull(); assertThat(ldsWatcher).isNotNull(); - assertThat(resourceName).isEqualTo(AUTHORITY); + assertThat(resourceName).isEqualTo(expectedLdsResourceName); ldsResource = null; ldsWatcher = null; } @@ -1773,7 +1866,7 @@ void deliverLdsUpdate(long httpMaxStreamDurationNano, List virtualH void deliverLdsUpdate(final List routes) { VirtualHost virtualHost = VirtualHost.create( - "virtual-host", Collections.singletonList(AUTHORITY), routes, + "virtual-host", Collections.singletonList(expectedLdsResourceName), routes, ImmutableMap.of()); ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts( 0L, Collections.singletonList(virtualHost), null))); @@ -1817,7 +1910,7 @@ void deliverLdsUpdateWithFaultInjection( FAULT_FILTER_INSTANCE_NAME, virtualHostFaultConfig); VirtualHost virtualHost = VirtualHost.create( "virtual-host", - Collections.singletonList(AUTHORITY), + Collections.singletonList(expectedLdsResourceName), Collections.singletonList(route), overrideConfig); ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts( @@ -1843,7 +1936,7 @@ void deliverLdsUpdateForRdsName(String rdsName) { } void deliverLdsResourceNotFound() { - ldsWatcher.onResourceDoesNotExist(AUTHORITY); + ldsWatcher.onResourceDoesNotExist(expectedLdsResourceName); } void deliverRdsUpdateWithFaultInjection( @@ -1876,7 +1969,7 @@ void deliverRdsUpdateWithFaultInjection( FAULT_FILTER_INSTANCE_NAME, virtualHostFaultConfig); VirtualHost virtualHost = VirtualHost.create( "virtual-host", - Collections.singletonList(AUTHORITY), + Collections.singletonList(expectedLdsResourceName), Collections.singletonList(route), overrideConfig); rdsWatcher.onChanged(new RdsUpdate(Collections.singletonList(virtualHost))); diff --git a/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java b/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java index bfb16c9745e..f011b789da9 100644 --- a/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsServerWrapperTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -55,6 +56,7 @@ import io.grpc.xds.VirtualHost.Route; import io.grpc.xds.VirtualHost.Route.RouteMatch; import io.grpc.xds.VirtualHost.Route.RouteMatch.PathMatcher; +import io.grpc.xds.XdsClient.LdsResourceWatcher; import io.grpc.xds.XdsClient.RdsResourceWatcher; import io.grpc.xds.XdsClient.RdsUpdate; import io.grpc.xds.XdsServerBuilder.XdsServingStatusListener; @@ -173,6 +175,36 @@ public void run() { } } + @Test + public void testBootstrap_templateWithXdstp() throws Exception { + Bootstrapper.BootstrapInfo b = Bootstrapper.BootstrapInfo.builder() + .servers(Arrays.asList( + Bootstrapper.ServerInfo.create( + "uri", InsecureChannelCredentials.create(), true))) + .node(EnvoyProtoData.Node.newBuilder().setId("id").build()) + .serverListenerResourceNameTemplate( + "xdstp://xds.authority.com/envoy.config.listener.v3.Listener/grpc/server/%s") + .build(); + XdsClient xdsClient = mock(XdsClient.class); + when(xdsClient.getBootstrapInfo()).thenReturn(b); + xdsServerWrapper = new XdsServerWrapper("[::FFFF:129.144.52.38]:80", mockBuilder, listener, + selectorManager, new FakeXdsClientPoolFactory(xdsClient), filterRegistry); + Executors.newSingleThreadExecutor().execute(new Runnable() { + @Override + public void run() { + try { + xdsServerWrapper.start(); + } catch (IOException ex) { + // ignore + } + } + }); + verify(xdsClient, timeout(5000)).watchLdsResource( + eq("xdstp://xds.authority.com/envoy.config.listener.v3.Listener/grpc/server/" + + "%5B::FFFF:129.144.52.38%5D:80"), + any(LdsResourceWatcher.class)); + } + @Test public void shutdown() throws Exception { final SettableFuture start = SettableFuture.create(); From ee581bfdfa03e7b0f96fd99e287f5a326648bc42 Mon Sep 17 00:00:00 2001 From: markb74 <57717302+markb74@users.noreply.github.com> Date: Tue, 23 Nov 2021 18:11:54 +0100 Subject: [PATCH 0015/2009] buildscripts: add config for building grpc-binder artifact (#8722) --- buildscripts/kokoro/linux_artifacts.sh | 9 ++++++++- buildscripts/kokoro/upload_artifacts.sh | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/buildscripts/kokoro/linux_artifacts.sh b/buildscripts/kokoro/linux_artifacts.sh index 17402fe89b3..c4386b94e07 100755 --- a/buildscripts/kokoro/linux_artifacts.sh +++ b/buildscripts/kokoro/linux_artifacts.sh @@ -10,7 +10,7 @@ readonly GRPC_JAVA_DIR="$(cd "$(dirname "$0")"/../.. && pwd)" "$GRPC_JAVA_DIR"/buildscripts/build_docker.sh "$GRPC_JAVA_DIR"/buildscripts/run_in_docker.sh /grpc-java/buildscripts/build_artifacts_in_docker.sh -# grpc-android and grpc-cronet require the Android SDK, so build outside of Docker and +# grpc-android, grpc-cronet and grpc-binder require the Android SDK, so build outside of Docker and # use --include-build for its grpc-core dependency echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3" LOCAL_MVN_TEMP=$(mktemp -d) @@ -28,6 +28,13 @@ pushd "$GRPC_JAVA_DIR/cronet" -PrepositoryDir="$LOCAL_MVN_TEMP" popd +pushd "$GRPC_JAVA_DIR/binder" +../gradlew publish \ + -Dorg.gradle.parallel=false \ + -PskipCodegen=true \ + -PrepositoryDir="$LOCAL_MVN_TEMP" +popd + readonly MVN_ARTIFACT_DIR="${MVN_ARTIFACT_DIR:-$GRPC_JAVA_DIR/mvn-artifacts}" mkdir -p "$MVN_ARTIFACT_DIR" cp -r "$LOCAL_MVN_TEMP"/* "$MVN_ARTIFACT_DIR"/ diff --git a/buildscripts/kokoro/upload_artifacts.sh b/buildscripts/kokoro/upload_artifacts.sh index 20e16c38a2f..06d037831ec 100644 --- a/buildscripts/kokoro/upload_artifacts.sh +++ b/buildscripts/kokoro/upload_artifacts.sh @@ -24,6 +24,9 @@ LOCAL_OTHER_ARTIFACTS="$KOKORO_GFILE_DIR"/github/grpc-java/artifacts/ # cronet artifact from linux job: [[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'grpc-cronet-*.aar' | wc -l)" != '0' ]] +# binder artifact from linux job: +[[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'grpc-binder-*.aar' | wc -l)" != '0' ]] + # from linux job: [[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'protoc-gen-grpc-java-*-linux-x86_64.exe' | wc -l)" != '0' ]] [[ "$(find "$LOCAL_MVN_ARTIFACTS" -type f -iname 'protoc-gen-grpc-java-*-linux-x86_32.exe' | wc -l)" != '0' ]] From a4334eb5c30c40419701835378b357fc0d2bcd27 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Mon, 29 Nov 2021 08:48:51 -0800 Subject: [PATCH 0016/2009] census: fix NPE in calling recordFinishedAttempt() (#8706) Fix the NPE as shown in the following stacktrace: ``` Caused by: java.lang.RuntimeException: java.lang.NullPointerException with message: null at io.grpc.census.CensusStatsModule$ClientTracer.recordFinishedAttempt(CensusStatsModule.java:388) ~[grpc-census-1.42.0.jar:1.42.0] at io.grpc.census.CensusStatsModule$CallAttemptsTracerFactory.recordFinishedCall(CensusStatsModule.java:525) ~[grpc-census-1.42.0.jar:1.42.0] at io.grpc.census.CensusStatsModule$CallAttemptsTracerFactory.attemptEnded(CensusStatsModule.java:492) ~[grpc-census-1.42.0.jar:1.42.0] at io.grpc.census.CensusStatsModule$ClientTracer.streamClosed(CensusStatsModule.java:345) ~[grpc-census-1.42.0.jar:1.42.0] at io.grpc.internal.StatsTraceContext.streamClosed(StatsTraceContext.java:155) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.closeListener(AbstractClientStream.java:458) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.access$400(AbstractClientStream.java:221) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState$1.run(AbstractClientStream.java:442) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.deframerClosed(AbstractClientStream.java:278) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.Http2ClientStreamTransportState.deframerClosed(Http2ClientStreamTransportState.java:31) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.MessageDeframer.close(MessageDeframer.java:233) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.MessageDeframer.closeWhenComplete(MessageDeframer.java:191) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractStream$TransportState.closeDeframer(AbstractStream.java:200) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.transportReportStatus(AbstractClientStream.java:445) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.transportReportStatus(AbstractClientStream.java:401) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.AbstractClientStream$TransportState.inboundTrailersReceived(AbstractClientStream.java:384) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.internal.Http2ClientStreamTransportState.transportTrailersReceived(Http2ClientStreamTransportState.java:183) ~[grpc-core-1.42.0.jar:1.42.0] at io.grpc.netty.shaded.io.grpc.netty.NettyClientStream$TransportState.transportHeadersReceived(NettyClientStream.java:334) ~[grpc-netty-shaded-1.42.0.jar:1.42.0] at io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler.onHeadersRead(NettyClientHandler.java:372) ~[grpc-netty-shaded-1.42.0.jar:1.42.0] at io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler.access$1200(NettyClientHandler.java:91) ~[grpc-netty-shaded-1.42.0.jar:1.42.0] at io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler$FrameListener.onHeadersRead(NettyClientHandler.java:934) ~[grpc-netty-shaded-1.42.0.jar:1.42.0] ``` The NPE can happen when `ClientCall.Listener.onClose()` and `StatsTraceContext.streamClosed()` (or `ClientStreamListener.closed()`) are invoked concurrently in different threads. Note that `CensusStatsModule$CallAttemptsTracerFactory.attemptEnded()` in the above stack trace would observe `callEnded==true` in such a race condition. The following are the possible scenarios that the race between `ClientCall.Listener.onClose()` and `ClientStreamListener.closed()` can happen: - Deadline exceeded but the underlying real stream is [not committed](https://github.com/grpc/grpc-java/blob/v1.42.0/core/src/main/java/io/grpc/internal/RetriableStream.java#L486-L495), the `ClientCall.Listener` may be closed earlier than the stream listener. (This is the case of the above stack trace, in which the inbound end-of-stream is received observing `callEnded==true`. Even if nothing inbound is received, there is still a chance that the NPE can happen.) - DelayedClientTransport.PendingStream has created a realStream but `setStream(realStream)` is [not called yet](https://github.com/grpc/grpc-java/blob/v1.42.0/core/src/main/java/io/grpc/internal/DelayedClientTransport.java#L366-L372), when deadline exceeded. (This has little chance to happen, only for the very first RPC on the channel.) - Hedging case. In deadline-exceeded cases, the shorter the deadline is, the more likely the race can happen. --- census/src/main/java/io/grpc/census/CensusStatsModule.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/census/src/main/java/io/grpc/census/CensusStatsModule.java b/census/src/main/java/io/grpc/census/CensusStatsModule.java index 4b2832c5989..487e49e5005 100644 --- a/census/src/main/java/io/grpc/census/CensusStatsModule.java +++ b/census/src/main/java/io/grpc/census/CensusStatsModule.java @@ -342,7 +342,6 @@ public void outboundMessage(int seqNo) { @Override public void streamClosed(Status status) { - attemptsState.attemptEnded(); stopwatch.stop(); roundtripNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS); Deadline deadline = info.getCallOptions().getDeadline(); @@ -355,6 +354,7 @@ public void streamClosed(Status status) { statusCode = Code.DEADLINE_EXCEEDED; } } + attemptsState.attemptEnded(); if (inboundReceivedOrClosed.compareAndSet(false, true)) { if (module.recordFinishedRpcs) { // Stream is closed early. So no need to record metrics for any inbound events after this @@ -522,6 +522,8 @@ void recordFinishedCall() { tracer.statusCode = status.getCode(); tracer.recordFinishedAttempt(); } else if (inboundMetricTracer != null) { + // activeStreams has been decremented to 0 by attemptEnded(), + // so inboundMetricTracer.statusCode is guaranteed to be assigned already. inboundMetricTracer.recordFinishedAttempt(); } if (!module.recordRetryMetrics) { From cb4b91418c34364b91ece9e9ca6fb5845abad1bf Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Mon, 29 Nov 2021 10:22:32 -0800 Subject: [PATCH 0017/2009] javadoc: update new API `@since` version (#8727) The @since version in commits 5a3b8e2 and a2398ce were missing and incorrect respectively. --- .../java/io/grpc/alts/GoogleDefaultChannelCredentials.java | 4 ++-- okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java index fe8c005da45..d9c2ddaaed7 100644 --- a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java +++ b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java @@ -50,7 +50,7 @@ public static ChannelCredentials create() { /** * Returns a new instance of {@link Builder}. * - * @since 1.42.0 + * @since 1.43.0 */ public static Builder newBuilder() { return new Builder(); @@ -59,7 +59,7 @@ public static Builder newBuilder() { /** * Builder for {@link GoogleDefaultChannelCredentials} instances. * - * @since 1.42.0 + * @since 1.43.0 */ public static final class Builder { private CallCredentials callCredentials; diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index b3e90d158fa..68ff6dbd787 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -413,6 +413,8 @@ public OkHttpChannelBuilder connectionSpec( * * @param tlsVersions List of tls versions. * @param cipherSuites List of cipher suites. + * + * @since 1.43.0 */ public OkHttpChannelBuilder tlsConnectionSpec( String[] tlsVersions, String[] cipherSuites) { From 2330922c3809b978f8eb08d14501553ed7f6fb5b Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Tue, 30 Nov 2021 08:36:20 -0800 Subject: [PATCH 0018/2009] rls: overhaul RouteLookupConfig validation (#8645) The `RlsProtoData.RouteLookupConfig` class is out-of-date. - Some of the fields were long, but now are of `Duration` type. - Some of the fields are deleted. - The validation of some of the fields either have been changed or were wrong since beginning. Now overhaul all the fields in `RlsProtoData.RouteLookupConfig` class based on the spec http://go/grpc-rls-lb-policy-design#heading=h.y3h669gfpown. Also move the validation logic in json parsing rather than in the constructor of `RouteLookupConfig`. --- .../java/io/grpc/rls/CachingRlsLbClient.java | 6 +- .../io/grpc/rls/RlsLoadBalancerProvider.java | 16 - .../java/io/grpc/rls/RlsProtoConverters.java | 120 ++++-- .../main/java/io/grpc/rls/RlsProtoData.java | 142 ++---- .../java/io/grpc/rls/RlsRequestFactory.java | 6 - .../io/grpc/rls/CachingRlsLbClientTest.java | 15 +- .../java/io/grpc/rls/RlsLoadBalancerTest.java | 8 +- .../io/grpc/rls/RlsProtoConvertersTest.java | 408 +++++++++++++++++- .../java/io/grpc/rls/RlsProtoDataTest.java | 56 --- .../io/grpc/rls/RlsRequestFactoryTest.java | 37 +- 10 files changed, 527 insertions(+), 287 deletions(-) delete mode 100644 rls/src/test/java/io/grpc/rls/RlsProtoDataTest.java diff --git a/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java b/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java index 87d01360f49..7bd9f4b68e3 100644 --- a/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java +++ b/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java @@ -128,9 +128,9 @@ private CachingRlsLbClient(Builder builder) { synchronizationContext = helper.getSynchronizationContext(); lbPolicyConfig = checkNotNull(builder.lbPolicyConfig, "lbPolicyConfig"); RouteLookupConfig rlsConfig = lbPolicyConfig.getRouteLookupConfig(); - maxAgeNanos = TimeUnit.MILLISECONDS.toNanos(rlsConfig.getMaxAgeInMillis()); - staleAgeNanos = TimeUnit.MILLISECONDS.toNanos(rlsConfig.getStaleAgeInMillis()); - callTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(rlsConfig.getLookupServiceTimeoutInMillis()); + maxAgeNanos = rlsConfig.getMaxAgeInNanos(); + staleAgeNanos = rlsConfig.getStaleAgeInNanos(); + callTimeoutNanos = rlsConfig.getLookupServiceTimeoutInNanos(); timeProvider = checkNotNull(builder.timeProvider, "timeProvider"); throttler = checkNotNull(builder.throttler, "throttler"); linkedHashLruCache = diff --git a/rls/src/main/java/io/grpc/rls/RlsLoadBalancerProvider.java b/rls/src/main/java/io/grpc/rls/RlsLoadBalancerProvider.java index ca1ed714e82..3755fe3f77c 100644 --- a/rls/src/main/java/io/grpc/rls/RlsLoadBalancerProvider.java +++ b/rls/src/main/java/io/grpc/rls/RlsLoadBalancerProvider.java @@ -67,22 +67,6 @@ public ConfigOrError parseLoadBalancingPolicyConfig(Map rawLoadBalanc JsonUtil.getString(rawLoadBalancingConfigPolicy, "childPolicyConfigTargetFieldName"), JsonUtil.checkObjectList( checkNotNull(JsonUtil.getList(rawLoadBalancingConfigPolicy, "childPolicy")))); - // Checking all valid targets to make sure the config is always valid. This strict check - // prevents child policy to handle invalid child policy. - for (String validTarget : routeLookupConfig.getValidTargets()) { - ConfigOrError childPolicyConfigOrError = - lbPolicy - .getEffectiveLbProvider() - .parseLoadBalancingPolicyConfig(lbPolicy.getEffectiveChildPolicy(validTarget)); - if (childPolicyConfigOrError.getError() != null) { - return - ConfigOrError.fromError( - childPolicyConfigOrError - .getError() - .augmentDescription( - "failed to parse childPolicy for validTarget: " + validTarget)); - } - } return ConfigOrError.fromConfig(new LbPolicyConfiguration(routeLookupConfig, lbPolicy)); } catch (Exception e) { return ConfigOrError.fromError( diff --git a/rls/src/main/java/io/grpc/rls/RlsProtoConverters.java b/rls/src/main/java/io/grpc/rls/RlsProtoConverters.java index ce89def4467..b4d3fcc3b29 100644 --- a/rls/src/main/java/io/grpc/rls/RlsProtoConverters.java +++ b/rls/src/main/java/io/grpc/rls/RlsProtoConverters.java @@ -18,8 +18,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; import com.google.common.base.Converter; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.grpc.internal.JsonUtil; import io.grpc.lookup.v1.RouteLookupRequest; @@ -29,10 +33,13 @@ import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.RouteLookupConfig; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; +import java.util.Set; import javax.annotation.Nullable; /** @@ -41,6 +48,12 @@ */ final class RlsProtoConverters { + private static final long MAX_AGE_NANOS = MINUTES.toNanos(5); + private static final long MAX_CACHE_SIZE = 5 * 1024 * 1024; // 5MiB + private static final long DEFAULT_LOOKUP_SERVICE_TIMEOUT = SECONDS.toNanos(10); + private static final ImmutableList EXTRA_KEY_NAMES = + ImmutableList.of("host", "service", "method"); + /** * RouteLookupRequestConverter converts between {@link RouteLookupRequest} and {@link * RlsProtoData.RouteLookupRequest}. @@ -96,31 +109,49 @@ static final class RouteLookupConfigConverter @Override protected RouteLookupConfig doForward(Map json) { List grpcKeyBuilders = - GrpcKeyBuilderConverter - .covertAll(JsonUtil.checkObjectList(JsonUtil.getList(json, "grpcKeyBuilders"))); + GrpcKeyBuilderConverter.covertAll( + checkNotNull(JsonUtil.getListOfObjects(json, "grpcKeyBuilders"), "grpcKeyBuilders")); + checkArgument(!grpcKeyBuilders.isEmpty(), "must have at least one GrpcKeyBuilder"); + Set names = new HashSet<>(); + for (GrpcKeyBuilder keyBuilder : grpcKeyBuilders) { + for (Name name : keyBuilder.getNames()) { + checkArgument(names.add(name), "duplicate names in grpc_keybuilders: " + name); + } + } String lookupService = JsonUtil.getString(json, "lookupService"); - long timeout = - TimeUnit.SECONDS.toMillis( - orDefault( - JsonUtil.getNumberAsLong(json, "lookupServiceTimeout"), - 0L)); - Long maxAge = - convertTimeIfNotNull( - TimeUnit.SECONDS, TimeUnit.MILLISECONDS, JsonUtil.getNumberAsLong(json, "maxAge")); - Long staleAge = - convertTimeIfNotNull( - TimeUnit.SECONDS, TimeUnit.MILLISECONDS, JsonUtil.getNumberAsLong(json, "staleAge")); - long cacheSize = orDefault(JsonUtil.getNumberAsLong(json, "cacheSizeBytes"), Long.MAX_VALUE); - List validTargets = JsonUtil.checkStringList(JsonUtil.getList(json, "validTargets")); - String defaultTarget = JsonUtil.getString(json, "defaultTarget"); + checkArgument(!Strings.isNullOrEmpty(lookupService), "lookupService must not be empty"); + try { + new URI(lookupService); + } catch (URISyntaxException e) { + throw new IllegalArgumentException( + "The lookupService field is not valid URI: " + lookupService, e); + } + long timeout = orDefault( + JsonUtil.getStringAsDuration(json, "lookupServiceTimeout"), + DEFAULT_LOOKUP_SERVICE_TIMEOUT); + checkArgument(timeout > 0, "lookupServiceTimeout should be positive"); + Long maxAge = JsonUtil.getStringAsDuration(json, "maxAge"); + Long staleAge = JsonUtil.getStringAsDuration(json, "staleAge"); + if (maxAge == null) { + checkArgument(staleAge == null, "to specify staleAge, must have maxAge"); + maxAge = MAX_AGE_NANOS; + } + if (staleAge == null) { + staleAge = MAX_AGE_NANOS; + } + maxAge = Math.min(maxAge, MAX_AGE_NANOS); + staleAge = Math.min(staleAge, maxAge); + long cacheSize = orDefault(JsonUtil.getNumberAsLong(json, "cacheSizeBytes"), MAX_CACHE_SIZE); + checkArgument(cacheSize > 0, "cacheSize must be positive"); + cacheSize = Math.min(cacheSize, MAX_CACHE_SIZE); + String defaultTarget = Strings.emptyToNull(JsonUtil.getString(json, "defaultTarget")); return new RouteLookupConfig( grpcKeyBuilders, lookupService, - /* lookupServiceTimeoutInMillis= */ timeout, - /* maxAgeInMillis= */ maxAge, - /* staleAgeInMillis= */ staleAge, + /* lookupServiceTimeoutInNanos= */ timeout, + /* maxAgeInNanos= */ maxAge, + /* staleAgeInNanos= */ staleAge, /* cacheSizeBytes= */ cacheSize, - validTargets, defaultTarget); } @@ -131,13 +162,6 @@ private static T orDefault(@Nullable T value, T defaultValue) { return value; } - private static Long convertTimeIfNotNull(TimeUnit from, TimeUnit to, Long value) { - if (value == null) { - return null; - } - return to.convert(value, from); - } - @Override protected Map doBackward(RouteLookupConfig routeLookupConfig) { throw new UnsupportedOperationException(); @@ -155,25 +179,29 @@ public static List covertAll(List> keyBuilders) { @SuppressWarnings("unchecked") static GrpcKeyBuilder convert(Map keyBuilder) { - List> rawNames = - JsonUtil.checkObjectList(JsonUtil.getList(keyBuilder, "names")); + List rawRawNames = JsonUtil.getList(keyBuilder, "names"); + checkArgument( + rawRawNames != null && !rawRawNames.isEmpty(), + "each keyBuilder must have at least one name"); + List> rawNames = JsonUtil.checkObjectList(rawRawNames); List names = new ArrayList<>(); for (Map rawName : rawNames) { - names.add( - new Name( - JsonUtil.getString(rawName, "service"), JsonUtil.getString(rawName, "method"))); + String serviceName = JsonUtil.getString(rawName, "service"); + checkArgument(!Strings.isNullOrEmpty(serviceName), "service must not be empty or null"); + names.add(new Name(serviceName, JsonUtil.getString(rawName, "method"))); } + List rawRawHeaders = JsonUtil.getList(keyBuilder, "headers"); List> rawHeaders = - JsonUtil.checkObjectList(JsonUtil.getList(keyBuilder, "headers")); + rawRawHeaders == null + ? new ArrayList>() : JsonUtil.checkObjectList(rawRawHeaders); List nameMatchers = new ArrayList<>(); for (Map rawHeader : rawHeaders) { - NameMatcher matcher = - new NameMatcher( - JsonUtil.getString(rawHeader, "key"), - (List) rawHeader.get("names"), - (Boolean) rawHeader.get("optional")); + Boolean requiredMatch = JsonUtil.getBoolean(rawHeader, "requiredMatch"); checkArgument( - matcher.isOptional(), "NameMatcher for GrpcKeyBuilders shouldn't be required"); + requiredMatch == null || !requiredMatch, + "requiredMatch shouldn't be specified for gRPC"); + NameMatcher matcher = new NameMatcher( + JsonUtil.getString(rawHeader, "key"), (List) rawHeader.get("names")); nameMatchers.add(matcher); } ExtraKeys extraKeys = ExtraKeys.DEFAULT; @@ -188,9 +216,21 @@ static GrpcKeyBuilder convert(Map keyBuilder) { if (constantKeys == null) { constantKeys = ImmutableMap.of(); } + checkUniqueKey(nameMatchers, constantKeys.keySet()); return new GrpcKeyBuilder(names, nameMatchers, extraKeys, constantKeys); } } + private static void checkUniqueKey(List nameMatchers, Set constantKeys) { + Set keys = new HashSet<>(constantKeys); + keys.addAll(EXTRA_KEY_NAMES); + for (NameMatcher nameMatcher : nameMatchers) { + keys.add(nameMatcher.getKey()); + } + if (keys.size() != nameMatchers.size() + constantKeys.size() + EXTRA_KEY_NAMES.size()) { + throw new IllegalArgumentException("keys in KeyBuilder must be unique"); + } + } + private RlsProtoConverters() {} } diff --git a/rls/src/main/java/io/grpc/rls/RlsProtoData.java b/rls/src/main/java/io/grpc/rls/RlsProtoData.java index 32dc81829b3..4709894833c 100644 --- a/rls/src/main/java/io/grpc/rls/RlsProtoData.java +++ b/rls/src/main/java/io/grpc/rls/RlsProtoData.java @@ -16,7 +16,6 @@ package io.grpc.rls; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -25,12 +24,8 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -142,66 +137,36 @@ public String toString() { @Immutable static final class RouteLookupConfig { - private static final long MAX_AGE_MILLIS = TimeUnit.MINUTES.toMillis(5); - private static final long MAX_CACHE_SIZE = 5 * 1024 * 1024; - private final ImmutableList grpcKeyBuilders; private final String lookupService; - private final long lookupServiceTimeoutInMillis; + private final long lookupServiceTimeoutInNanos; - private final long maxAgeInMillis; + private final long maxAgeInNanos; - private final long staleAgeInMillis; + private final long staleAgeInNanos; private final long cacheSizeBytes; - private final ImmutableList validTargets; - @Nullable private final String defaultTarget; RouteLookupConfig( List grpcKeyBuilders, String lookupService, - long lookupServiceTimeoutInMillis, - @Nullable Long maxAgeInMillis, - @Nullable Long staleAgeInMillis, + long lookupServiceTimeoutInNanos, + long maxAgeInNanos, + long staleAgeInNanos, long cacheSizeBytes, - List validTargets, @Nullable String defaultTarget) { - checkState( - !checkNotNull(grpcKeyBuilders, "grpcKeyBuilders").isEmpty(), - "must have at least one GrpcKeyBuilder"); - checkUniqueName(grpcKeyBuilders); this.grpcKeyBuilders = ImmutableList.copyOf(grpcKeyBuilders); - // TODO(creamsoup) also check if it is URI - checkState( - lookupService != null && !lookupService.isEmpty(), "lookupService must not be empty"); this.lookupService = lookupService; - checkState( - lookupServiceTimeoutInMillis > 0, "lookupServiceTimeoutInMillis should be positive"); - this.lookupServiceTimeoutInMillis = lookupServiceTimeoutInMillis; - if (maxAgeInMillis == null) { - checkState( - staleAgeInMillis == null, "To specify staleAgeInMillis, must have maxAgeInMillis"); - } - if (maxAgeInMillis == null || maxAgeInMillis == 0) { - maxAgeInMillis = MAX_AGE_MILLIS; - } - if (staleAgeInMillis == null || staleAgeInMillis == 0) { - staleAgeInMillis = MAX_AGE_MILLIS; - } - this.maxAgeInMillis = Math.min(maxAgeInMillis, MAX_AGE_MILLIS); - this.staleAgeInMillis = Math.min(staleAgeInMillis, this.maxAgeInMillis); - checkArgument(cacheSizeBytes > 0, "cacheSize must be positive"); - this.cacheSizeBytes = Math.min(cacheSizeBytes, MAX_CACHE_SIZE); - this.validTargets = ImmutableList.copyOf(checkNotNull(validTargets, "validTargets")); - if (defaultTarget != null && defaultTarget.isEmpty()) { - defaultTarget = null; - } + this.lookupServiceTimeoutInNanos = lookupServiceTimeoutInNanos; + this.maxAgeInNanos = maxAgeInNanos; + this.staleAgeInNanos = staleAgeInNanos; + this.cacheSizeBytes = cacheSizeBytes; this.defaultTarget = defaultTarget; } @@ -224,22 +189,22 @@ String getLookupService() { } /** Returns the timeout value for lookup service requests. */ - long getLookupServiceTimeoutInMillis() { - return lookupServiceTimeoutInMillis; + long getLookupServiceTimeoutInNanos() { + return lookupServiceTimeoutInNanos; } /** Returns the maximum age the result will be cached. */ - long getMaxAgeInMillis() { - return maxAgeInMillis; + long getMaxAgeInNanos() { + return maxAgeInNanos; } /** * Returns the time when an entry will be in a staled status. When cache is accessed whgen the * entry is in staled status, it will */ - long getStaleAgeInMillis() { - return staleAgeInMillis; + long getStaleAgeInNanos() { + return staleAgeInNanos; } /** @@ -252,15 +217,6 @@ long getCacheSizeBytes() { return cacheSizeBytes; } - /** - * Returns the list of all the possible targets that can be returned by the lookup service. If - * a target not on this list is returned, it will be treated the same as an RPC error from the - * RLS. - */ - ImmutableList getValidTargets() { - return validTargets; - } - /** * Returns the default target to use if needed. If nonempty (implies request processing * strategy SYNC_LOOKUP_DEFAULT_TARGET_ON_ERROR is set), it will be used if RLS returns an @@ -281,9 +237,9 @@ public boolean equals(Object o) { return false; } RouteLookupConfig that = (RouteLookupConfig) o; - return lookupServiceTimeoutInMillis == that.lookupServiceTimeoutInMillis - && maxAgeInMillis == that.maxAgeInMillis - && staleAgeInMillis == that.staleAgeInMillis + return lookupServiceTimeoutInNanos == that.lookupServiceTimeoutInNanos + && maxAgeInNanos == that.maxAgeInNanos + && staleAgeInNanos == that.staleAgeInNanos && cacheSizeBytes == that.cacheSizeBytes && Objects.equal(grpcKeyBuilders, that.grpcKeyBuilders) && Objects.equal(lookupService, that.lookupService) @@ -295,9 +251,9 @@ public int hashCode() { return Objects.hashCode( grpcKeyBuilders, lookupService, - lookupServiceTimeoutInMillis, - maxAgeInMillis, - staleAgeInMillis, + lookupServiceTimeoutInNanos, + maxAgeInNanos, + staleAgeInNanos, cacheSizeBytes, defaultTarget); } @@ -307,26 +263,15 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("grpcKeyBuilders", grpcKeyBuilders) .add("lookupService", lookupService) - .add("lookupServiceTimeoutInMillis", lookupServiceTimeoutInMillis) - .add("maxAgeInMillis", maxAgeInMillis) - .add("staleAgeInMillis", staleAgeInMillis) + .add("lookupServiceTimeoutInNanos", lookupServiceTimeoutInNanos) + .add("maxAgeInNanos", maxAgeInNanos) + .add("staleAgeInNanos", staleAgeInNanos) .add("cacheSize", cacheSizeBytes) .add("defaultTarget", defaultTarget) .toString(); } } - private static void checkUniqueName(List grpcKeyBuilders) { - Set names = new HashSet<>(); - for (GrpcKeyBuilder grpcKeyBuilder : grpcKeyBuilders) { - int prevSize = names.size(); - names.addAll(grpcKeyBuilder.getNames()); - if (names.size() != prevSize + grpcKeyBuilder.getNames().size()) { - throw new IllegalStateException("Names in the GrpcKeyBuilders should be unique"); - } - } - } - /** * NameMatcher extract a key based on a given name (e.g. header name or query parameter name). * The name must match one of the names listed in the "name" field. If the "required_match" field @@ -339,12 +284,9 @@ static final class NameMatcher { private final ImmutableList names; - private final boolean optional; - - NameMatcher(String key, List names, @Nullable Boolean optional) { + NameMatcher(String key, List names) { this.key = checkNotNull(key, "key"); this.names = ImmutableList.copyOf(checkNotNull(names, "names")); - this.optional = optional != null ? optional : true; } /** The name that will be used in the RLS key_map to refer to this value. */ @@ -357,13 +299,6 @@ ImmutableList names() { return names; } - /** - * Indicates if this extraction optional. A key builder will still match if no value is found. - */ - boolean isOptional() { - return optional; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -373,14 +308,13 @@ public boolean equals(Object o) { return false; } NameMatcher matcher = (NameMatcher) o; - return optional == matcher.optional - && java.util.Objects.equals(key, matcher.key) + return java.util.Objects.equals(key, matcher.key) && java.util.Objects.equals(names, matcher.names); } @Override public int hashCode() { - return java.util.Objects.hash(key, names, optional); + return java.util.Objects.hash(key, names); } @Override @@ -388,7 +322,6 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("key", key) .add("names", names) - .add("optional", optional) .toString(); } } @@ -408,19 +341,11 @@ static final class GrpcKeyBuilder { Map constantKeys) { checkState(names != null && !names.isEmpty(), "names cannot be empty"); this.names = ImmutableList.copyOf(names); - checkUniqueKey(checkNotNull(headers, "headers")); this.headers = ImmutableList.copyOf(headers); this.extraKeys = checkNotNull(extraKeys, "extraKeys"); this.constantKeys = ImmutableMap.copyOf(checkNotNull(constantKeys, "constantKeys")); } - private static void checkUniqueKey(List headers) { - Set names = new HashSet<>(); - for (NameMatcher header : headers) { - checkState(names.add(header.key), "key in headers must be unique"); - } - } - /** * Returns names. To match, one of the given Name fields must match; the service and method * fields are specified as fixed strings. The service name is required and includes the proto @@ -486,17 +411,11 @@ static final class Name { private final String service; + @Nullable private final String method; - public Name(String service) { - this(service, "*"); - } - /** The primary constructor. */ - Name(String service, String method) { - checkState( - !checkNotNull(service, "service").isEmpty(), - "service must not be empty or null"); + Name(String service, @Nullable String method) { this.service = service; this.method = method; } @@ -505,6 +424,7 @@ String getService() { return service; } + @Nullable String getMethod() { return method; } diff --git a/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java b/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java index e181d64833d..d3aecabd034 100644 --- a/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java +++ b/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java @@ -21,8 +21,6 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; import io.grpc.Metadata; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; import io.grpc.rls.RlsProtoData.ExtraKeys; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; @@ -107,10 +105,6 @@ private Map createRequestHeaders( } if (value != null) { rlsRequestHeaders.put(nameMatcher.getKey(), value); - } else if (!nameMatcher.isOptional()) { - throw new StatusRuntimeException( - Status.INVALID_ARGUMENT.withDescription( - String.format("Missing mandatory metadata(%s) not found", nameMatcher.getKey()))); } } return rlsRequestHeaders; diff --git a/rls/src/test/java/io/grpc/rls/CachingRlsLbClientTest.java b/rls/src/test/java/io/grpc/rls/CachingRlsLbClientTest.java index aa64ec890b6..c8222a02b8a 100644 --- a/rls/src/test/java/io/grpc/rls/CachingRlsLbClientTest.java +++ b/rls/src/test/java/io/grpc/rls/CachingRlsLbClientTest.java @@ -210,7 +210,7 @@ public void get_noError_lifeCycle() throws Exception { assertThat(resp.hasData()).isTrue(); // cache hit for staled entry - fakeTimeProvider.forwardTime(ROUTE_LOOKUP_CONFIG.getStaleAgeInMillis(), TimeUnit.MILLISECONDS); + fakeTimeProvider.forwardTime(ROUTE_LOOKUP_CONFIG.getStaleAgeInNanos(), TimeUnit.NANOSECONDS); resp = getInSyncContext(routeLookupRequest); assertThat(resp.hasData()).isTrue(); @@ -226,7 +226,7 @@ public void get_noError_lifeCycle() throws Exception { assertThat(resp.hasData()).isTrue(); // existing cache expired - fakeTimeProvider.forwardTime(ROUTE_LOOKUP_CONFIG.getMaxAgeInMillis(), TimeUnit.MILLISECONDS); + fakeTimeProvider.forwardTime(ROUTE_LOOKUP_CONFIG.getMaxAgeInNanos(), TimeUnit.NANOSECONDS); resp = getInSyncContext(routeLookupRequest); @@ -423,16 +423,15 @@ private static RouteLookupConfig getRouteLookupConfig() { new GrpcKeyBuilder( ImmutableList.of(new Name("service1", "create")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("id", ImmutableList.of("X-Google-Id"))), ExtraKeys.create("server", "service-key", "method-key"), ImmutableMap.of())), /* lookupService= */ "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), - /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), - /* staleAgeInMillis= */ TimeUnit.SECONDS.toMillis(240), + /* lookupServiceTimeoutInNanos= */ TimeUnit.SECONDS.toNanos(2), + /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), + /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(240), /* cacheSizeBytes= */ 1000, - /* validTargets= */ ImmutableList.of("a valid target"), DEFAULT_TARGET); } diff --git a/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java b/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java index fba295f98f0..bf0bc47fcc4 100644 --- a/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java @@ -420,11 +420,11 @@ private String getRlsConfigJsonStr() { + " }\n" + " ],\n" + " \"lookupService\": \"localhost:8972\",\n" - + " \"lookupServiceTimeout\": 2,\n" - + " \"maxAge\": 300,\n" - + " \"staleAge\": 240,\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"maxAge\": \"300s\",\n" + + " \"staleAge\": \"240s\",\n" + " \"validTargets\": [\"localhost:9001\", \"localhost:9002\"]," - + " \"cacheSizeBytes\": 1000,\n" + + " \"cacheSizeBytes\": \"1000\",\n" + " \"defaultTarget\": \"" + defaultTarget + "\",\n" + " \"requestProcessingStrategy\": \"SYNC_LOOKUP_DEFAULT_TARGET_ON_ERROR\"\n" + "}"; diff --git a/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java b/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java index bfb331e6cc8..5d1dcc1cadb 100644 --- a/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java @@ -17,6 +17,7 @@ package io.grpc.rls; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; import com.google.common.base.Converter; import com.google.common.collect.ImmutableList; @@ -166,11 +167,11 @@ public void convert_jsonRlsConfig() throws IOException { + " }\n" + " ],\n" + " \"lookupService\": \"service1\",\n" - + " \"lookupServiceTimeout\": 2,\n" - + " \"maxAge\": 300,\n" - + " \"staleAge\": 240,\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"maxAge\": \"300s\",\n" + + " \"staleAge\": \"240s\",\n" + " \"validTargets\": [\"a valid target\"]," - + " \"cacheSizeBytes\": 1000,\n" + + " \"cacheSizeBytes\": \"1000\",\n" + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + "}"; @@ -180,29 +181,28 @@ public void convert_jsonRlsConfig() throws IOException { new GrpcKeyBuilder( ImmutableList.of(new Name("service1", "create")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("id", ImmutableList.of("X-Google-Id"))), ExtraKeys.DEFAULT, ImmutableMap.of()), new GrpcKeyBuilder( - ImmutableList.of(new Name("service1")), + ImmutableList.of(new Name("service1", "*")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("password", ImmutableList.of("Password"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("password", ImmutableList.of("Password"))), ExtraKeys.DEFAULT, ImmutableMap.of()), new GrpcKeyBuilder( - ImmutableList.of(new Name("service3")), + ImmutableList.of(new Name("service3", "*")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent"))), ExtraKeys.create("host-key", "service-key", "method-key"), ImmutableMap.of("constKey1", "value1"))), /* lookupService= */ "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), - /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), - /* staleAgeInMillis= */ TimeUnit.SECONDS.toMillis(240), + /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(2), + /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), + /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(240), /* cacheSizeBytes= */ 1000, - /* validTargets= */ ImmutableList.of("a valid target"), /* defaultTarget= */ "us_east_1.cloudbigtable.googleapis.com"); RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); @@ -211,4 +211,382 @@ public void convert_jsonRlsConfig() throws IOException { RouteLookupConfig converted = converter.convert(parsedJson); assertThat(converted).isEqualTo(expectedConfig); } + + @Test + public void convert_jsonRlsConfig_emptyKeyBuilders() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"maxAge\": \"300s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat().contains("must have at least one GrpcKeyBuilder"); + } + } + + @Test + public void convert_jsonRlsConfig_namesNotUnique() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\",\n" + + " \"method\": \"create\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\",\n" + + " \"method\": \"create\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"password\"," + + " \"names\": [\"Password\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service3\",\n" + + " \"method\": \"*\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ],\n" + + " \"extraKeys\": {\n" + + " \"host\": \"host-key\",\n" + + " \"service\": \"service-key\",\n" + + " \"method\": \"method-key\"\n" + + " }, \n" + + " \"constantKeys\": {\n" + + " \"constKey1\": \"value1\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"maxAge\": \"300s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat() + .contains("duplicate names in grpc_keybuilders: Name{service=service1, method=create}"); + } + } + + @Test + public void convert_jsonRlsConfig_defaultValues() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfig expectedConfig = + new RouteLookupConfig( + ImmutableList.of( + new GrpcKeyBuilder( + ImmutableList.of(new Name("service1", null)), + ImmutableList.of(), + ExtraKeys.DEFAULT, + ImmutableMap.of())), + /* lookupService= */ "service1", + /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(10), + /* maxAgeInNanos= */ TimeUnit.MINUTES.toNanos(5), + /* staleAgeInNanos= */ TimeUnit.MINUTES.toNanos(5), + /* cacheSizeBytes= */ 5 * 1024 * 1024, + /* defaultTarget= */ "us_east_1.cloudbigtable.googleapis.com"); + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + RouteLookupConfig converted = converter.convert(parsedJson); + assertThat(converted).isEqualTo(expectedConfig); + } + + @Test + public void convert_jsonRlsConfig_staleAgeCappedByMaxAge() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\",\n" + + " \"method\": \"create\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"maxAge\": \"300s\",\n" + + " \"staleAge\": \"400s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfig expectedConfig = + new RouteLookupConfig( + ImmutableList.of( + new GrpcKeyBuilder( + ImmutableList.of(new Name("service1", "create")), + ImmutableList.of( + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("id", ImmutableList.of("X-Google-Id"))), + ExtraKeys.DEFAULT, + ImmutableMap.of())), + /* lookupService= */ "service1", + /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(2), + /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), + /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), + /* cacheSizeBytes= */ 1000, + /* defaultTarget= */ "us_east_1.cloudbigtable.googleapis.com"); + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + RouteLookupConfig converted = converter.convert(parsedJson); + assertThat(converted).isEqualTo(expectedConfig); + } + + @Test + public void convert_jsonRlsConfig_staleAgeGivenWithoutMaxAge() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\",\n" + + " \"method\": \"create\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat().contains("to specify staleAge, must have maxAge"); + } + } + + @Test + public void convert_jsonRlsConfig_keyBuilderWithoutName() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat().contains("each keyBuilder must have at least one name"); + } + } + + @Test + public void convert_jsonRlsConfig_nameWithoutService() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"method\": \"create\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"user\"," + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat().contains("service must not be empty or null"); + } + } + + @Test + public void convert_jsonRlsConfig_keysNotUnique() throws IOException { + String jsonStr = "{\n" + + " \"grpcKeyBuilders\": [\n" + + " {\n" + + " \"names\": [\n" + + " {\n" + + " \"service\": \"service1\"\n" + + " }\n" + + " ],\n" + + " \"headers\": [\n" + + " {\n" + + " \"key\": \"service\"," // duplicate to extra_keys + + " \"names\": [\"User\", \"Parent\"],\n" + + " \"optional\": true\n" + + " },\n" + + " {\n" + + " \"key\": \"id\"," + + " \"names\": [\"X-Google-Id\"],\n" + + " \"optional\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"lookupService\": \"service1\",\n" + + " \"lookupServiceTimeout\": \"2s\",\n" + + " \"staleAge\": \"240s\",\n" + + " \"validTargets\": [\"a valid target\"]," + + " \"cacheSizeBytes\": \"1000\",\n" + + " \"defaultTarget\": \"us_east_1.cloudbigtable.googleapis.com\"\n" + + "}"; + + RouteLookupConfigConverter converter = new RouteLookupConfigConverter(); + @SuppressWarnings("unchecked") + Map parsedJson = (Map) JsonParser.parse(jsonStr); + try { + converter.convert(parsedJson); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageThat().contains("keys in KeyBuilder must be unique"); + } + } } diff --git a/rls/src/test/java/io/grpc/rls/RlsProtoDataTest.java b/rls/src/test/java/io/grpc/rls/RlsProtoDataTest.java deleted file mode 100644 index 9cfb6c753fb..00000000000 --- a/rls/src/test/java/io/grpc/rls/RlsProtoDataTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021 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.rls; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.grpc.rls.RlsProtoData.ExtraKeys; -import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; -import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; -import io.grpc.rls.RlsProtoData.NameMatcher; -import io.grpc.rls.RlsProtoData.RouteLookupConfig; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link RlsProtoData}. */ -@RunWith(JUnit4.class) -public class RlsProtoDataTest { - @Test - public void maxCacheSize() { - RouteLookupConfig config = new RouteLookupConfig( - ImmutableList.of( - new GrpcKeyBuilder( - ImmutableList.of(new Name("service1", "create")), - ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)), - ExtraKeys.create("server", "service-key", "method-key"), - ImmutableMap.of())), - "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), - /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), - /* staleAgeInMillis= */ TimeUnit.SECONDS.toMillis(240), - /* cacheSizeBytes= */ 20 * 1000 * 1000, - ImmutableList.of("a-valid-target"), - "default-target"); - assertThat(config.getCacheSizeBytes()).isEqualTo(5 * 1024 * 1024); - } -} diff --git a/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java b/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java index b0d197ff525..0d834601279 100644 --- a/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java @@ -17,13 +17,10 @@ package io.grpc.rls; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.grpc.Metadata; -import io.grpc.Status.Code; -import io.grpc.StatusRuntimeException; import io.grpc.rls.RlsProtoData.ExtraKeys; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; @@ -44,28 +41,27 @@ public class RlsRequestFactoryTest { new GrpcKeyBuilder( ImmutableList.of(new Name("com.google.service1", "Create")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("id", ImmutableList.of("X-Google-Id"))), ExtraKeys.create("server-1", null, null), ImmutableMap.of("const-key-1", "const-value-1")), new GrpcKeyBuilder( - ImmutableList.of(new Name("com.google.service1")), + ImmutableList.of(new Name("com.google.service1", "*")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true), - new NameMatcher("password", ImmutableList.of("Password"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent")), + new NameMatcher("password", ImmutableList.of("Password"))), ExtraKeys.create(null, "service-2", null), ImmutableMap.of("const-key-2", "const-value-2")), new GrpcKeyBuilder( - ImmutableList.of(new Name("com.google.service2")), + ImmutableList.of(new Name("com.google.service2", "*")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), false), - new NameMatcher("password", ImmutableList.of("Password"), true)), + new NameMatcher("password", ImmutableList.of("Password"))), ExtraKeys.create(null, "service-3", "method-3"), ImmutableMap.of()), new GrpcKeyBuilder( - ImmutableList.of(new Name("com.google.service3")), + ImmutableList.of(new Name("com.google.service3", "*")), ImmutableList.of( - new NameMatcher("user", ImmutableList.of("User", "Parent"), true)), + new NameMatcher("user", ImmutableList.of("User", "Parent"))), ExtraKeys.create(null, null, null), ImmutableMap.of("const-key-4", "const-value-4"))), /* lookupService= */ "bigtable-rls.googleapis.com", @@ -73,7 +69,6 @@ public class RlsRequestFactoryTest { /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), /* staleAgeInMillis= */ TimeUnit.SECONDS.toMillis(240), /* cacheSizeBytes= */ 1000, - /* validTargets= */ ImmutableList.of("a valid target"), /* defaultTarget= */ "us_east_1.cloudbigtable.googleapis.com"); private final RlsRequestFactory factory = new RlsRequestFactory( @@ -94,20 +89,6 @@ public void create_pathMatches() { "const-key-1", "const-value-1"); } - @Test - public void create_missingRequiredHeader() { - Metadata metadata = new Metadata(); - - try { - RouteLookupRequest unused = factory.create("com.google.service2", "Create", metadata); - fail(); - } catch (StatusRuntimeException e) { - assertThat(e.getStatus().getCode()).isEqualTo(Code.INVALID_ARGUMENT); - assertThat(e.getStatus().getDescription()) - .isEqualTo("Missing mandatory metadata(user) not found"); - } - } - @Test public void create_pathFallbackMatches() { Metadata metadata = new Metadata(); From 65c00cf24e9764335484614e3d41733e70c6d6df Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Tue, 30 Nov 2021 11:53:56 -0800 Subject: [PATCH 0019/2009] Start 1.44.0 development cycle (#8729) --- build.gradle | 2 +- .../src/test/golden/TestDeprecatedService.java.txt | 2 +- compiler/src/test/golden/TestService.java.txt | 2 +- .../src/testLite/golden/TestDeprecatedService.java.txt | 2 +- compiler/src/testLite/golden/TestService.java.txt | 2 +- core/src/main/java/io/grpc/internal/GrpcUtil.java | 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-gauth/build.gradle | 2 +- examples/example-gauth/pom.xml | 4 ++-- 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-tls/build.gradle | 2 +- examples/example-tls/pom.xml | 4 ++-- examples/example-xds/build.gradle | 2 +- examples/pom.xml | 4 ++-- 22 files changed, 40 insertions(+), 40 deletions(-) diff --git a/build.gradle b/build.gradle index 9d9e991bca5..9aab8312c5c 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.43.0-SNAPSHOT" // CURRENT_GRPC_VERSION + version = "1.44.0-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 98dcbf87587..68d8e1172a3 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.43.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.44.0-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 49938bd9345..3c6cdc82b51 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.43.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.44.0-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated public final class TestServiceGrpc { diff --git a/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt index fdd980a554e..8dcafe51f24 100644 --- a/compiler/src/testLite/golden/TestDeprecatedService.java.txt +++ b/compiler/src/testLite/golden/TestDeprecatedService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.43.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.44.0-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated @java.lang.Deprecated diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt index e13628ac66f..60ac085f920 100644 --- a/compiler/src/testLite/golden/TestService.java.txt +++ b/compiler/src/testLite/golden/TestService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.43.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.44.0-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 6a7b93baf06..635fab11c8f 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -205,7 +205,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - private static final String IMPLEMENTATION_VERSION = "1.43.0-SNAPSHOT"; // CURRENT_GRPC_VERSION + private static final String IMPLEMENTATION_VERSION = "1.44.0-SNAPSHOT"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index fbbcdd9b364..075f4fab117 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.17.2' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -54,12 +54,12 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' testImplementation 'junit:junit:4.12' testImplementation 'com.google.truth:truth:1.0.1' - testImplementation 'io.grpc:grpc-testing:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 0c71d91c0d2..e8655c09dd9 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.17.2' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.44.0-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 09dc587850f..13df17021c8 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.17.2' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.44.0-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 9fb69f3f690..b0bbc7a7268 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.17.2' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -53,8 +53,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/build.gradle b/examples/build.gradle index 4c88b826d38..03b43512a5c 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.17.2' def protocVersion = protobufVersion diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index a0d726f6768..6bb43394579 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.17.2' dependencies { diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 2558469feb3..fcfbab9d026 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.17.2' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 67db6c7c9fb..7445b7b7ce7 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT 3.17.2 1.7 diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index 331d8309136..e6bb1d73846 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -21,7 +21,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.17.2' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index d4625193bf8..71b2903e816 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT 3.17.2 1.7 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index 94ae0610a21..881cc553645 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.17.2' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 9ac3aefe34e..12724e4fbd1 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT 3.17.2 3.17.2 diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 8a8ceb371af..213034e10c2 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.17.2' dependencies { diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index 60d632bbb87..0eb097ee525 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT example-tls https://github.com/grpc/grpc-java UTF-8 - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT 3.17.2 2.0.34.Final diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index d00beaa06bb..123adbcef8f 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // 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.43.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def nettyTcNativeVersion = '2.0.31.Final' def protocVersion = '3.17.2' diff --git a/examples/pom.xml b/examples/pom.xml index 0704ce80d88..7546b58d763 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT examples https://github.com/grpc/grpc-java UTF-8 - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT 3.17.2 3.17.2 From 27b03c66a64aeae25f3fc867457b02e21ca81dab Mon Sep 17 00:00:00 2001 From: John Cormie Date: Tue, 30 Nov 2021 16:00:43 -0800 Subject: [PATCH 0020/2009] Send empty shutdown flags to avoid a binder memory leak (#8728) --- .../src/main/java/io/grpc/binder/internal/BinderTransport.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java index b3bc488b64a..8b41703af5c 100644 --- a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java +++ b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java @@ -345,6 +345,8 @@ private final void sendShutdownTransaction() { // Ignore. } Parcel parcel = Parcel.obtain(); + // Send empty flags to avoid a memory leak linked to empty parcels (b/207778694). + parcel.writeInt(0); try { outgoingBinder.transact(SHUTDOWN_TRANSPORT, parcel, null, IBinder.FLAG_ONEWAY); } catch (RemoteException re) { From 7aaa418ec71faeb761fd9146b1165e4eb28669fd Mon Sep 17 00:00:00 2001 From: Sergii Tkachenko Date: Wed, 1 Dec 2021 15:02:13 -0800 Subject: [PATCH 0021/2009] rls: Fix RouteLookupConfig test arguments This PR fixes a few cosmetic violations of the ErrorProne patterns introduced in PR #8645: ParameterName, and TimeUnitMismatch. --- rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java | 6 +++--- rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java b/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java index 5d1dcc1cadb..958abea3926 100644 --- a/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsProtoConvertersTest.java @@ -199,7 +199,7 @@ public void convert_jsonRlsConfig() throws IOException { ExtraKeys.create("host-key", "service-key", "method-key"), ImmutableMap.of("constKey1", "value1"))), /* lookupService= */ "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(2), + /* lookupServiceTimeoutInNanos= */ TimeUnit.SECONDS.toNanos(2), /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(240), /* cacheSizeBytes= */ 1000, @@ -351,7 +351,7 @@ public void convert_jsonRlsConfig_defaultValues() throws IOException { ExtraKeys.DEFAULT, ImmutableMap.of())), /* lookupService= */ "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(10), + /* lookupServiceTimeoutInNanos= */ TimeUnit.SECONDS.toNanos(10), /* maxAgeInNanos= */ TimeUnit.MINUTES.toNanos(5), /* staleAgeInNanos= */ TimeUnit.MINUTES.toNanos(5), /* cacheSizeBytes= */ 5 * 1024 * 1024, @@ -409,7 +409,7 @@ public void convert_jsonRlsConfig_staleAgeCappedByMaxAge() throws IOException { ExtraKeys.DEFAULT, ImmutableMap.of())), /* lookupService= */ "service1", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toNanos(2), + /* lookupServiceTimeoutInNanos= */ TimeUnit.SECONDS.toNanos(2), /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), /* cacheSizeBytes= */ 1000, diff --git a/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java b/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java index 0d834601279..9b66944d787 100644 --- a/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsRequestFactoryTest.java @@ -65,9 +65,9 @@ public class RlsRequestFactoryTest { ExtraKeys.create(null, null, null), ImmutableMap.of("const-key-4", "const-value-4"))), /* lookupService= */ "bigtable-rls.googleapis.com", - /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), - /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), - /* staleAgeInMillis= */ TimeUnit.SECONDS.toMillis(240), + /* lookupServiceTimeoutInNanos= */ TimeUnit.SECONDS.toNanos(2), + /* maxAgeInNanos= */ TimeUnit.SECONDS.toNanos(300), + /* staleAgeInNanos= */ TimeUnit.SECONDS.toNanos(240), /* cacheSizeBytes= */ 1000, /* defaultTarget= */ "us_east_1.cloudbigtable.googleapis.com"); From 24330bccff2b0d0caf3fc4c27ccf3f11860773a7 Mon Sep 17 00:00:00 2001 From: apolcyn Date: Tue, 7 Dec 2021 13:29:29 -0800 Subject: [PATCH 0022/2009] Replace C2P resolver env var with experimental scheme suffix (#8744) Java analogue of grpc/grpc#28294 --- .../grpc/xds/GoogleCloudToProdNameResolverProvider.java | 9 ++------- .../xds/GoogleCloudToProdNameResolverProviderTest.java | 3 ++- .../io/grpc/xds/GoogleCloudToProdNameResolverTest.java | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/GoogleCloudToProdNameResolverProvider.java b/xds/src/main/java/io/grpc/xds/GoogleCloudToProdNameResolverProvider.java index be8324b93cf..e7f9cb45ff8 100644 --- a/xds/src/main/java/io/grpc/xds/GoogleCloudToProdNameResolverProvider.java +++ b/xds/src/main/java/io/grpc/xds/GoogleCloudToProdNameResolverProvider.java @@ -29,9 +29,7 @@ @Internal public final class GoogleCloudToProdNameResolverProvider extends NameResolverProvider { - private static final boolean enableC2PResolver = - Boolean.parseBoolean(System.getenv("GRPC_EXPERIMENTAL_GOOGLE_C2P_RESOLVER")); - private static final String SCHEME = "google-c2p"; + private static final String SCHEME = "google-c2p-experimental"; @Override public NameResolver newNameResolver(URI targetUri, Args args) { @@ -50,10 +48,7 @@ public String getDefaultScheme() { @Override protected boolean isAvailable() { - if (enableC2PResolver) { - return true; - } - return false; + return true; } @Override diff --git a/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverProviderTest.java b/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverProviderTest.java index 372c8af8f41..cc6621028c8 100644 --- a/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverProviderTest.java +++ b/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverProviderTest.java @@ -73,7 +73,8 @@ NameResolverProvider.class, getClass().getClassLoader())) { @Test public void newNameResolver() { - assertThat(provider.newNameResolver(URI.create("google-c2p:///foo.googleapis.com"), args)) + assertThat(provider + .newNameResolver(URI.create("google-c2p-experimental:///foo.googleapis.com"), args)) .isInstanceOf(GoogleCloudToProdNameResolver.class); } } diff --git a/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverTest.java b/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverTest.java index 421b2a1dd0a..58be7108405 100644 --- a/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverTest.java +++ b/xds/src/test/java/io/grpc/xds/GoogleCloudToProdNameResolverTest.java @@ -69,7 +69,7 @@ public class GoogleCloudToProdNameResolverTest { @Rule public final MockitoRule mocks = MockitoJUnit.rule(); - private static final URI TARGET_URI = URI.create("google-c2p:///googleapis.com"); + private static final URI TARGET_URI = URI.create("google-c2p-experimental:///googleapis.com"); private static final String ZONE = "us-central1-a"; private static final int DEFAULT_PORT = 887; From e28145ab6afb92b68f18032f83ead26c1a37b2e6 Mon Sep 17 00:00:00 2001 From: Grant Oakley Date: Wed, 8 Dec 2021 14:39:42 -0800 Subject: [PATCH 0023/2009] Enclose all operations using obtained Parcels in try-finally blocks that will recycle the Parcel in the case that any exception is thrown. (#8733) --- .../grpc/binder/internal/BinderTransport.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java index 8b41703af5c..e07619dca33 100644 --- a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java +++ b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java @@ -323,17 +323,18 @@ final void sendSetupTransaction() { @GuardedBy("this") final void sendSetupTransaction(IBinder iBinder) { Parcel parcel = Parcel.obtain(); - parcel.writeInt(WIRE_FORMAT_VERSION); - parcel.writeStrongBinder(incomingBinder); try { + parcel.writeInt(WIRE_FORMAT_VERSION); + parcel.writeStrongBinder(incomingBinder); if (!iBinder.transact(SETUP_TRANSPORT, parcel, null, IBinder.FLAG_ONEWAY)) { shutdownInternal( Status.UNAVAILABLE.withDescription("Failed sending SETUP_TRANSPORT transaction"), true); } } catch (RemoteException re) { shutdownInternal(statusFromRemoteException(re), true); + } finally { + parcel.recycle(); } - parcel.recycle(); } @GuardedBy("this") @@ -345,14 +346,15 @@ private final void sendShutdownTransaction() { // Ignore. } Parcel parcel = Parcel.obtain(); - // Send empty flags to avoid a memory leak linked to empty parcels (b/207778694). - parcel.writeInt(0); try { + // Send empty flags to avoid a memory leak linked to empty parcels (b/207778694). + parcel.writeInt(0); outgoingBinder.transact(SHUTDOWN_TRANSPORT, parcel, null, IBinder.FLAG_ONEWAY); } catch (RemoteException re) { // Ignore. + } finally { + parcel.recycle(); } - parcel.recycle(); } } @@ -363,8 +365,8 @@ protected synchronized void sendPing(int id) throws StatusException { throw Status.FAILED_PRECONDITION.withDescription("Transport not ready.").asException(); } else { Parcel parcel = Parcel.obtain(); - parcel.writeInt(id); try { + parcel.writeInt(id); outgoingBinder.transact(PING, parcel, null, IBinder.FLAG_ONEWAY); } catch (RemoteException re) { throw statusFromRemoteException(re).asException(); @@ -410,15 +412,16 @@ final void sendTransaction(int callId, Parcel parcel) throws StatusException { final void sendOutOfBandClose(int callId, Status status) { Parcel parcel = Parcel.obtain(); - parcel.writeInt(0); // Placeholder for flags. Will be filled in below. - int flags = TransactionUtils.writeStatus(parcel, status); - TransactionUtils.fillInFlags(parcel, flags | TransactionUtils.FLAG_OUT_OF_BAND_CLOSE); try { + parcel.writeInt(0); // Placeholder for flags. Will be filled in below. + int flags = TransactionUtils.writeStatus(parcel, status); + TransactionUtils.fillInFlags(parcel, flags | TransactionUtils.FLAG_OUT_OF_BAND_CLOSE); sendTransaction(callId, parcel); } catch (StatusException e) { logger.log(Level.WARNING, "Failed sending oob close transaction", e); + } finally { + parcel.recycle(); } - parcel.recycle(); } @Override @@ -507,16 +510,17 @@ private void sendAcknowledgeBytes(IBinder iBinder) { long n = numIncomingBytes.get(); acknowledgedIncomingBytes = n; Parcel parcel = Parcel.obtain(); - parcel.writeLong(n); try { + parcel.writeLong(n); if (!iBinder.transact(ACKNOWLEDGE_BYTES, parcel, null, IBinder.FLAG_ONEWAY)) { shutdownInternal( Status.UNAVAILABLE.withDescription("Failed sending ack bytes transaction"), true); } } catch (RemoteException re) { shutdownInternal(statusFromRemoteException(re), true); + } finally { + parcel.recycle(); } - parcel.recycle(); } @GuardedBy("this") @@ -909,3 +913,4 @@ private static Status statusFromRemoteException(RemoteException e) { return Status.INTERNAL.withCause(e); } } + From efd968bcbb9c34dc94493ed88dbf627a5552cebb Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Tue, 7 Dec 2021 16:18:46 -0800 Subject: [PATCH 0024/2009] Upgrade Protobuf to 3.19.1 and Guava to 30.1.1 Protobuf uses Guava 30.1.1, so I upgrade it at the same time. It also caused an update to rules_jvm_external and reworking the Bazel build. Protobuf no longer requires bind() so they were dropped. Although Protobuf's protobuf_deps() brings in rules_jvm_external, and so we don't need to define it ourselves, it seems better to define it directly and not depend on transitive deps since we use it directly. Protobuf now has support for maven_install() by exposing PROTOBUF_MAVEN_ARTIFACTS, which required reorganizing the WORKSPACE to use maven_install() after loading protobuf. Protobuf still doesn't define target overrides for itself so we still maintain those. When reorganizing the WORKSPACE I noticed http_archive should ideally be above io_grpc_grpc_java as most users will need it there, so I fixed that since there were lots of other load()-reordering already. --- COMPILING.md | 4 +-- WORKSPACE | 24 +++++++-------- build.gradle | 4 +-- buildscripts/make_dependencies.bat | 2 +- buildscripts/make_dependencies.sh | 2 +- examples/WORKSPACE | 30 +++++++++---------- examples/android/clientcache/app/build.gradle | 2 +- examples/android/helloworld/app/build.gradle | 2 +- examples/android/routeguide/app/build.gradle | 2 +- examples/android/strictmode/app/build.gradle | 2 +- examples/build.gradle | 2 +- examples/example-alts/build.gradle | 2 +- examples/example-gauth/build.gradle | 2 +- examples/example-gauth/pom.xml | 2 +- examples/example-hostname/build.gradle | 2 +- examples/example-hostname/pom.xml | 2 +- examples/example-jwt-auth/build.gradle | 2 +- examples/example-jwt-auth/pom.xml | 4 +-- examples/example-tls/build.gradle | 2 +- examples/example-tls/pom.xml | 2 +- examples/example-xds/build.gradle | 2 +- examples/pom.xml | 4 +-- repositories.bzl | 27 +++++------------ 23 files changed, 58 insertions(+), 71 deletions(-) diff --git a/COMPILING.md b/COMPILING.md index 208f05e25cb..d065e702842 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -43,11 +43,11 @@ This section is only necessary if you are making changes to the code generation. Most users only need to use `skipCodegen=true` as discussed above. ### Build Protobuf -The codegen plugin is C++ code and requires protobuf 3.17.2 or later. +The codegen plugin is C++ code and requires protobuf 3.19.1 or later. For Linux, Mac and MinGW: ``` -$ PROTOBUF_VERSION=3.17.2 +$ PROTOBUF_VERSION=3.19.1 $ curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOBUF_VERSION/protobuf-all-$PROTOBUF_VERSION.tar.gz $ tar xzf protobuf-all-$PROTOBUF_VERSION.tar.gz $ cd protobuf-$PROTOBUF_VERSION diff --git a/WORKSPACE b/WORKSPACE index dad4842a7a7..b6198573f28 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -4,17 +4,25 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_jvm_external", - sha256 = "62133c125bf4109dfd9d2af64830208356ce4ef8b165a6ef15bbff7460b35c3a", - strip_prefix = "rules_jvm_external-3.0", - url = "https://github.com/bazelbuild/rules_jvm_external/archive/3.0.zip", + sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca", + strip_prefix = "rules_jvm_external-4.2", + url = "https://github.com/bazelbuild/rules_jvm_external/archive/4.2.zip", ) load("@rules_jvm_external//:defs.bzl", "maven_install") load("//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS") load("//:repositories.bzl", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS") +load("//:repositories.bzl", "grpc_java_repositories") + +grpc_java_repositories() + +load("@com_google_protobuf//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS") +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") + +protobuf_deps() maven_install( - artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS, + artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS + PROTOBUF_MAVEN_ARTIFACTS, generate_compat_repositories = True, override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS, repositories = [ @@ -25,11 +33,3 @@ maven_install( load("@maven//:compat.bzl", "compat_repositories") compat_repositories() - -load("//:repositories.bzl", "grpc_java_repositories") - -grpc_java_repositories() - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") - -protobuf_deps() diff --git a/build.gradle b/build.gradle index 9aab8312c5c..a852dec9276 100644 --- a/build.gradle +++ b/build.gradle @@ -55,9 +55,9 @@ subprojects { javaPluginPath = "$rootDir/compiler/build/exe/java_plugin/$protocPluginBaseName$exeSuffix" nettyVersion = '4.1.63.Final' - guavaVersion = '30.1-android' + guavaVersion = '30.1.1-android' googleauthVersion = '0.22.2' - protobufVersion = '3.17.2' + protobufVersion = '3.19.1' protocVersion = protobufVersion opencensusVersion = '0.28.0' autovalueVersion = '1.7.4' diff --git a/buildscripts/make_dependencies.bat b/buildscripts/make_dependencies.bat index 1622daaa16b..b8586e85832 100644 --- a/buildscripts/make_dependencies.bat +++ b/buildscripts/make_dependencies.bat @@ -1,4 +1,4 @@ -set PROTOBUF_VER=3.17.2 +set PROTOBUF_VER=3.19.1 set CMAKE_NAME=cmake-3.3.2-win32-x86 if not exist "protobuf-%PROTOBUF_VER%\cmake\build\Release\" ( diff --git a/buildscripts/make_dependencies.sh b/buildscripts/make_dependencies.sh index 927f1b4be28..7e132a91db0 100755 --- a/buildscripts/make_dependencies.sh +++ b/buildscripts/make_dependencies.sh @@ -3,7 +3,7 @@ # Build protoc set -evux -o pipefail -PROTOBUF_VERSION=3.17.2 +PROTOBUF_VERSION=3.19.1 # ARCH is x86_64 bit unless otherwise specified. ARCH="${ARCH:-x86_64}" diff --git a/examples/WORKSPACE b/examples/WORKSPACE index 36a002b4ee0..bd139ddd406 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -1,7 +1,9 @@ workspace(name = "examples") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + # For released versions, use release tag: -# http_repository( +# http_archive( # name = "io_grpc_grpc_java", # sha256 = "", # strip_prefix = "grpc-java-", @@ -12,24 +14,30 @@ local_repository( path = "..", ) -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - http_archive( name = "rules_jvm_external", - sha256 = "62133c125bf4109dfd9d2af64830208356ce4ef8b165a6ef15bbff7460b35c3a", - strip_prefix = "rules_jvm_external-3.0", - url = "https://github.com/bazelbuild/rules_jvm_external/archive/3.0.zip", + sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca", + strip_prefix = "rules_jvm_external-4.2", + url = "https://github.com/bazelbuild/rules_jvm_external/archive/4.2.zip", ) load("@rules_jvm_external//:defs.bzl", "maven_install") load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS") load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS") +load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories") + +grpc_java_repositories() + +load("@com_google_protobuf//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS") +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") + +protobuf_deps() maven_install( artifacts = [ "com.google.api.grpc:grpc-google-cloud-pubsub-v1:0.1.24", "com.google.api.grpc:proto-google-cloud-pubsub-v1:0.1.24", - ] + IO_GRPC_GRPC_JAVA_ARTIFACTS, + ] + IO_GRPC_GRPC_JAVA_ARTIFACTS + PROTOBUF_MAVEN_ARTIFACTS, generate_compat_repositories = True, override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS, repositories = [ @@ -40,11 +48,3 @@ maven_install( load("@maven//:compat.bzl", "compat_repositories") compat_repositories() - -load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories") - -grpc_java_repositories() - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") - -protobuf_deps() diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 075f4fab117..260255a1773 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -32,7 +32,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.17.2' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index e8655c09dd9..458a33584ea 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -30,7 +30,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.17.2' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index 13df17021c8..fb3fe7e8f95 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -30,7 +30,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.17.2' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index b0bbc7a7268..9472151bceb 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -31,7 +31,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.17.2' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/build.gradle b/examples/build.gradle index 03b43512a5c..3fe5c439e6d 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.17.2' +def protobufVersion = '3.19.1' def protocVersion = protobufVersion dependencies { diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index 6bb43394579..7db8e672704 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protocVersion = '3.17.2' +def protocVersion = '3.19.1' dependencies { // grpc-alts transitively depends on grpc-netty-shaded, grpc-protobuf, and grpc-stub diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index fcfbab9d026..2a581f2822f 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.17.2' +def protobufVersion = '3.19.1' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 7445b7b7ce7..765960c3bd3 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.17.2 + 3.19.1 1.7 1.7 diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index e6bb1d73846..f18060097ea 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.17.2' +def protobufVersion = '3.19.1' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index 71b2903e816..1ce2438e8de 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.17.2 + 3.19.1 1.7 1.7 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index 881cc553645..18f08658b69 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.17.2' +def protobufVersion = '3.19.1' def protocVersion = protobufVersion dependencies { diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 12724e4fbd1..9fc68fb40c1 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -14,8 +14,8 @@ UTF-8 1.44.0-SNAPSHOT - 3.17.2 - 3.17.2 + 3.19.1 + 3.19.1 1.7 1.7 diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 213034e10c2..98b73eec9c7 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protocVersion = '3.17.2' +def protocVersion = '3.19.1' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index 0eb097ee525..bcb6ecd47c0 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.17.2 + 3.19.1 2.0.34.Final 1.7 diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index 123adbcef8f..f593a48050a 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // updating the version in our release process. def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def nettyTcNativeVersion = '2.0.31.Final' -def protocVersion = '3.17.2' +def protocVersion = '3.19.1' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/pom.xml b/examples/pom.xml index 7546b58d763..ac45d452c68 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -13,8 +13,8 @@ UTF-8 1.44.0-SNAPSHOT - 3.17.2 - 3.17.2 + 3.19.1 + 3.19.1 1.7 1.7 diff --git a/repositories.bzl b/repositories.bzl index 3222e15ff65..712e34fded0 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -20,7 +20,7 @@ IO_GRPC_GRPC_JAVA_ARTIFACTS = [ "com.google.auto.value:auto-value-annotations:1.7.4", "com.google.errorprone:error_prone_annotations:2.9.0", "com.google.guava:failureaccess:1.0.1", - "com.google.guava:guava:30.1-android", + "com.google.guava:guava:30.1.1-android", "com.google.j2objc:j2objc-annotations:1.3", "com.google.truth:truth:1.0.1", "com.squareup.okhttp:okhttp:2.7.4", @@ -92,37 +92,24 @@ def grpc_java_repositories(): if not native.existing_rule("io_grpc_grpc_proto"): io_grpc_grpc_proto() - native.bind( - name = "guava", - actual = "@com_google_guava_guava//jar", - ) - native.bind( - name = "gson", - actual = "@com_google_code_gson_gson//jar", - ) - native.bind( - name = "error_prone_annotations", - actual = "@com_google_errorprone_error_prone_annotations//jar", - ) - def com_google_protobuf(): # proto_library rules implicitly depend on @com_google_protobuf//:protoc, # which is the proto-compiler. # This statement defines the @com_google_protobuf repo. http_archive( name = "com_google_protobuf", - sha256 = "f6042eef01551cee4c663a11c3f429c06360a1f51daa9f4772bf3f13d24cde1f", - strip_prefix = "protobuf-3.17.2", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.17.2.zip"], + sha256 = "25f1292d4ea6666f460a2a30038eef121e6c3937ae0f61d610611dfb14b0bd32", + strip_prefix = "protobuf-3.19.1", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.zip"], ) def com_google_protobuf_javalite(): # java_lite_proto_library rules implicitly depend on @com_google_protobuf_javalite http_archive( name = "com_google_protobuf_javalite", - sha256 = "f6042eef01551cee4c663a11c3f429c06360a1f51daa9f4772bf3f13d24cde1f", - strip_prefix = "protobuf-3.17.2", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.17.2.zip"], + sha256 = "25f1292d4ea6666f460a2a30038eef121e6c3937ae0f61d610611dfb14b0bd32", + strip_prefix = "protobuf-3.19.1", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.zip"], ) def io_grpc_grpc_proto(): From 531db504ca9f84bdf6bcec6e06d202888abccd31 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Tue, 14 Dec 2021 17:55:48 -0800 Subject: [PATCH 0025/2009] core: fix race condition in idleTimer & ManagedChannel#enterIdle PR for Spikhalskiy/grpc-java@6d260b8 Hot fix of #8714 --- core/src/main/java/io/grpc/internal/ManagedChannelImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java index 2e079078fc7..601c7740ca4 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java @@ -349,6 +349,9 @@ private class IdleModeTimer implements Runnable { @Override public void run() { + if (lbHelper == null) { + return; + } enterIdleMode(); } } From 282a62e418e1e895e2f14c16f60c63d6294a9899 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Wed, 15 Dec 2021 10:27:01 -0800 Subject: [PATCH 0026/2009] Update README etc to reference 1.43.0 (#8760) --- README.md | 36 ++++++++++++------------ cronet/README.md | 2 +- documentation/android-channel-builder.md | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index d11c2850805..853b37e8c6a 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,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.42.1/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.42.1/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.43.0/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.43.0/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -43,17 +43,17 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.42.1 + 1.43.0 io.grpc grpc-protobuf - 1.42.1 + 1.43.0 io.grpc grpc-stub - 1.42.1 + 1.43.0 org.apache.tomcat @@ -65,23 +65,23 @@ 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 -implementation 'io.grpc:grpc-netty-shaded:1.42.1' -implementation 'io.grpc:grpc-protobuf:1.42.1' -implementation 'io.grpc:grpc-stub:1.42.1' +implementation 'io.grpc:grpc-netty-shaded:1.43.0' +implementation 'io.grpc:grpc-protobuf:1.43.0' +implementation 'io.grpc:grpc-stub:1.43.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.42.1' -implementation 'io.grpc:grpc-protobuf-lite:1.42.1' -implementation 'io.grpc:grpc-stub:1.42.1' +implementation 'io.grpc:grpc-okhttp:1.43.0' +implementation 'io.grpc:grpc-protobuf-lite:1.43.0' +implementation 'io.grpc:grpc-stub:1.43.0' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.42.1 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.43.0 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -111,9 +111,9 @@ For protobuf-based codegen integrated with the Maven build system, you can use protobuf-maven-plugin 0.6.1 - com.google.protobuf:protoc:3.17.2:exe:${os.detected.classifier} + com.google.protobuf:protoc:3.19.1:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.43.0:exe:${os.detected.classifier} @@ -139,11 +139,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.17.2" + artifact = "com.google.protobuf:protoc:3.19.1" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' + artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0' } } generateProtoTasks { @@ -172,11 +172,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.17.2" + artifact = "com.google.protobuf:protoc:3.19.1" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' + artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0' } } generateProtoTasks { diff --git a/cronet/README.md b/cronet/README.md index a682c5bcee8..e7705acc3de 100644 --- a/cronet/README.md +++ b/cronet/README.md @@ -26,7 +26,7 @@ In your app module's `build.gradle` file, include a dependency on both `grpc-cro Google Play Services Client Library for Cronet ``` -implementation 'io.grpc:grpc-cronet:1.42.1' +implementation 'io.grpc:grpc-cronet:1.43.0' implementation 'com.google.android.gms:play-services-cronet:16.0.0' ``` diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md index d9541c56623..3ebbf9522a4 100644 --- a/documentation/android-channel-builder.md +++ b/documentation/android-channel-builder.md @@ -36,8 +36,8 @@ In your `build.gradle` file, include a dependency on both `grpc-android` and `grpc-okhttp`: ``` -implementation 'io.grpc:grpc-android:1.42.1' -implementation 'io.grpc:grpc-okhttp:1.42.1' +implementation 'io.grpc:grpc-android:1.43.0' +implementation 'io.grpc:grpc-okhttp:1.43.0' ``` You also need permission to access the device's network state in your From d9eb30cd92faca201b5a1bff886102a10373722b Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Wed, 15 Dec 2021 14:03:36 -0800 Subject: [PATCH 0027/2009] Bump GSON to 2.8.9 --- build.gradle | 2 +- examples/pom.xml | 5 +++++ repositories.bzl | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a852dec9276..e3dcad2a0de 100644 --- a/build.gradle +++ b/build.gradle @@ -148,7 +148,7 @@ subprojects { errorprone: "com.google.errorprone:error_prone_annotations:2.9.0", cronet_api: 'org.chromium.net:cronet-api:92.4515.131', cronet_embedded: 'org.chromium.net:cronet-embedded:92.4515.131', - gson: "com.google.code.gson:gson:2.8.6", + gson: "com.google.code.gson:gson:2.8.9", guava: "com.google.guava:guava:${guavaVersion}", javax_annotation: 'org.apache.tomcat:annotations-api:6.0.53', jsr305: 'com.google.code.findbugs:jsr305:3.0.2', diff --git a/examples/pom.xml b/examples/pom.xml index ac45d452c68..4a23872d05c 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -51,6 +51,11 @@ protobuf-java-util ${protobuf.version} + + com.google.code.gson + gson + 2.8.9 + org.apache.tomcat annotations-api diff --git a/repositories.bzl b/repositories.bzl index 712e34fded0..6e9caf9409d 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -15,7 +15,7 @@ IO_GRPC_GRPC_JAVA_ARTIFACTS = [ "com.google.auth:google-auth-library-credentials:0.22.0", "com.google.auth:google-auth-library-oauth2-http:0.22.0", "com.google.code.findbugs:jsr305:3.0.2", - "com.google.code.gson:gson:jar:2.8.6", + "com.google.code.gson:gson:jar:2.8.9", "com.google.auto.value:auto-value:1.7.4", "com.google.auto.value:auto-value-annotations:1.7.4", "com.google.errorprone:error_prone_annotations:2.9.0", From 63756ec9514dbfd9d2ff496342b93f794b83ecc6 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Fri, 17 Dec 2021 07:36:00 -0800 Subject: [PATCH 0028/2009] core: remove unused method in AutoConfiguredLoadBalancer (#8769) The method added in #5821 seems not used now. --- .../io/grpc/internal/AutoConfiguredLoadBalancerFactory.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java b/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java index 037d49cb72f..01c48b9efcf 100644 --- a/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java +++ b/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java @@ -96,10 +96,6 @@ public final class AutoConfiguredLoadBalancer { delegate = delegateProvider.newLoadBalancer(helper); } - public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) { - tryHandleResolvedAddresses(resolvedAddresses); - } - /** * Returns non-OK status if resolvedAddresses is empty and delegate lb requires address ({@link * LoadBalancer#canHandleEmptyAddressListFromNameResolution()} returns {@code false}). {@code From 042f9879d4c36aa4a4b04937c8f2e5775b851342 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Mon, 20 Dec 2021 09:46:25 -0800 Subject: [PATCH 0029/2009] all: remove deprecated StreamInfo.transportAttrs (#8768) APIs such as `StreamInfo.getTransportAttrs()` were [deprecated](https://github.com/grpc/grpc-java/commit/860e97d12ab46e184ac4448eeca8a45671de6462#diff-aa4049f54d6d5d462700e9221344184a37d2068b3ba7d715abd417b1df5bf883R114) since 1.41.0. Removing now. --- .../main/java/io/grpc/ClientStreamTracer.java | 39 +------------- .../test/java/io/grpc/CallOptionsTest.java | 2 +- .../io/grpc/census/CensusStatsModule.java | 2 +- .../io/grpc/census/CensusTracingModule.java | 2 +- .../main/java/io/grpc/internal/GrpcUtil.java | 53 +------------------ .../io/grpc/internal/RetriableStream.java | 2 +- .../java/io/grpc/ClientStreamTracerTest.java | 22 ++------ .../java/io/grpc/internal/GrpcUtilTest.java | 38 ------------- .../grpc/internal/ManagedChannelImplTest.java | 8 +-- .../grpc/grpclb/GrpclbClientLoadRecorder.java | 2 +- .../grpclb/TokenAttachingTracerFactory.java | 2 +- .../TokenAttachingTracerFactoryTest.java | 2 +- .../integration/AbstractInteropTest.java | 2 +- .../grpc/testing/integration/RetryTest.java | 4 +- .../io/grpc/xds/ClusterImplLoadBalancer.java | 2 +- .../java/io/grpc/xds/OrcaPerRequestUtil.java | 4 +- 16 files changed, 25 insertions(+), 161 deletions(-) diff --git a/api/src/main/java/io/grpc/ClientStreamTracer.java b/api/src/main/java/io/grpc/ClientStreamTracer.java index bb836ac82e1..53909f23740 100644 --- a/api/src/main/java/io/grpc/ClientStreamTracer.java +++ b/api/src/main/java/io/grpc/ClientStreamTracer.java @@ -81,10 +81,6 @@ public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata header } } - /** An abstract class for internal use only. */ - @Internal - public abstract static class InternalLimitedInfoFactory extends Factory {} - /** * Information about a stream. * @@ -95,32 +91,17 @@ public abstract static class InternalLimitedInfoFactory extends Factory {} */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2861") public static final class StreamInfo { - private final Attributes transportAttrs; private final CallOptions callOptions; private final int previousAttempts; private final boolean isTransparentRetry; StreamInfo( - Attributes transportAttrs, CallOptions callOptions, int previousAttempts, - boolean isTransparentRetry) { - this.transportAttrs = checkNotNull(transportAttrs, "transportAttrs"); + CallOptions callOptions, int previousAttempts, boolean isTransparentRetry) { this.callOptions = checkNotNull(callOptions, "callOptions"); this.previousAttempts = previousAttempts; this.isTransparentRetry = isTransparentRetry; } - /** - * Returns the attributes of the transport that this stream was created on. - * - * @deprecated Use {@link ClientStreamTracer#streamCreated(Attributes, Metadata)} to handle - * the transport Attributes instead. - */ - @Deprecated - @Grpc.TransportAttr - public Attributes getTransportAttrs() { - return transportAttrs; - } - /** * Returns the effective CallOptions of the call. */ @@ -154,7 +135,6 @@ public boolean isTransparentRetry() { public Builder toBuilder() { return new Builder() .setCallOptions(callOptions) - .setTransportAttrs(transportAttrs) .setPreviousAttempts(previousAttempts) .setIsTransparentRetry(isTransparentRetry); } @@ -171,7 +151,6 @@ public static Builder newBuilder() { @Override public String toString() { return MoreObjects.toStringHelper(this) - .add("transportAttrs", transportAttrs) .add("callOptions", callOptions) .add("previousAttempts", previousAttempts) .add("isTransparentRetry", isTransparentRetry) @@ -184,7 +163,6 @@ public String toString() { * @since 1.21.0 */ public static final class Builder { - private Attributes transportAttrs = Attributes.EMPTY; private CallOptions callOptions = CallOptions.DEFAULT; private int previousAttempts; private boolean isTransparentRetry; @@ -192,19 +170,6 @@ public static final class Builder { Builder() { } - /** - * Sets the attributes of the transport that this stream was created on. This field is - * optional. - * - * @deprecated Use {@link ClientStreamTracer#streamCreated(Attributes, Metadata)} to handle - * the transport Attributes instead. - */ - @Deprecated - public Builder setTransportAttrs(@Grpc.TransportAttr Attributes transportAttrs) { - this.transportAttrs = checkNotNull(transportAttrs, "transportAttrs cannot be null"); - return this; - } - /** * Sets the effective CallOptions of the call. This field is optional. */ @@ -237,7 +202,7 @@ public Builder setIsTransparentRetry(boolean isTransparentRetry) { * Builds a new StreamInfo. */ public StreamInfo build() { - return new StreamInfo(transportAttrs, callOptions, previousAttempts, isTransparentRetry); + return new StreamInfo(callOptions, previousAttempts, isTransparentRetry); } } } diff --git a/api/src/test/java/io/grpc/CallOptionsTest.java b/api/src/test/java/io/grpc/CallOptionsTest.java index 0bc0d357358..15e5163e860 100644 --- a/api/src/test/java/io/grpc/CallOptionsTest.java +++ b/api/src/test/java/io/grpc/CallOptionsTest.java @@ -272,7 +272,7 @@ public void increment(long period, TimeUnit unit) { } } - private static class FakeTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory { + private static class FakeTracerFactory extends ClientStreamTracer.Factory { final String name; FakeTracerFactory(String name) { diff --git a/census/src/main/java/io/grpc/census/CensusStatsModule.java b/census/src/main/java/io/grpc/census/CensusStatsModule.java index 487e49e5005..366be55de68 100644 --- a/census/src/main/java/io/grpc/census/CensusStatsModule.java +++ b/census/src/main/java/io/grpc/census/CensusStatsModule.java @@ -397,7 +397,7 @@ void recordFinishedAttempt() { @VisibleForTesting static final class CallAttemptsTracerFactory extends - ClientStreamTracer.InternalLimitedInfoFactory { + ClientStreamTracer.Factory { static final MeasureLong RETRIES_PER_CALL = Measure.MeasureLong.create( "grpc.io/client/retries_per_call", "Number of retries per call", "1"); diff --git a/census/src/main/java/io/grpc/census/CensusTracingModule.java b/census/src/main/java/io/grpc/census/CensusTracingModule.java index 08d5fe3ca97..5c635613f33 100644 --- a/census/src/main/java/io/grpc/census/CensusTracingModule.java +++ b/census/src/main/java/io/grpc/census/CensusTracingModule.java @@ -226,7 +226,7 @@ private static void recordMessageEvent( } @VisibleForTesting - final class CallAttemptsTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory { + final class CallAttemptsTracerFactory extends ClientStreamTracer.Factory { volatile int callEnded; private final boolean isSampledToLocalTracing; diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index 635fab11c8f..c997414eabe 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -27,10 +27,8 @@ import com.google.common.base.Supplier; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; -import io.grpc.ClientStreamTracer.InternalLimitedInfoFactory; import io.grpc.ClientStreamTracer.StreamInfo; import io.grpc.InternalChannelz.SocketStats; import io.grpc.InternalLogId; @@ -725,7 +723,7 @@ public ClientStream newStream( ClientStreamTracer[] tracers) { StreamInfo info = StreamInfo.newBuilder().setCallOptions(callOptions).build(); ClientStreamTracer streamTracer = - newClientStreamTracer(streamTracerFactory, info, headers); + streamTracerFactory.newClientStreamTracer(info, headers); checkState(tracers[tracers.length - 1] == NOOP_TRACER, "lb tracer already assigned"); tracers[tracers.length - 1] = streamTracer; return transport.newStream(method, headers, callOptions, tracers); @@ -769,7 +767,7 @@ public static ClientStreamTracer[] getClientStreamTracers( .setIsTransparentRetry(isTransparentRetry) .build(); for (int i = 0; i < factories.size(); i++) { - tracers[i] = newClientStreamTracer(factories.get(i), streamInfo, headers); + tracers[i] = factories.get(i).newClientStreamTracer(streamInfo, headers); } // Reserved to be set later by the lb as per the API contract of ClientTransport.newStream(). // See also GrpcUtil.getTransportFromPickResult() @@ -777,53 +775,6 @@ public static ClientStreamTracer[] getClientStreamTracers( return tracers; } - // A util function for backward compatibility to support deprecated StreamInfo.getAttributes(). - @VisibleForTesting - static ClientStreamTracer newClientStreamTracer( - final ClientStreamTracer.Factory streamTracerFactory, final StreamInfo info, - final Metadata headers) { - ClientStreamTracer streamTracer; - if (streamTracerFactory instanceof InternalLimitedInfoFactory) { - streamTracer = streamTracerFactory.newClientStreamTracer(info, headers); - } else { - streamTracer = new ForwardingClientStreamTracer() { - final ClientStreamTracer noop = new ClientStreamTracer() {}; - volatile ClientStreamTracer delegate = noop; - - void maybeInit(StreamInfo info, Metadata headers) { - if (delegate != noop) { - return; - } - synchronized (this) { - if (delegate == noop) { - delegate = streamTracerFactory.newClientStreamTracer(info, headers); - } - } - } - - @Override - protected ClientStreamTracer delegate() { - return delegate; - } - - @SuppressWarnings("deprecation") - @Override - public void streamCreated(Attributes transportAttrs, Metadata headers) { - StreamInfo streamInfo = info.toBuilder().setTransportAttrs(transportAttrs).build(); - maybeInit(streamInfo, headers); - delegate().streamCreated(transportAttrs, headers); - } - - @Override - public void streamClosed(Status status) { - maybeInit(info, headers); - delegate().streamClosed(status); - } - }; - } - return streamTracer; - } - /** Quietly closes all messages in MessageProducer. */ static void closeQuietly(MessageProducer producer) { InputStream message; diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java index 1fb8d3c43bd..4afdb3f750e 100644 --- a/core/src/main/java/io/grpc/internal/RetriableStream.java +++ b/core/src/main/java/io/grpc/internal/RetriableStream.java @@ -221,7 +221,7 @@ private Substream createSubstream(int previousAttemptCount, boolean isTransparen Substream sub = new Substream(previousAttemptCount); // one tracer per substream final ClientStreamTracer bufferSizeTracer = new BufferSizeTracer(sub); - ClientStreamTracer.Factory tracerFactory = new ClientStreamTracer.InternalLimitedInfoFactory() { + ClientStreamTracer.Factory tracerFactory = new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer( ClientStreamTracer.StreamInfo info, Metadata headers) { diff --git a/core/src/test/java/io/grpc/ClientStreamTracerTest.java b/core/src/test/java/io/grpc/ClientStreamTracerTest.java index df450adc630..5ddee77f5c0 100644 --- a/core/src/test/java/io/grpc/ClientStreamTracerTest.java +++ b/core/src/test/java/io/grpc/ClientStreamTracerTest.java @@ -27,48 +27,34 @@ /** Unit tests for the embedded classes in {@link ClientStreamTracer}. */ @RunWith(JUnit4.class) public class ClientStreamTracerTest { - private static final Attributes.Key TRANSPORT_ATTR_KEY = - Attributes.Key.create("transport-attr-key"); private final CallOptions callOptions = CallOptions.DEFAULT.withDeadlineAfter(1, MINUTES); - private final Attributes transportAttrs = - Attributes.newBuilder().set(TRANSPORT_ATTR_KEY, "value").build(); @Test - @SuppressWarnings("deprecation") // info.getTransportAttrs() public void streamInfo_empty() { StreamInfo info = StreamInfo.newBuilder().build(); assertThat(info.getCallOptions()).isSameInstanceAs(CallOptions.DEFAULT); - assertThat(info.getTransportAttrs()).isSameInstanceAs(Attributes.EMPTY); } @Test - @SuppressWarnings("deprecation") // info.getTransportAttrs() public void streamInfo_withInfo() { - StreamInfo info = StreamInfo.newBuilder() - .setCallOptions(callOptions).setTransportAttrs(transportAttrs).build(); + StreamInfo info = StreamInfo.newBuilder().setCallOptions(callOptions).build(); assertThat(info.getCallOptions()).isSameInstanceAs(callOptions); - assertThat(info.getTransportAttrs()).isSameInstanceAs(transportAttrs); } @Test - @SuppressWarnings("deprecation") // info.setTransportAttrs() public void streamInfo_noEquality() { - StreamInfo info1 = StreamInfo.newBuilder() - .setCallOptions(callOptions).setTransportAttrs(transportAttrs).build(); - StreamInfo info2 = StreamInfo.newBuilder() - .setCallOptions(callOptions).setTransportAttrs(transportAttrs).build(); + StreamInfo info1 = StreamInfo.newBuilder().setCallOptions(callOptions).build(); + StreamInfo info2 = StreamInfo.newBuilder().setCallOptions(callOptions).build(); assertThat(info1).isNotSameInstanceAs(info2); assertThat(info1).isNotEqualTo(info2); } @Test - @SuppressWarnings("deprecation") // info.getTransportAttrs() public void streamInfo_toBuilder() { StreamInfo info1 = StreamInfo.newBuilder() - .setCallOptions(callOptions).setTransportAttrs(transportAttrs).build(); + .setCallOptions(callOptions).build(); StreamInfo info2 = info1.toBuilder().build(); assertThat(info2.getCallOptions()).isSameInstanceAs(callOptions); - assertThat(info2.getTransportAttrs()).isSameInstanceAs(transportAttrs); } } diff --git a/core/src/test/java/io/grpc/internal/GrpcUtilTest.java b/core/src/test/java/io/grpc/internal/GrpcUtilTest.java index 6d2c21ddab8..7e3f6e7db4e 100644 --- a/core/src/test/java/io/grpc/internal/GrpcUtilTest.java +++ b/core/src/test/java/io/grpc/internal/GrpcUtilTest.java @@ -16,7 +16,6 @@ package io.grpc.internal; -import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -28,18 +27,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; -import io.grpc.ClientStreamTracer.StreamInfo; import io.grpc.LoadBalancer.PickResult; import io.grpc.Metadata; import io.grpc.Status; import io.grpc.internal.ClientStreamListener.RpcProgress; import io.grpc.internal.GrpcUtil.Http2Error; import io.grpc.testing.TestMethodDescriptors; -import java.util.ArrayDeque; -import java.util.concurrent.atomic.AtomicReference; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -296,37 +291,4 @@ public void getTransportFromPickResult_dropPickResult_failFast() { verify(listener).closed(eq(status), eq(RpcProgress.DROPPED), any(Metadata.class)); } - - @Test - public void clientStreamTracerFactoryBackwardCompatibility() { - final AtomicReference transportAttrsRef = new AtomicReference<>(); - final ClientStreamTracer mockTracer = mock(ClientStreamTracer.class); - final Metadata.Key key = Metadata.Key.of("fake-key", Metadata.ASCII_STRING_MARSHALLER); - final ArrayDeque tracers = new ArrayDeque<>(); - ClientStreamTracer.Factory oldFactoryImpl = new ClientStreamTracer.Factory() { - @SuppressWarnings("deprecation") - @Override - public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { - transportAttrsRef.set(info.getTransportAttrs()); - headers.put(key, "fake-value"); - tracers.offer(mockTracer); - return mockTracer; - } - }; - - StreamInfo info = - StreamInfo.newBuilder().setCallOptions(CallOptions.DEFAULT.withWaitForReady()).build(); - Metadata metadata = new Metadata(); - Attributes transAttrs = - Attributes.newBuilder().set(Attributes.Key.create("foo"), "bar").build(); - ClientStreamTracer tracer = GrpcUtil.newClientStreamTracer(oldFactoryImpl, info, metadata); - tracer.streamCreated(transAttrs, metadata); - assertThat(tracers.poll()).isSameInstanceAs(mockTracer); - assertThat(transportAttrsRef.get()).isEqualTo(transAttrs); - assertThat(metadata.get(key)).isEqualTo("fake-value"); - - tracer.streamClosed(Status.UNAVAILABLE); - // verify that newClientStreamTracer() is called no more than once - assertThat(tracers).isEmpty(); - } } diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java index 668411d7ecc..f47954e2215 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java @@ -2447,13 +2447,13 @@ public void pickerReturnsStreamTracer_noDelay() { ClientStream mockStream = mock(ClientStream.class); final ClientStreamTracer tracer1 = new ClientStreamTracer() {}; final ClientStreamTracer tracer2 = new ClientStreamTracer() {}; - ClientStreamTracer.Factory factory1 = new ClientStreamTracer.InternalLimitedInfoFactory() { + ClientStreamTracer.Factory factory1 = new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return tracer1; } }; - ClientStreamTracer.Factory factory2 = new ClientStreamTracer.InternalLimitedInfoFactory() { + ClientStreamTracer.Factory factory2 = new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return tracer2; @@ -2491,13 +2491,13 @@ public void pickerReturnsStreamTracer_delayed() { ClientStream mockStream = mock(ClientStream.class); final ClientStreamTracer tracer1 = new ClientStreamTracer() {}; final ClientStreamTracer tracer2 = new ClientStreamTracer() {}; - ClientStreamTracer.Factory factory1 = new ClientStreamTracer.InternalLimitedInfoFactory() { + ClientStreamTracer.Factory factory1 = new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return tracer1; } }; - ClientStreamTracer.Factory factory2 = new ClientStreamTracer.InternalLimitedInfoFactory() { + ClientStreamTracer.Factory factory2 = new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return tracer2; diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java index 75f2481254d..d27c485dc13 100644 --- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java +++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java @@ -37,7 +37,7 @@ * span of an LB stream with the remote load-balancer. */ @ThreadSafe -final class GrpclbClientLoadRecorder extends ClientStreamTracer.InternalLimitedInfoFactory { +final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory { private static final AtomicLongFieldUpdater callsStartedUpdater = AtomicLongFieldUpdater.newUpdater(GrpclbClientLoadRecorder.class, "callsStarted"); diff --git a/grpclb/src/main/java/io/grpc/grpclb/TokenAttachingTracerFactory.java b/grpclb/src/main/java/io/grpc/grpclb/TokenAttachingTracerFactory.java index 03e1447bb2c..c00d988aa5d 100644 --- a/grpclb/src/main/java/io/grpc/grpclb/TokenAttachingTracerFactory.java +++ b/grpclb/src/main/java/io/grpc/grpclb/TokenAttachingTracerFactory.java @@ -30,7 +30,7 @@ * Wraps a {@link ClientStreamTracer.Factory}, retrieves tokens from transport attributes and * attaches them to headers. This is only used in the PICK_FIRST mode. */ -final class TokenAttachingTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory { +final class TokenAttachingTracerFactory extends ClientStreamTracer.Factory { private static final ClientStreamTracer NOOP_TRACER = new ClientStreamTracer() {}; @Nullable diff --git a/grpclb/src/test/java/io/grpc/grpclb/TokenAttachingTracerFactoryTest.java b/grpclb/src/test/java/io/grpc/grpclb/TokenAttachingTracerFactoryTest.java index 29ded18d913..4787c8697cc 100644 --- a/grpclb/src/test/java/io/grpc/grpclb/TokenAttachingTracerFactoryTest.java +++ b/grpclb/src/test/java/io/grpc/grpclb/TokenAttachingTracerFactoryTest.java @@ -49,7 +49,7 @@ public void streamCreated(Attributes transportAttrs, Metadata headers) { private final ClientStreamTracer.Factory delegate = mock( ClientStreamTracer.Factory.class, delegatesTo( - new ClientStreamTracer.InternalLimitedInfoFactory() { + new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer( ClientStreamTracer.StreamInfo info, Metadata headers) { diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java index 698aa330ec6..8e107add3e3 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java @@ -302,7 +302,7 @@ final SocketAddress getListenAddress() { new LinkedBlockingQueue<>(); private final ClientStreamTracer.Factory clientStreamTracerFactory = - new ClientStreamTracer.InternalLimitedInfoFactory() { + new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer( ClientStreamTracer.StreamInfo info, Metadata headers) { diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java index 045d54ea44e..80cf83b0939 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java @@ -432,7 +432,7 @@ public void streamClosed(Status status) { } } - class CloseDelayedTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory { + class CloseDelayedTracerFactory extends ClientStreamTracer.Factory { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return new CloseDelayedTracer(); @@ -492,7 +492,7 @@ public void streamClosed(Status status) { } } - class TransparentRetryTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory { + class TransparentRetryTracerFactory extends ClientStreamTracer.Factory { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return new TransparentRetryTriggeringTracer(); diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java index b4fc017d2d1..e9796267a85 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java @@ -336,7 +336,7 @@ public String toString() { } private static final class CountingStreamTracerFactory extends - ClientStreamTracer.InternalLimitedInfoFactory { + ClientStreamTracer.Factory { private ClusterLocalityStats stats; private final AtomicLong inFlights; @Nullable diff --git a/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java b/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java index 4b4cff92064..34589d77d07 100644 --- a/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java +++ b/xds/src/main/java/io/grpc/xds/OrcaPerRequestUtil.java @@ -37,7 +37,7 @@ abstract class OrcaPerRequestUtil { private static final ClientStreamTracer NOOP_CLIENT_STREAM_TRACER = new ClientStreamTracer() {}; private static final ClientStreamTracer.Factory NOOP_CLIENT_STREAM_TRACER_FACTORY = - new ClientStreamTracer.InternalLimitedInfoFactory() { + new ClientStreamTracer.Factory() { @Override public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) { return NOOP_CLIENT_STREAM_TRACER; @@ -190,7 +190,7 @@ public interface OrcaPerRequestReportListener { */ @VisibleForTesting static final class OrcaReportingTracerFactory extends - ClientStreamTracer.InternalLimitedInfoFactory { + ClientStreamTracer.Factory { @VisibleForTesting static final Metadata.Key ORCA_ENDPOINT_LOAD_METRICS_KEY = From b244ba8d4cbbcca0362925b71f611f48d6c9f5f7 Mon Sep 17 00:00:00 2001 From: Mohan Li <67390330+mohanli-ml@users.noreply.github.com> Date: Mon, 20 Dec 2021 13:00:42 -0800 Subject: [PATCH 0030/2009] xds: add skipNetCmd flag to fallback test client (#8765) We are setting up fallback test based on TD. Currently the test client is compiled in google3, so we must run it in a container so that the client can have the GRTE dependency. However, container does not have `ip`, `iptables`, etc network command, so we plan to run the network command outside of the container. To do this, add a new flag `skipNetCmd` to skip network commands inside the test client. --- .../integration/GrpclbFallbackTestClient.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/GrpclbFallbackTestClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/GrpclbFallbackTestClient.java index e98f4c31d2a..52c9e8238b5 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/GrpclbFallbackTestClient.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/GrpclbFallbackTestClient.java @@ -74,6 +74,7 @@ public void run() { private String serverUri; private String customCredentialsType; private String testCase; + private Boolean skipNetCmd = false; private ManagedChannel channel; private TestServiceGrpc.TestServiceBlockingStub blockingStub; @@ -108,6 +109,8 @@ private void parseArgs(String[] args) { blackholeLbAndBackendAddrsCmd = value; } else if ("custom_credentials_type".equals(key)) { customCredentialsType = value; + } else if ("skip_net_cmd".equals(key)) { + skipNetCmd = Boolean.valueOf(value); } else { System.err.println("Unknown argument: " + key); usage = true; @@ -129,6 +132,10 @@ private void parseArgs(String[] args) { + "\n --blackhole_lb_and_backend_addrs_cmd Shell command used to make " + "LB and backend addresses black holed. Default: " + c.blackholeLbAndBackendAddrsCmd + + "\n --skip_net_cmd Skip unroute and blackhole " + + "shell command to allow setting the net config outside of the test " + + "client. Default: " + + c.skipNetCmd + "\n --test_case=TEST_CASE Test case to run. Valid options are:" + "\n fast_fallback_before_startup : fallback before LB connection" + "\n fast_fallback_after_startup : fallback after startup due to " @@ -172,9 +179,14 @@ private void tearDown() { } } - private static void runShellCmd(String cmd) throws Exception { + private void runShellCmd(String cmd) throws Exception { + if (skipNetCmd) { + logger.info("Skip net cmd because --skip_net_cmd is set to true"); + return; + } logger.info("Run shell command: " + cmd); - ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd); + // Do not use bash -c here as bash may not exist in a container + ProcessBuilder pb = new ProcessBuilder(cmd.split(" ")); pb.redirectErrorStream(true); Process process = pb.start(); logger.info("Shell command merged stdout and stderr: " @@ -211,7 +223,7 @@ private GrpclbRouteType doRpcAndGetPath(Deadline deadline) { private void waitForFallbackAndDoRpcs(Deadline fallbackDeadline) throws Exception { int fallbackRetryCount = 0; - boolean fellBack = false; + boolean fallBack = false; while (!fallbackDeadline.isExpired()) { GrpclbRouteType grpclbRouteType = doRpcAndGetPath( Deadline.after(1, TimeUnit.SECONDS)); @@ -222,14 +234,14 @@ private void waitForFallbackAndDoRpcs(Deadline fallbackDeadline) throws Exceptio if (grpclbRouteType == GrpclbRouteType.GRPCLB_ROUTE_TYPE_FALLBACK) { logger.info("Made one successful RPC to a fallback. Now expect the " + "same for the rest."); - fellBack = true; + fallBack = true; break; } else { logger.info("Retryable RPC failure on iteration: " + fallbackRetryCount); } fallbackRetryCount++; } - if (!fellBack) { + if (!fallBack) { throw new AssertionError("Didn't fall back within deadline"); } for (int i = 0; i < 30; i++) { From 86ca55483bbe2b2238aaa333fa1025dcd6292209 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Tue, 21 Dec 2021 15:18:52 -0800 Subject: [PATCH 0031/2009] Update README etc to reference 1.43.1 (#8775) --- README.md | 30 ++++++++++++------------ cronet/README.md | 2 +- documentation/android-channel-builder.md | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 853b37e8c6a..0e25ca28534 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,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.43.0/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.43.0/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.43.1/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.43.1/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -43,17 +43,17 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.43.0 + 1.43.1 io.grpc grpc-protobuf - 1.43.0 + 1.43.1 io.grpc grpc-stub - 1.43.0 + 1.43.1 org.apache.tomcat @@ -65,23 +65,23 @@ 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 -implementation 'io.grpc:grpc-netty-shaded:1.43.0' -implementation 'io.grpc:grpc-protobuf:1.43.0' -implementation 'io.grpc:grpc-stub:1.43.0' +implementation 'io.grpc:grpc-netty-shaded:1.43.1' +implementation 'io.grpc:grpc-protobuf:1.43.1' +implementation 'io.grpc:grpc-stub:1.43.1' 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.43.0' -implementation 'io.grpc:grpc-protobuf-lite:1.43.0' -implementation 'io.grpc:grpc-stub:1.43.0' +implementation 'io.grpc:grpc-okhttp:1.43.1' +implementation 'io.grpc:grpc-protobuf-lite:1.43.1' +implementation 'io.grpc:grpc-stub:1.43.1' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.43.0 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.43.1 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -113,7 +113,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use com.google.protobuf:protoc:3.19.1:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.43.0:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.43.1:exe:${os.detected.classifier} @@ -143,7 +143,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.43.1' } } generateProtoTasks { @@ -176,7 +176,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.43.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.43.1' } } generateProtoTasks { diff --git a/cronet/README.md b/cronet/README.md index e7705acc3de..d53da56a8d7 100644 --- a/cronet/README.md +++ b/cronet/README.md @@ -26,7 +26,7 @@ In your app module's `build.gradle` file, include a dependency on both `grpc-cro Google Play Services Client Library for Cronet ``` -implementation 'io.grpc:grpc-cronet:1.43.0' +implementation 'io.grpc:grpc-cronet:1.43.1' implementation 'com.google.android.gms:play-services-cronet:16.0.0' ``` diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md index 3ebbf9522a4..09c0bef179a 100644 --- a/documentation/android-channel-builder.md +++ b/documentation/android-channel-builder.md @@ -36,8 +36,8 @@ In your `build.gradle` file, include a dependency on both `grpc-android` and `grpc-okhttp`: ``` -implementation 'io.grpc:grpc-android:1.43.0' -implementation 'io.grpc:grpc-okhttp:1.43.0' +implementation 'io.grpc:grpc-android:1.43.1' +implementation 'io.grpc:grpc-okhttp:1.43.1' ``` You also need permission to access the device's network state in your From 80f1be03f0dc347125765bd9360848f221a7f174 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 21 Dec 2021 16:39:31 -0800 Subject: [PATCH 0032/2009] Use xds-test-server-5 as the GCE interop server (#8777) --- buildscripts/kokoro/xds.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/kokoro/xds.sh b/buildscripts/kokoro/xds.sh index c43438213c3..83ba7fc864f 100755 --- a/buildscripts/kokoro/xds.sh +++ b/buildscripts/kokoro/xds.sh @@ -31,7 +31,7 @@ JAVA_OPTS=-Djava.util.logging.config.file=grpc-java/buildscripts/xds_logging.pro --test_case="all,circuit_breaking,timeout,fault_injection,csds" \ --project_id=grpc-testing \ --project_num=830293263384 \ - --source_image=projects/grpc-testing/global/images/xds-test-server-4 \ + --source_image=projects/grpc-testing/global/images/xds-test-server-5 \ --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \ --gcp_suffix=$(date '+%s') \ --verbose \ From e474e3dc7ebc0f4ba0b97ddbec445f200a30ec6f Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Tue, 4 Jan 2022 13:01:02 -0800 Subject: [PATCH 0033/2009] buildscripts: always make sure we are using jdk8 (#8800) --- buildscripts/kokoro/unix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/buildscripts/kokoro/unix.sh b/buildscripts/kokoro/unix.sh index 1de35827809..61d65324a07 100755 --- a/buildscripts/kokoro/unix.sh +++ b/buildscripts/kokoro/unix.sh @@ -24,6 +24,9 @@ fi cd $(dirname $0)/../.. # TODO(zpencer): always make sure we are using Oracle jdk8 +if [[ -f /usr/libexec/java_home ]]; then + JAVA_HOME=$(/usr/libexec/java_home -v"1.8.0") +fi # ARCH is x86_64 unless otherwise specified. ARCH="${ARCH:-x86_64}" From 24e345c06da7846053b8b3c86889e915160f34a4 Mon Sep 17 00:00:00 2001 From: Daniel Norberg Date: Tue, 4 Jan 2022 18:39:19 -0500 Subject: [PATCH 0034/2009] readme: grpc-netty-shaded runtime scope We should recommend runtime scope for grpc-netty-shaded. https://github.com/grpc/grpc-java/issues/8606#issuecomment-1004504316 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e25ca28534..610c637892b 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded 1.43.1 + runtime io.grpc @@ -65,7 +66,7 @@ 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 -implementation 'io.grpc:grpc-netty-shaded:1.43.1' +runtimeOnly 'io.grpc:grpc-netty-shaded:1.43.1' implementation 'io.grpc:grpc-protobuf:1.43.1' implementation 'io.grpc:grpc-stub:1.43.1' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ From 86b8b265ba5989d4b69e5015ba67c2db5e6954e7 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Wed, 5 Jan 2022 10:31:22 -0800 Subject: [PATCH 0035/2009] .github/workflows: publish test results for failed job The GitHub Actions Linux Testing only reports limited information (can not see full stacktrace, time consumed, or stderr from child threads) when unit tests fail. Adding a step to upload the test report to Artifacts if the test fails. If the test is successful, no artifacts will be uploaded. --- .github/workflows/testing.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ea883a77b04..609d0841494 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -53,6 +53,13 @@ jobs: - name: Build run: buildscripts/kokoro/unix.sh + - name: Post Failure Upload Test Reports to Artifacts + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: Test Reports (JRE ${{ matrix.jre }}) + path: ./*/build/reports/tests/** + retention-days: 14 - name: Check for modified codegen run: test -z "$(git status --porcelain)" || (git status && echo Error Working directory is not clean. Forget to commit generated files? && false) From 80c3be0f80a9d961a66751bd85a086e382104cd5 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Thu, 6 Jan 2022 09:08:50 -0800 Subject: [PATCH 0036/2009] Bump protobuf to 3.19.2 --- COMPILING.md | 4 ++-- build.gradle | 2 +- buildscripts/make_dependencies.bat | 2 +- buildscripts/make_dependencies.sh | 2 +- examples/android/clientcache/app/build.gradle | 2 +- examples/android/helloworld/app/build.gradle | 2 +- examples/android/routeguide/app/build.gradle | 2 +- examples/android/strictmode/app/build.gradle | 2 +- examples/build.gradle | 2 +- examples/example-alts/build.gradle | 2 +- examples/example-gauth/build.gradle | 2 +- examples/example-gauth/pom.xml | 2 +- examples/example-hostname/build.gradle | 2 +- examples/example-hostname/pom.xml | 2 +- examples/example-jwt-auth/build.gradle | 2 +- examples/example-jwt-auth/pom.xml | 4 ++-- examples/example-tls/build.gradle | 2 +- examples/example-tls/pom.xml | 2 +- examples/example-xds/build.gradle | 2 +- examples/pom.xml | 4 ++-- repositories.bzl | 12 ++++++------ 21 files changed, 29 insertions(+), 29 deletions(-) diff --git a/COMPILING.md b/COMPILING.md index d065e702842..3915c561db7 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -43,11 +43,11 @@ This section is only necessary if you are making changes to the code generation. Most users only need to use `skipCodegen=true` as discussed above. ### Build Protobuf -The codegen plugin is C++ code and requires protobuf 3.19.1 or later. +The codegen plugin is C++ code and requires protobuf 3.19.2 or later. For Linux, Mac and MinGW: ``` -$ PROTOBUF_VERSION=3.19.1 +$ PROTOBUF_VERSION=3.19.2 $ curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOBUF_VERSION/protobuf-all-$PROTOBUF_VERSION.tar.gz $ tar xzf protobuf-all-$PROTOBUF_VERSION.tar.gz $ cd protobuf-$PROTOBUF_VERSION diff --git a/build.gradle b/build.gradle index e3dcad2a0de..f68125fa5d7 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ subprojects { nettyVersion = '4.1.63.Final' guavaVersion = '30.1.1-android' googleauthVersion = '0.22.2' - protobufVersion = '3.19.1' + protobufVersion = '3.19.2' protocVersion = protobufVersion opencensusVersion = '0.28.0' autovalueVersion = '1.7.4' diff --git a/buildscripts/make_dependencies.bat b/buildscripts/make_dependencies.bat index b8586e85832..18c6086adab 100644 --- a/buildscripts/make_dependencies.bat +++ b/buildscripts/make_dependencies.bat @@ -1,4 +1,4 @@ -set PROTOBUF_VER=3.19.1 +set PROTOBUF_VER=3.19.2 set CMAKE_NAME=cmake-3.3.2-win32-x86 if not exist "protobuf-%PROTOBUF_VER%\cmake\build\Release\" ( diff --git a/buildscripts/make_dependencies.sh b/buildscripts/make_dependencies.sh index 7e132a91db0..5e7561c4313 100755 --- a/buildscripts/make_dependencies.sh +++ b/buildscripts/make_dependencies.sh @@ -3,7 +3,7 @@ # Build protoc set -evux -o pipefail -PROTOBUF_VERSION=3.19.1 +PROTOBUF_VERSION=3.19.2 # ARCH is x86_64 bit unless otherwise specified. ARCH="${ARCH:-x86_64}" diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 260255a1773..1b00d689488 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -32,7 +32,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.2' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 458a33584ea..82c4abe7550 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -30,7 +30,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.2' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index fb3fe7e8f95..8e33ac40d39 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -30,7 +30,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.2' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index 9472151bceb..7b3de25c3f5 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -31,7 +31,7 @@ android { } protobuf { - protoc { artifact = 'com.google.protobuf:protoc:3.19.1' } + protoc { artifact = 'com.google.protobuf:protoc:3.19.2' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/build.gradle b/examples/build.gradle index 3fe5c439e6d..e95cfd2f33c 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.19.1' +def protobufVersion = '3.19.2' def protocVersion = protobufVersion dependencies { diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index 7db8e672704..2cc4ac5afc9 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protocVersion = '3.19.1' +def protocVersion = '3.19.2' dependencies { // grpc-alts transitively depends on grpc-netty-shaded, grpc-protobuf, and grpc-stub diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 2a581f2822f..db4baf1cd38 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.19.1' +def protobufVersion = '3.19.2' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 765960c3bd3..2ccd6654757 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.19.1 + 3.19.2 1.7 1.7 diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index f18060097ea..e1476fe11f8 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.19.1' +def protobufVersion = '3.19.2' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index 1ce2438e8de..31445d405de 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.19.1 + 3.19.2 1.7 1.7 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index 18f08658b69..c1470dd693e 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protobufVersion = '3.19.1' +def protobufVersion = '3.19.2' def protocVersion = protobufVersion dependencies { diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 9fc68fb40c1..f026be38467 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -14,8 +14,8 @@ UTF-8 1.44.0-SNAPSHOT - 3.19.1 - 3.19.1 + 3.19.2 + 3.19.2 1.7 1.7 diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 98b73eec9c7..bd8d264b7f9 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // 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.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION -def protocVersion = '3.19.1' +def protocVersion = '3.19.2' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index bcb6ecd47c0..193e05fd812 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -13,7 +13,7 @@ UTF-8 1.44.0-SNAPSHOT - 3.19.1 + 3.19.2 2.0.34.Final 1.7 diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index f593a48050a..0ce7fbd56b5 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -24,7 +24,7 @@ targetCompatibility = 1.7 // updating the version in our release process. def grpcVersion = '1.44.0-SNAPSHOT' // CURRENT_GRPC_VERSION def nettyTcNativeVersion = '2.0.31.Final' -def protocVersion = '3.19.1' +def protocVersion = '3.19.2' dependencies { implementation "io.grpc:grpc-protobuf:${grpcVersion}" diff --git a/examples/pom.xml b/examples/pom.xml index 4a23872d05c..525fb616fa0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -13,8 +13,8 @@ UTF-8 1.44.0-SNAPSHOT - 3.19.1 - 3.19.1 + 3.19.2 + 3.19.2 1.7 1.7 diff --git a/repositories.bzl b/repositories.bzl index 6e9caf9409d..e5e5ccb0a55 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -98,18 +98,18 @@ def com_google_protobuf(): # This statement defines the @com_google_protobuf repo. http_archive( name = "com_google_protobuf", - sha256 = "25f1292d4ea6666f460a2a30038eef121e6c3937ae0f61d610611dfb14b0bd32", - strip_prefix = "protobuf-3.19.1", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.zip"], + sha256 = "9ceef0daf7e8be16cd99ac759271eb08021b53b1c7b6edd399953a76390234cd", + strip_prefix = "protobuf-3.19.2", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.2.zip"], ) def com_google_protobuf_javalite(): # java_lite_proto_library rules implicitly depend on @com_google_protobuf_javalite http_archive( name = "com_google_protobuf_javalite", - sha256 = "25f1292d4ea6666f460a2a30038eef121e6c3937ae0f61d610611dfb14b0bd32", - strip_prefix = "protobuf-3.19.1", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.zip"], + sha256 = "9ceef0daf7e8be16cd99ac759271eb08021b53b1c7b6edd399953a76390234cd", + strip_prefix = "protobuf-3.19.2", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.2.zip"], ) def io_grpc_grpc_proto(): From b32d2d2de9766987e900ce0c098937f1ae24dc15 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Thu, 6 Jan 2022 10:22:57 -0800 Subject: [PATCH 0037/2009] xds: parse ClusterSpecifierPlugin from RouteConfiguration in xDS response Implement the xds Client section of go/grpc-rls-in-xds#heading=h.9kitavdfxxiw --- .../java/io/grpc/xds/ClientXdsClient.java | 107 +++++- .../io/grpc/xds/ClusterSpecifierPlugin.java | 12 + .../xds/ClusterSpecifierPluginRegistry.java | 7 +- ...teLookupServiceClusterSpecifierPlugin.java | 2 +- .../main/java/io/grpc/xds/VirtualHost.java | 33 +- .../io/grpc/xds/ClientXdsClientDataTest.java | 357 ++++++++++++++++-- .../ClusterSpecifierPluginRegistryTest.java | 2 +- ...okupServiceClusterSpecifierPluginTest.java | 6 +- 8 files changed, 469 insertions(+), 57 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index 2b676553838..30c18cfe147 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -47,8 +47,10 @@ import io.envoyproxy.envoy.config.core.v3.SocketAddress; import io.envoyproxy.envoy.config.core.v3.SocketAddress.PortSpecifierCase; import io.envoyproxy.envoy.config.core.v3.TrafficDirection; +import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig; import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment; import io.envoyproxy.envoy.config.listener.v3.Listener; +import io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin; import io.envoyproxy.envoy.config.route.v3.RetryPolicy.RetryBackOff; import io.envoyproxy.envoy.config.route.v3.RouteConfiguration; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager; @@ -73,6 +75,8 @@ import io.grpc.xds.AbstractXdsClient.ResourceType; import io.grpc.xds.Bootstrapper.AuthorityInfo; import io.grpc.xds.Bootstrapper.ServerInfo; +import io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig; +import io.grpc.xds.ClusterSpecifierPlugin.PluginConfig; import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.Endpoints.LbEndpoint; import io.grpc.xds.Endpoints.LocalityLbEndpoints; @@ -150,6 +154,10 @@ final class ClientXdsClient extends XdsClient implements XdsResponseHandler, Res static boolean enableRbac = Strings.isNullOrEmpty(System.getenv("GRPC_XDS_EXPERIMENTAL_RBAC")) || Boolean.parseBoolean(System.getenv("GRPC_XDS_EXPERIMENTAL_RBAC")); + @VisibleForTesting + static boolean enableRouteLookup = + !Strings.isNullOrEmpty(System.getenv("GRPC_EXPERIMENTAL_XDS_RLS_LB")) + && Boolean.parseBoolean(System.getenv("GRPC_EXPERIMENTAL_XDS_RLS_LB")); private static final String TYPE_URL_HTTP_CONNECTION_MANAGER_V2 = "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2" @@ -857,18 +865,8 @@ static io.grpc.xds.HttpConnectionManager parseHttpConnectionManager( // Parse inlined RouteConfiguration or RDS. if (proto.hasRouteConfig()) { - List virtualHosts = new ArrayList<>(); - for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto - : proto.getRouteConfig().getVirtualHostsList()) { - StructOrError virtualHost = - parseVirtualHost(virtualHostProto, filterRegistry, parseHttpFilter); - if (virtualHost.getErrorDetail() != null) { - throw new ResourceInvalidException( - "HttpConnectionManager contains invalid virtual host: " - + virtualHost.getErrorDetail()); - } - virtualHosts.add(virtualHost.getStruct()); - } + List virtualHosts = extractVirtualHosts( + proto.getRouteConfig(), filterRegistry, parseHttpFilter); return io.grpc.xds.HttpConnectionManager.forVirtualHosts( maxStreamDuration, virtualHosts, filterConfigs); } @@ -950,11 +948,12 @@ static StructOrError parseHttpFilter( private static StructOrError parseVirtualHost( io.envoyproxy.envoy.config.route.v3.VirtualHost proto, FilterRegistry filterRegistry, - boolean parseHttpFilter) { + boolean parseHttpFilter, Map pluginConfigMap) { String name = proto.getName(); List routes = new ArrayList<>(proto.getRoutesCount()); for (io.envoyproxy.envoy.config.route.v3.Route routeProto : proto.getRoutesList()) { - StructOrError route = parseRoute(routeProto, filterRegistry, parseHttpFilter); + StructOrError route = parseRoute( + routeProto, filterRegistry, parseHttpFilter, pluginConfigMap); if (route == null) { continue; } @@ -1039,7 +1038,7 @@ static StructOrError> parseOverrideFilterConfigs( @Nullable static StructOrError parseRoute( io.envoyproxy.envoy.config.route.v3.Route proto, FilterRegistry filterRegistry, - boolean parseHttpFilter) { + boolean parseHttpFilter, Map pluginConfigMap) { StructOrError routeMatch = parseRouteMatch(proto.getMatch()); if (routeMatch == null) { return null; @@ -1065,7 +1064,7 @@ static StructOrError parseRoute( switch (proto.getActionCase()) { case ROUTE: StructOrError routeAction = - parseRouteAction(proto.getRoute(), filterRegistry, parseHttpFilter); + parseRouteAction(proto.getRoute(), filterRegistry, parseHttpFilter, pluginConfigMap); if (routeAction == null) { return null; } @@ -1218,7 +1217,7 @@ static StructOrError parseHeaderMatcher( @Nullable static StructOrError parseRouteAction( io.envoyproxy.envoy.config.route.v3.RouteAction proto, FilterRegistry filterRegistry, - boolean parseHttpFilter) { + boolean parseHttpFilter, Map pluginConfigMap) { Long timeoutNano = null; if (proto.hasMaxStreamDuration()) { io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration maxStreamDuration @@ -1297,6 +1296,20 @@ static StructOrError parseRouteAction( // TODO(chengyuanzhang): validate if the sum of weights equals to total weight. return StructOrError.fromStruct(RouteAction.forWeightedClusters( weightedClusters, hashPolicies, timeoutNano, retryPolicy)); + case CLUSTER_SPECIFIER_PLUGIN: + if (enableRouteLookup) { + String pluginName = proto.getClusterSpecifierPlugin(); + PluginConfig pluginConfig = pluginConfigMap.get(pluginName); + if (pluginConfig == null) { + return StructOrError.fromError( + "ClusterSpecifierPlugin for [" + pluginName + "] not found"); + } + NamedPluginConfig namedPluginConfig = NamedPluginConfig.create(pluginName, pluginConfig); + return StructOrError.fromStruct(RouteAction.forClusterSpecifierPlugin( + namedPluginConfig, hashPolicies, timeoutNano, retryPolicy)); + } else { + return StructOrError.fromError("Support for ClusterSpecifierPlugin not enabled"); + } case CLUSTERSPECIFIER_NOT_SET: default: return StructOrError.fromError( @@ -1432,18 +1445,74 @@ public void handleRdsResponse( private static RdsUpdate processRouteConfiguration( RouteConfiguration routeConfig, FilterRegistry filterRegistry, boolean parseHttpFilter) throws ResourceInvalidException { + return new RdsUpdate(extractVirtualHosts(routeConfig, filterRegistry, parseHttpFilter)); + } + + private static List extractVirtualHosts( + RouteConfiguration routeConfig, FilterRegistry filterRegistry, boolean parseHttpFilter) + throws ResourceInvalidException { + Map pluginConfigMap = new HashMap<>(); + if (enableRouteLookup) { + List plugins = routeConfig.getClusterSpecifierPluginsList(); + for (ClusterSpecifierPlugin plugin : plugins) { + PluginConfig existing = pluginConfigMap.put( + plugin.getExtension().getName(), parseClusterSpecifierPlugin(plugin)); + if (existing != null) { + throw new ResourceInvalidException( + "Multiple ClusterSpecifierPlugins with the same name: " + + plugin.getExtension().getName()); + } + } + } List virtualHosts = new ArrayList<>(routeConfig.getVirtualHostsCount()); for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto : routeConfig.getVirtualHostsList()) { StructOrError virtualHost = - parseVirtualHost(virtualHostProto, filterRegistry, parseHttpFilter); + parseVirtualHost(virtualHostProto, filterRegistry, parseHttpFilter, pluginConfigMap); if (virtualHost.getErrorDetail() != null) { throw new ResourceInvalidException( "RouteConfiguration contains invalid virtual host: " + virtualHost.getErrorDetail()); } virtualHosts.add(virtualHost.getStruct()); } - return new RdsUpdate(virtualHosts); + return virtualHosts; + } + + private static PluginConfig parseClusterSpecifierPlugin(ClusterSpecifierPlugin pluginProto) + throws ResourceInvalidException { + return parseClusterSpecifierPlugin( + pluginProto, ClusterSpecifierPluginRegistry.getDefaultRegistry()); + } + + @VisibleForTesting + static PluginConfig parseClusterSpecifierPlugin( + ClusterSpecifierPlugin pluginProto, ClusterSpecifierPluginRegistry registry) + throws ResourceInvalidException { + TypedExtensionConfig extension = pluginProto.getExtension(); + String pluginName = extension.getName(); + Any anyConfig = extension.getTypedConfig(); + String typeUrl = anyConfig.getTypeUrl(); + Message rawConfig = anyConfig; + if (typeUrl.equals(TYPE_URL_TYPED_STRUCT_UDPA) || typeUrl.equals(TYPE_URL_TYPED_STRUCT)) { + try { + TypedStruct typedStruct = unpackCompatibleType( + anyConfig, TypedStruct.class, TYPE_URL_TYPED_STRUCT_UDPA, TYPE_URL_TYPED_STRUCT); + typeUrl = typedStruct.getTypeUrl(); + rawConfig = typedStruct.getValue(); + } catch (InvalidProtocolBufferException e) { + throw new ResourceInvalidException( + "ClusterSpecifierPlugin [" + pluginName + "] contains invalid proto", e); + } + } + io.grpc.xds.ClusterSpecifierPlugin plugin = registry.get(typeUrl); + if (plugin == null) { + throw new ResourceInvalidException("Unsupported ClusterSpecifierPlugin type: " + typeUrl); + } + ConfigOrError pluginConfigOrError = plugin.parsePlugin(rawConfig); + if (pluginConfigOrError.errorDetail != null) { + throw new ResourceInvalidException(pluginConfigOrError.errorDetail); + } + return pluginConfigOrError.config; } @Override diff --git a/xds/src/main/java/io/grpc/xds/ClusterSpecifierPlugin.java b/xds/src/main/java/io/grpc/xds/ClusterSpecifierPlugin.java index 44de67b8295..1a0d4a82c28 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterSpecifierPlugin.java +++ b/xds/src/main/java/io/grpc/xds/ClusterSpecifierPlugin.java @@ -16,6 +16,7 @@ package io.grpc.xds; +import com.google.auto.value.AutoValue; import com.google.protobuf.Message; /** @@ -35,4 +36,15 @@ interface ClusterSpecifierPlugin { interface PluginConfig { String typeUrl(); } + + @AutoValue + abstract class NamedPluginConfig { + abstract String name(); + + abstract PluginConfig config(); + + static NamedPluginConfig create(String name, PluginConfig config) { + return new AutoValue_ClusterSpecifierPlugin_NamedPluginConfig(name, config); + } + } } diff --git a/xds/src/main/java/io/grpc/xds/ClusterSpecifierPluginRegistry.java b/xds/src/main/java/io/grpc/xds/ClusterSpecifierPluginRegistry.java index cf7b4cf523d..b81ee96b319 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterSpecifierPluginRegistry.java +++ b/xds/src/main/java/io/grpc/xds/ClusterSpecifierPluginRegistry.java @@ -16,6 +16,7 @@ package io.grpc.xds; +import com.google.common.annotations.VisibleForTesting; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; @@ -34,11 +35,13 @@ static synchronized ClusterSpecifierPluginRegistry getDefaultRegistry() { return instance; } - private static ClusterSpecifierPluginRegistry newRegistry() { + @VisibleForTesting + static ClusterSpecifierPluginRegistry newRegistry() { return new ClusterSpecifierPluginRegistry(); } - private ClusterSpecifierPluginRegistry register(ClusterSpecifierPlugin... plugins) { + @VisibleForTesting + ClusterSpecifierPluginRegistry register(ClusterSpecifierPlugin... plugins) { for (ClusterSpecifierPlugin plugin : plugins) { for (String typeUrl : plugin.typeUrls()) { supportedPlugins.put(typeUrl, plugin); diff --git a/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java b/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java index 64464f03737..3f843758eeb 100644 --- a/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java +++ b/xds/src/main/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPlugin.java @@ -33,7 +33,7 @@ final class RouteLookupServiceClusterSpecifierPlugin implements ClusterSpecifier new RouteLookupServiceClusterSpecifierPlugin(); private static final String TYPE_URL = - "type.googleapis.com/grpc.lookup.v1.RouteLookupConfig"; + "type.googleapis.com/grpc.lookup.v1.RouteLookupClusterSpecifier"; private RouteLookupServiceClusterSpecifierPlugin() {} diff --git a/xds/src/main/java/io/grpc/xds/VirtualHost.java b/xds/src/main/java/io/grpc/xds/VirtualHost.java index 24f66dd8934..d9f93dd3a07 100644 --- a/xds/src/main/java/io/grpc/xds/VirtualHost.java +++ b/xds/src/main/java/io/grpc/xds/VirtualHost.java @@ -26,6 +26,7 @@ import com.google.protobuf.Duration; import com.google.re2j.Pattern; import io.grpc.Status.Code; +import io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig; import io.grpc.xds.Filter.FilterConfig; import io.grpc.xds.internal.Matchers.FractionMatcher; import io.grpc.xds.internal.Matchers.HeaderMatcher; @@ -34,7 +35,7 @@ import java.util.Map; import javax.annotation.Nullable; -/** Reprsents an upstream virtual host. */ +/** Represents an upstream virtual host. */ @AutoValue abstract class VirtualHost { // The canonical name of this virtual host. @@ -159,6 +160,9 @@ abstract static class RouteAction { @Nullable abstract ImmutableList weightedClusters(); + @Nullable + abstract NamedPluginConfig namedClusterSpecifierPluginConfig(); + @Nullable abstract RetryPolicy retryPolicy(); @@ -166,7 +170,7 @@ static RouteAction forCluster( String cluster, List hashPolicies, @Nullable Long timeoutNano, @Nullable RetryPolicy retryPolicy) { checkNotNull(cluster, "cluster"); - return RouteAction.create(hashPolicies, timeoutNano, cluster, null, retryPolicy); + return RouteAction.create(hashPolicies, timeoutNano, cluster, null, null, retryPolicy); } static RouteAction forWeightedClusters( @@ -174,15 +178,32 @@ static RouteAction forWeightedClusters( @Nullable Long timeoutNano, @Nullable RetryPolicy retryPolicy) { checkNotNull(weightedClusters, "weightedClusters"); checkArgument(!weightedClusters.isEmpty(), "empty cluster list"); - return RouteAction.create(hashPolicies, timeoutNano, null, weightedClusters, retryPolicy); + return RouteAction.create( + hashPolicies, timeoutNano, null, weightedClusters, null, retryPolicy); + } + + static RouteAction forClusterSpecifierPlugin( + NamedPluginConfig namedConfig, + List hashPolicies, + @Nullable Long timeoutNano, + @Nullable RetryPolicy retryPolicy) { + checkNotNull(namedConfig, "namedConfig"); + return RouteAction.create(hashPolicies, timeoutNano, null, null, namedConfig, retryPolicy); } - private static RouteAction create(List hashPolicies, @Nullable Long timeoutNano, - @Nullable String cluster, @Nullable List weightedClusters, + private static RouteAction create( + List hashPolicies, + @Nullable Long timeoutNano, + @Nullable String cluster, + @Nullable List weightedClusters, + @Nullable NamedPluginConfig namedConfig, @Nullable RetryPolicy retryPolicy) { return new AutoValue_VirtualHost_Route_RouteAction( - ImmutableList.copyOf(hashPolicies), timeoutNano, cluster, + ImmutableList.copyOf(hashPolicies), + timeoutNano, + cluster, weightedClusters == null ? null : ImmutableList.copyOf(weightedClusters), + namedConfig, retryPolicy); } diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java index e14d6db45ac..44b36b9c5c5 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java @@ -18,9 +18,10 @@ import static com.google.common.truth.Truth.assertThat; -import com.github.xds.type.v3.TypedStruct; +import com.github.udpa.udpa.type.v1.TypedStruct; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.InvalidProtocolBufferException; @@ -72,6 +73,7 @@ import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.Header; import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter; import io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration; +import io.envoyproxy.envoy.config.route.v3.RouteConfiguration; import io.envoyproxy.envoy.config.route.v3.WeightedCluster; import io.envoyproxy.envoy.extensions.filters.common.fault.v3.FaultDelay; import io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort; @@ -102,12 +104,20 @@ import io.grpc.InsecureChannelCredentials; import io.grpc.LoadBalancer; import io.grpc.Status.Code; +import io.grpc.lookup.v1.GrpcKeyBuilder; +import io.grpc.lookup.v1.GrpcKeyBuilder.Name; +import io.grpc.lookup.v1.NameMatcher; +import io.grpc.lookup.v1.RouteLookupClusterSpecifier; +import io.grpc.lookup.v1.RouteLookupConfig; import io.grpc.xds.Bootstrapper.ServerInfo; import io.grpc.xds.ClientXdsClient.ResourceInvalidException; import io.grpc.xds.ClientXdsClient.StructOrError; +import io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig; +import io.grpc.xds.ClusterSpecifierPlugin.PluginConfig; import io.grpc.xds.Endpoints.LbEndpoint; import io.grpc.xds.Endpoints.LocalityLbEndpoints; import io.grpc.xds.Filter.FilterConfig; +import io.grpc.xds.RouteLookupServiceClusterSpecifierPlugin.RlsPluginConfig; import io.grpc.xds.VirtualHost.Route; import io.grpc.xds.VirtualHost.Route.RouteAction; import io.grpc.xds.VirtualHost.Route.RouteAction.ClusterWeight; @@ -145,6 +155,7 @@ public class ClientXdsClientDataTest { private final FilterRegistry filterRegistry = FilterRegistry.getDefaultRegistry(); private boolean originalEnableRetry; private boolean originalEnableRbac; + private boolean originalEnableRouteLookup; @Before public void setUp() { @@ -152,12 +163,15 @@ public void setUp() { assertThat(originalEnableRetry).isTrue(); originalEnableRbac = ClientXdsClient.enableRbac; assertThat(originalEnableRbac).isTrue(); + originalEnableRouteLookup = ClientXdsClient.enableRouteLookup; + assertThat(originalEnableRouteLookup).isFalse(); } @After public void tearDown() { ClientXdsClient.enableRetry = originalEnableRetry; ClientXdsClient.enableRbac = originalEnableRbac; + ClientXdsClient.enableRouteLookup = originalEnableRouteLookup; } @Test @@ -172,7 +186,8 @@ public void parseRoute_withRouteAction() { io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() .setCluster("cluster-foo")) .build(); - StructOrError struct = ClientXdsClient.parseRoute(proto, filterRegistry, false); + StructOrError struct = ClientXdsClient.parseRoute( + proto, filterRegistry, false, ImmutableMap.of()); assertThat(struct.getErrorDetail()).isNull(); assertThat(struct.getStruct()) .isEqualTo( @@ -194,7 +209,8 @@ public void parseRoute_withNonForwardingAction() { .setPath("/service/method")) .setNonForwardingAction(NonForwardingAction.getDefaultInstance()) .build(); - StructOrError struct = ClientXdsClient.parseRoute(proto, filterRegistry, false); + StructOrError struct = ClientXdsClient.parseRoute( + proto, filterRegistry, false, ImmutableMap.of()); assertThat(struct.getStruct()) .isEqualTo( Route.forNonForwardingAction( @@ -212,7 +228,8 @@ public void parseRoute_withUnsupportedActionTypes() { .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath("")) .setRedirect(RedirectAction.getDefaultInstance()) .build(); - res = ClientXdsClient.parseRoute(redirectRoute, filterRegistry, false); + res = ClientXdsClient.parseRoute( + redirectRoute, filterRegistry, false, ImmutableMap.of()); assertThat(res.getStruct()).isNull(); assertThat(res.getErrorDetail()) .isEqualTo("Route [route-blade] with unknown action type: REDIRECT"); @@ -223,7 +240,8 @@ public void parseRoute_withUnsupportedActionTypes() { .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath("")) .setDirectResponse(DirectResponseAction.getDefaultInstance()) .build(); - res = ClientXdsClient.parseRoute(directResponseRoute, filterRegistry, false); + res = ClientXdsClient.parseRoute( + directResponseRoute, filterRegistry, false, ImmutableMap.of()); assertThat(res.getStruct()).isNull(); assertThat(res.getErrorDetail()) .isEqualTo("Route [route-blade] with unknown action type: DIRECT_RESPONSE"); @@ -234,7 +252,8 @@ public void parseRoute_withUnsupportedActionTypes() { .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath("")) .setFilterAction(FilterAction.getDefaultInstance()) .build(); - res = ClientXdsClient.parseRoute(filterRoute, filterRegistry, false); + res = ClientXdsClient.parseRoute( + filterRoute, filterRegistry, false, ImmutableMap.of()); assertThat(res.getStruct()).isNull(); assertThat(res.getErrorDetail()) .isEqualTo("Route [route-blade] with unknown action type: FILTER_ACTION"); @@ -255,7 +274,9 @@ public void parseRoute_skipRouteWithUnsupportedMatcher() { io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() .setCluster("cluster-foo")) .build(); - assertThat(ClientXdsClient.parseRoute(proto, filterRegistry, false)).isNull(); + assertThat(ClientXdsClient.parseRoute( + proto, filterRegistry, false, ImmutableMap.of())) + .isNull(); } @Test @@ -270,7 +291,9 @@ public void parseRoute_skipRouteWithUnsupportedAction() { io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() .setClusterHeader("cluster header")) // cluster_header action not supported .build(); - assertThat(ClientXdsClient.parseRoute(proto, filterRegistry, false)).isNull(); + assertThat(ClientXdsClient.parseRoute( + proto, filterRegistry, false, ImmutableMap.of())) + .isNull(); } @Test @@ -456,7 +479,8 @@ public void parseRouteAction_withCluster() { .setCluster("cluster-foo") .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()).isNull(); assertThat(struct.getStruct().cluster()).isEqualTo("cluster-foo"); assertThat(struct.getStruct().weightedClusters()).isNull(); @@ -479,7 +503,8 @@ public void parseRouteAction_withWeightedCluster() { .setWeight(UInt32Value.newBuilder().setValue(70)))) .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()).isNull(); assertThat(struct.getStruct().cluster()).isNull(); assertThat(struct.getStruct().weightedClusters()).containsExactly( @@ -498,7 +523,8 @@ public void parseRouteAction_withTimeoutByGrpcTimeoutHeaderMax() { .setMaxStreamDuration(Durations.fromMillis(20L))) .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L)); } @@ -512,7 +538,8 @@ public void parseRouteAction_withTimeoutByMaxStreamDuration() { .setMaxStreamDuration(Durations.fromSeconds(5L))) .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L)); } @@ -523,7 +550,8 @@ public void parseRouteAction_withTimeoutUnset() { .setCluster("cluster-foo") .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().timeoutNano()).isNull(); } @@ -545,7 +573,8 @@ public void parseRouteAction_withRetryPolicy() { .setRetryPolicy(builder.build()) .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); RouteAction.RetryPolicy retryPolicy = struct.getStruct().retryPolicy(); assertThat(retryPolicy.maxAttempts()).isEqualTo(4); assertThat(retryPolicy.initialBackoff()).isEqualTo(Durations.fromMillis(500)); @@ -568,7 +597,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder.build()) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().retryPolicy()).isNotNull(); assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()).isEmpty(); @@ -580,7 +610,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()).isEqualTo("No base_interval specified in retry_backoff"); // max_interval unset @@ -589,7 +620,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); retryPolicy = struct.getStruct().retryPolicy(); assertThat(retryPolicy.maxBackoff()).isEqualTo(Durations.fromMillis(500 * 10)); @@ -599,7 +631,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()) .isEqualTo("base_interval in retry_backoff must be positive"); @@ -611,7 +644,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()) .isEqualTo("max_interval in retry_backoff cannot be less than base_interval"); @@ -623,7 +657,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getErrorDetail()) .isEqualTo("max_interval in retry_backoff cannot be less than base_interval"); @@ -635,7 +670,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().retryPolicy().initialBackoff()) .isEqualTo(Durations.fromMillis(1)); assertThat(struct.getStruct().retryPolicy().maxBackoff()) @@ -650,7 +686,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); retryPolicy = struct.getStruct().retryPolicy(); assertThat(retryPolicy.initialBackoff()).isEqualTo(Durations.fromMillis(25)); assertThat(retryPolicy.maxBackoff()).isEqualTo(Durations.fromMillis(250)); @@ -668,7 +705,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()) .containsExactly(Code.CANCELLED); @@ -685,7 +723,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()) .containsExactly(Code.CANCELLED); @@ -702,7 +741,8 @@ public void parseRouteAction_withRetryPolicy() { .setCluster("cluster-foo") .setRetryPolicy(builder) .build(); - struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()) .containsExactly(Code.CANCELLED); } @@ -739,7 +779,8 @@ public void parseRouteAction_withHashPolicies() { QueryParameter.newBuilder().setName("param"))) // unsupported .build(); StructOrError struct = - ClientXdsClient.parseRouteAction(proto, filterRegistry, false); + ClientXdsClient.parseRouteAction(proto, filterRegistry, false, + ImmutableMap.of()); List policies = struct.getStruct().hashPolicies(); assertThat(policies).hasSize(2); assertThat(policies.get(0).type()).isEqualTo(HashPolicy.Type.HEADER); @@ -1339,6 +1380,270 @@ public void parseHttpConnectionManager_emptyFilters() throws ResourceInvalidExce true /* does not matter */); } + @Test + public void parseHttpConnectionManager_clusterSpecifierPlugin() throws Exception { + ClientXdsClient.enableRouteLookup = true; + RouteLookupConfig routeLookupConfig = RouteLookupConfig.newBuilder() + .addGrpcKeybuilders( + GrpcKeyBuilder.newBuilder() + .addNames(Name.newBuilder().setService("service1")) + .addNames(Name.newBuilder().setService("service2")) + .addHeaders( + NameMatcher.newBuilder().setKey("key1").addNames("v1").setRequiredMatch(true))) + .setLookupService("rls-cbt.googleapis.com") + .setLookupServiceTimeout(Durations.fromMillis(1234)) + .setCacheSizeBytes(5000) + .addValidTargets("valid-target") + .build(); + RouteLookupClusterSpecifier specifier = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig).build(); + TypedExtensionConfig typedExtensionConfig = TypedExtensionConfig.newBuilder() + .setName("rls-plugin-1") + .setTypedConfig(Any.pack(specifier)) + .build(); + io.envoyproxy.envoy.config.route.v3.Route route = + io.envoyproxy.envoy.config.route.v3.Route.newBuilder() + .setName("route-1") + .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPrefix("")) + .setRoute(io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() + .setClusterSpecifierPlugin("rls-plugin-1")) + .build(); + HttpConnectionManager hcm = + HttpConnectionManager.newBuilder() + .setRouteConfig( + RouteConfiguration.newBuilder() + .addClusterSpecifierPlugins( + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(typedExtensionConfig) + .build()) + .addVirtualHosts(io.envoyproxy.envoy.config.route.v3.VirtualHost.newBuilder() + .setName("virtual-host-1") + .addRoutes(route))) + .build(); + + io.grpc.xds.HttpConnectionManager parsedHcm = ClientXdsClient.parseHttpConnectionManager( + hcm, new HashSet(), filterRegistry, false /* parseHttpFilter */, + true /* does not matter */); + + VirtualHost virtualHost = Iterables.getOnlyElement(parsedHcm.virtualHosts()); + Route parsedRoute = Iterables.getOnlyElement(virtualHost.routes()); + NamedPluginConfig namedPluginConfig = + parsedRoute.routeAction().namedClusterSpecifierPluginConfig(); + assertThat(namedPluginConfig.name()).isEqualTo("rls-plugin-1"); + assertThat(namedPluginConfig.config()).isInstanceOf(RlsPluginConfig.class); + } + + @Test + public void parseHttpConnectionManager_duplicatePluginName() throws Exception { + ClientXdsClient.enableRouteLookup = true; + RouteLookupConfig routeLookupConfig1 = RouteLookupConfig.newBuilder() + .addGrpcKeybuilders( + GrpcKeyBuilder.newBuilder() + .addNames(Name.newBuilder().setService("service1")) + .addNames(Name.newBuilder().setService("service2")) + .addHeaders( + NameMatcher.newBuilder().setKey("key1").addNames("v1").setRequiredMatch(true))) + .setLookupService("rls-cbt.googleapis.com") + .setLookupServiceTimeout(Durations.fromMillis(1234)) + .setCacheSizeBytes(5000) + .addValidTargets("valid-target") + .build(); + RouteLookupClusterSpecifier specifier1 = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig1).build(); + RouteLookupConfig routeLookupConfig2 = RouteLookupConfig.newBuilder() + .addGrpcKeybuilders( + GrpcKeyBuilder.newBuilder() + .addNames(Name.newBuilder().setService("service3")) + .addHeaders( + NameMatcher.newBuilder().setKey("key1").addNames("v1").setRequiredMatch(true))) + .setLookupService("rls-cbt.googleapis.com") + .setLookupServiceTimeout(Durations.fromMillis(1234)) + .setCacheSizeBytes(5000) + .addValidTargets("valid-target") + .build(); + RouteLookupClusterSpecifier specifier2 = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig2).build(); + TypedExtensionConfig typedExtensionConfig = TypedExtensionConfig.newBuilder() + .setName("rls-plugin-1") + .setTypedConfig(Any.pack(specifier1)) + .build(); + TypedExtensionConfig typedExtensionConfig2 = TypedExtensionConfig.newBuilder() + .setName("rls-plugin-1") + .setTypedConfig(Any.pack(specifier2)) + .build(); + io.envoyproxy.envoy.config.route.v3.Route route = + io.envoyproxy.envoy.config.route.v3.Route.newBuilder() + .setName("route-1") + .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPrefix("")) + .setRoute(io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() + .setClusterSpecifierPlugin("rls-plugin-1")) + .build(); + HttpConnectionManager hcm = + HttpConnectionManager.newBuilder() + .setRouteConfig( + RouteConfiguration.newBuilder() + .addClusterSpecifierPlugins( + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(typedExtensionConfig) + .build()) + .addClusterSpecifierPlugins( + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(typedExtensionConfig2) + .build()) + .addVirtualHosts(io.envoyproxy.envoy.config.route.v3.VirtualHost.newBuilder() + .setName("virtual-host-1") + .addRoutes(route))) + .build(); + + thrown.expect(ResourceInvalidException.class); + thrown.expectMessage("Multiple ClusterSpecifierPlugins with the same name: rls-plugin-1"); + + ClientXdsClient.parseHttpConnectionManager( + hcm, new HashSet(), filterRegistry, false /* parseHttpFilter */, + true /* does not matter */); + } + + @Test + public void parseHttpConnectionManager_pluginNameNotFound() throws Exception { + ClientXdsClient.enableRouteLookup = true; + RouteLookupConfig routeLookupConfig = RouteLookupConfig.newBuilder() + .addGrpcKeybuilders( + GrpcKeyBuilder.newBuilder() + .addNames(Name.newBuilder().setService("service1")) + .addNames(Name.newBuilder().setService("service2")) + .addHeaders( + NameMatcher.newBuilder().setKey("key1").addNames("v1").setRequiredMatch(true))) + .setLookupService("rls-cbt.googleapis.com") + .setLookupServiceTimeout(Durations.fromMillis(1234)) + .setCacheSizeBytes(5000) + .addValidTargets("valid-target") + .build(); + RouteLookupClusterSpecifier specifier = + RouteLookupClusterSpecifier.newBuilder().setRouteLookupConfig(routeLookupConfig).build(); + TypedExtensionConfig typedExtensionConfig = TypedExtensionConfig.newBuilder() + .setName("rls-plugin-1") + .setTypedConfig(Any.pack(specifier)) + .build(); + io.envoyproxy.envoy.config.route.v3.Route route = + io.envoyproxy.envoy.config.route.v3.Route.newBuilder() + .setName("route-1") + .setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPrefix("")) + .setRoute(io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder() + .setClusterSpecifierPlugin("invalid-plugin-name")) + .build(); + HttpConnectionManager hcm = + HttpConnectionManager.newBuilder() + .setRouteConfig( + RouteConfiguration.newBuilder() + .addClusterSpecifierPlugins( + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(typedExtensionConfig) + .build()) + .addVirtualHosts(io.envoyproxy.envoy.config.route.v3.VirtualHost.newBuilder() + .setName("virtual-host-1") + .addRoutes(route))) + .build(); + + thrown.expect(ResourceInvalidException.class); + thrown.expectMessage("ClusterSpecifierPlugin for [invalid-plugin-name] not found"); + + ClientXdsClient.parseHttpConnectionManager( + hcm, new HashSet(), filterRegistry, false /* parseHttpFilter */, + true /* does not matter */); + } + + @Test + public void parseClusterSpecifierPlugin_typedStructInTypedExtension() throws Exception { + class TestPluginConfig implements PluginConfig { + @Override + public String typeUrl() { + return "type.googleapis.com/google.protobuf.Empty"; + } + } + + ClusterSpecifierPluginRegistry registry = ClusterSpecifierPluginRegistry.newRegistry(); + registry.register(new ClusterSpecifierPlugin() { + @Override + public String[] typeUrls() { + return new String[] { + "type.googleapis.com/google.protobuf.Empty", + }; + } + + @Override + public ConfigOrError parsePlugin(Message rawProtoMessage) { + return ConfigOrError.fromConfig(new TestPluginConfig()); + } + }); + + TypedStruct typedStruct = TypedStruct.newBuilder() + .setTypeUrl("type.googleapis.com/google.protobuf.Empty") + .setValue(Struct.newBuilder()) + .build(); + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin pluginProto = + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(TypedExtensionConfig.newBuilder() + .setTypedConfig(Any.pack(typedStruct))) + .build(); + + PluginConfig pluginConfig = ClientXdsClient.parseClusterSpecifierPlugin(pluginProto, registry); + assertThat(pluginConfig).isInstanceOf(TestPluginConfig.class); + } + + @Test + public void parseClusterSpecifierPlugin_v3TypedStructInTypedExtension() throws Exception { + class TestPluginConfig implements PluginConfig { + @Override + public String typeUrl() { + return "type.googleapis.com/google.protobuf.Empty"; + } + } + + ClusterSpecifierPluginRegistry registry = ClusterSpecifierPluginRegistry.newRegistry(); + registry.register(new ClusterSpecifierPlugin() { + @Override + public String[] typeUrls() { + return new String[] { + "type.googleapis.com/google.protobuf.Empty", + }; + } + + @Override + public ConfigOrError parsePlugin(Message rawProtoMessage) { + return ConfigOrError.fromConfig(new TestPluginConfig()); + } + }); + + com.github.xds.type.v3.TypedStruct typedStruct = com.github.xds.type.v3.TypedStruct.newBuilder() + .setTypeUrl("type.googleapis.com/google.protobuf.Empty") + .setValue(Struct.newBuilder()) + .build(); + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin pluginProto = + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(TypedExtensionConfig.newBuilder() + .setTypedConfig(Any.pack(typedStruct))) + .build(); + + PluginConfig pluginConfig = ClientXdsClient.parseClusterSpecifierPlugin(pluginProto, registry); + assertThat(pluginConfig).isInstanceOf(TestPluginConfig.class); + } + + @Test + public void parseClusterSpecifierPlugin_unregisteredPlugin() throws Exception { + ClusterSpecifierPluginRegistry registry = ClusterSpecifierPluginRegistry.newRegistry(); + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin pluginProto = + io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin.newBuilder() + .setExtension(TypedExtensionConfig.newBuilder() + .setTypedConfig(Any.pack(StringValue.of("unregistered")))) + .build(); + + thrown.expect(ResourceInvalidException.class); + thrown.expectMessage( + "Unsupported ClusterSpecifierPlugin type: type.googleapis.com/google.protobuf.StringValue"); + + ClientXdsClient.parseClusterSpecifierPlugin(pluginProto, registry); + } + @Test public void parseCluster_ringHashLbPolicy_defaultLbConfig() throws ResourceInvalidException { Cluster cluster = Cluster.newBuilder() diff --git a/xds/src/test/java/io/grpc/xds/ClusterSpecifierPluginRegistryTest.java b/xds/src/test/java/io/grpc/xds/ClusterSpecifierPluginRegistryTest.java index 7f04a2a7f39..27ad72a7683 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterSpecifierPluginRegistryTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterSpecifierPluginRegistryTest.java @@ -28,7 +28,7 @@ public class ClusterSpecifierPluginRegistryTest { @Test public void pluginsInGlobaalInstance() { assertThat(ClusterSpecifierPluginRegistry.getDefaultRegistry() - .get("type.googleapis.com/grpc.lookup.v1.RouteLookupConfig")) + .get("type.googleapis.com/grpc.lookup.v1.RouteLookupClusterSpecifier")) .isEqualTo(RouteLookupServiceClusterSpecifierPlugin.INSTANCE); } } diff --git a/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java b/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java index f8d1c2ef7c0..c883a9d257d 100644 --- a/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java +++ b/xds/src/test/java/io/grpc/xds/RouteLookupServiceClusterSpecifierPluginTest.java @@ -62,7 +62,8 @@ public void parseConfigWithAllFieldsGiven() { RlsPluginConfig config = RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(specifier)) .config; - assertThat(config.typeUrl()).isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupConfig"); + assertThat(config.typeUrl()) + .isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupClusterSpecifier"); assertThat(config.config()).isEqualTo( ImmutableMap.builder() .put( @@ -110,7 +111,8 @@ public void parseConfigWithOptionalFieldsUnspecified() { RlsPluginConfig config = RouteLookupServiceClusterSpecifierPlugin.INSTANCE.parsePlugin(Any.pack(specifier)) .config; - assertThat(config.typeUrl()).isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupConfig"); + assertThat(config.typeUrl()) + .isEqualTo("type.googleapis.com/grpc.lookup.v1.RouteLookupClusterSpecifier"); assertThat(config.config()).isEqualTo( ImmutableMap.builder() .put( From 6f223920a6c6c8d8014c528c5abdac984b14dd15 Mon Sep 17 00:00:00 2001 From: Sergii Tkachenko Date: Wed, 5 Jan 2022 16:03:52 -0800 Subject: [PATCH 0038/2009] xds: Rename parseCluster() back to processCluster() for consistency This is to keep names of the top-level process* functions called from handle*Response functions, and returning *Update resources consistent: - `handleLdsResponse()` -> `LdsUpdate processClientSideListener()` `LdsUpdate processServerSideListener()` - `handleCdsResponse()` -> `CdsUpdate processCluster()` - `handleRdsResponse()` -> `RdsUpdate processRouteConfiguration()` - `handleEdsResponse()` -> `EdsUpdate processClusterLoadAssignment()` For some reason, processCluster() was renamed to parseCluster() in fa4b980e0. --- xds/src/main/java/io/grpc/xds/ClientXdsClient.java | 5 +++-- .../test/java/io/grpc/xds/ClientXdsClientDataTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java index 30c18cfe147..222191ad55b 100644 --- a/xds/src/main/java/io/grpc/xds/ClientXdsClient.java +++ b/xds/src/main/java/io/grpc/xds/ClientXdsClient.java @@ -1554,7 +1554,8 @@ public void handleCdsResponse( if (getBootstrapInfo() != null && getBootstrapInfo().certProviders() != null) { certProviderInstances = getBootstrapInfo().certProviders().keySet(); } - cdsUpdate = parseCluster(cluster, retainedEdsResources, certProviderInstances, serverInfo); + cdsUpdate = + processCluster(cluster, retainedEdsResources, certProviderInstances, serverInfo); } catch (ResourceInvalidException e) { errors.add( "CDS response Cluster '" + clusterName + "' validation error: " + e.getMessage()); @@ -1572,7 +1573,7 @@ public void handleCdsResponse( } @VisibleForTesting - static CdsUpdate parseCluster(Cluster cluster, Set retainedEdsResources, + static CdsUpdate processCluster(Cluster cluster, Set retainedEdsResources, Set certProviderInstances, ServerInfo serverInfo) throws ResourceInvalidException { StructOrError structOrError; diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java index 44b36b9c5c5..940d96fd10e 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java @@ -1658,7 +1658,7 @@ public void parseCluster_ringHashLbPolicy_defaultLbConfig() throws ResourceInval .setLbPolicy(LbPolicy.RING_HASH) .build(); - CdsUpdate update = ClientXdsClient.parseCluster( + CdsUpdate update = ClientXdsClient.processCluster( cluster, new HashSet(), null, LRS_SERVER_INFO); assertThat(update.lbPolicy()).isEqualTo(CdsUpdate.LbPolicy.RING_HASH); assertThat(update.minRingSize()) @@ -1686,7 +1686,7 @@ public void parseCluster_transportSocketMatches_exception() throws ResourceInval thrown.expect(ResourceInvalidException.class); thrown.expectMessage( "Cluster cluster-foo.googleapis.com: transport-socket-matches not supported."); - ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); + ClientXdsClient.processCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test @@ -1711,7 +1711,7 @@ public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_minGreaterThanMa thrown.expect(ResourceInvalidException.class); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); - ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); + ClientXdsClient.processCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test @@ -1738,7 +1738,7 @@ public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_tooLargeRingSize thrown.expect(ResourceInvalidException.class); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); - ClientXdsClient.parseCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); + ClientXdsClient.processCluster(cluster, new HashSet(), null, LRS_SERVER_INFO); } @Test From 3ad4d9bfb7f7407ec0b9637ee1de508051192676 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Fri, 7 Jan 2022 08:13:32 -0800 Subject: [PATCH 0039/2009] all: clean up code related to android api level less than 19 --- .../integrationtest/InteropInstrumentationTest.java | 8 -------- api/build.gradle | 2 +- auth/build.gradle | 2 +- context/build.gradle | 2 +- core/build.gradle | 2 +- .../main/java/io/grpc/internal/ProxyDetectorImpl.java | 9 +-------- okhttp/build.gradle | 2 +- protobuf-lite/build.gradle | 2 +- stub/build.gradle | 2 +- 9 files changed, 8 insertions(+), 23 deletions(-) diff --git a/android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/InteropInstrumentationTest.java b/android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/InteropInstrumentationTest.java index e6a2c85fda5..abcf9e08593 100644 --- a/android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/InteropInstrumentationTest.java +++ b/android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/InteropInstrumentationTest.java @@ -20,7 +20,6 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import com.google.android.gms.common.GooglePlayServicesNotAvailableException; import com.google.android.gms.common.GooglePlayServicesRepairableException; @@ -30,7 +29,6 @@ import java.io.InputStream; import java.util.concurrent.TimeUnit; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,12 +44,6 @@ public class InteropInstrumentationTest { private boolean useTestCa; private String testCase; - // Ensures Looper is initialized for tests running on API level 15. Otherwise instantiating an - // AsyncTask throws an exception. - @Rule - public ActivityTestRule activityRule = - new ActivityTestRule(TesterActivity.class); - @Before public void setUp() throws Exception { host = InstrumentationRegistry.getArguments().getString("server_host", "10.0.2.2"); diff --git a/api/build.gradle b/api/build.gradle index a959fed4ea9..fa58c96ef8a 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -25,7 +25,7 @@ dependencies { jmh project(':grpc-core') signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } javadoc { diff --git a/auth/build.gradle b/auth/build.gradle index 233de359b49..791402fce59 100644 --- a/auth/build.gradle +++ b/auth/build.gradle @@ -14,5 +14,5 @@ dependencies { testImplementation project(':grpc-testing'), libraries.google_auth_oauth2_http signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } diff --git a/context/build.gradle b/context/build.gradle index 4512cc56f0a..909a7472b1e 100644 --- a/context/build.gradle +++ b/context/build.gradle @@ -15,5 +15,5 @@ dependencies { exclude group: 'junit', module: 'junit' } signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } diff --git a/core/build.gradle b/core/build.gradle index 14cfbb70497..e62ae8a804b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,7 +43,7 @@ dependencies { jmh project(':grpc-testing') signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } javadoc { diff --git a/core/src/main/java/io/grpc/internal/ProxyDetectorImpl.java b/core/src/main/java/io/grpc/internal/ProxyDetectorImpl.java index 3e7dd010e22..0cc1dd3aaca 100644 --- a/core/src/main/java/io/grpc/internal/ProxyDetectorImpl.java +++ b/core/src/main/java/io/grpc/internal/ProxyDetectorImpl.java @@ -202,14 +202,7 @@ public ProxiedSocketAddress proxyFor(SocketAddress targetServerAddress) throws I private ProxiedSocketAddress detectProxy(InetSocketAddress targetAddr) throws IOException { URI uri; - String host; - try { - host = GrpcUtil.getHost(targetAddr); - } catch (Throwable t) { - // Workaround for Android API levels < 19 if getHostName causes a NetworkOnMainThreadException - log.log(Level.WARNING, "Failed to get host for proxy lookup, proceeding without proxy", t); - return null; - } + String host = GrpcUtil.getHost(targetAddr); try { uri = new URI( diff --git a/okhttp/build.gradle b/okhttp/build.gradle index 999f21e7c10..3271118feda 100644 --- a/okhttp/build.gradle +++ b/okhttp/build.gradle @@ -22,7 +22,7 @@ dependencies { project(':grpc-testing'), project(':grpc-netty') signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } project.sourceSets { diff --git a/protobuf-lite/build.gradle b/protobuf-lite/build.gradle index 7b58309c414..75cca43f0e6 100644 --- a/protobuf-lite/build.gradle +++ b/protobuf-lite/build.gradle @@ -18,7 +18,7 @@ dependencies { testImplementation project(':grpc-core') signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } compileTestJava { diff --git a/stub/build.gradle b/stub/build.gradle index 2b5a6a4edb6..7d8040a87c2 100644 --- a/stub/build.gradle +++ b/stub/build.gradle @@ -14,7 +14,7 @@ dependencies { testImplementation libraries.truth, project(':grpc-testing') signature "org.codehaus.mojo.signature:java17:1.0@signature" - signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" + signature "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4@signature" } javadoc { From 5ae6f9ca2597fef96ce0cbe0957250d6b08be4bd Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Fri, 7 Jan 2022 09:52:26 -0800 Subject: [PATCH 0040/2009] all: Upgrade Android plugin to 4.2.0 - bump android plugin version to 4.2.0 - migrate deprecated android.support dependencies to androidx dependencies - bump `targetSdkVersion` to 29 - temporarily ignore lint error for 'MissingClass' due to #8799 - run android CIs with `-Pandroid.useAndroidX=true -Pandroid.enableJetifier=true` flags - android examples are still using android.support dependencies, will not be updated in this PR. --- COMPILING.md | 1 + android-interop-testing/build.gradle | 17 ++++++++++------- .../src/main/AndroidManifest.xml | 2 +- .../android/integrationtest/TesterActivity.java | 2 +- .../TesterOkHttpChannelBuilder.java | 2 +- buildscripts/kokoro/android-interop.sh | 8 +++++--- buildscripts/kokoro/android.sh | 7 +++++-- buildscripts/kokoro/linux_artifacts.sh | 10 +++++++--- settings.gradle | 4 ++-- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/COMPILING.md b/COMPILING.md index 3915c561db7..aef4cf61b66 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -15,6 +15,7 @@ Some parts of grpc-java depend on Android. Since many Java developers don't have the Android SDK installed and don't need to run or modify the Android components, the build can skip it. To skip, create the file `/gradle.properties` and add `skipAndroid=true`. +Otherwise, create the file `/gradle.properties` and add `android.useAndroidX=true`. Then, to build, run: ``` diff --git a/android-interop-testing/build.gradle b/android-interop-testing/build.gradle index 8f1c0849e9e..b18d84e2625 100644 --- a/android-interop-testing/build.gradle +++ b/android-interop-testing/build.gradle @@ -29,12 +29,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - compileSdkVersion 26 + compileSdkVersion 29 defaultConfig { applicationId "io.grpc.android.integrationtest" minSdkVersion 19 - targetSdkVersion 26 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -47,14 +47,17 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - lintOptions { disable 'InvalidPackage', 'HardcodedText' } + lintOptions { + disable 'InvalidPackage', 'HardcodedText', + 'MissingClass' // https://github.com/grpc/grpc-java/issues/8799 + } } dependencies { - implementation 'com.android.support:appcompat-v7:26.1.0' - implementation 'com.android.support:multidex:1.0.3' - implementation 'com.android.support:support-annotations:26.1.0' - implementation 'com.google.android.gms:play-services-base:16.1.0' + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'androidx.multidex:multidex:2.0.0' + implementation libraries.androidx_annotation + implementation 'com.google.android.gms:play-services-base:18.0.1' implementation project(':grpc-auth'), project(':grpc-census'), diff --git a/android-interop-testing/src/main/AndroidManifest.xml b/android-interop-testing/src/main/AndroidManifest.xml index 2e1e2c696d8..d9ce28630e0 100644 --- a/android-interop-testing/src/main/AndroidManifest.xml +++ b/android-interop-testing/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/Base.V7.Theme.AppCompat.Light" - android:name="android.support.multidex.MultiDexApplication" > + android:name="androidx.multidex.MultiDexApplication" > diff --git a/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterActivity.java b/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterActivity.java index 004950e7380..d4358ddf945 100644 --- a/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterActivity.java +++ b/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterActivity.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -28,6 +27,7 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; +import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.security.ProviderInstaller; import io.grpc.ManagedChannel; import java.io.InputStream; diff --git a/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterOkHttpChannelBuilder.java b/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterOkHttpChannelBuilder.java index f4d8f5abcdc..a663378dbf3 100644 --- a/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterOkHttpChannelBuilder.java +++ b/android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterOkHttpChannelBuilder.java @@ -16,7 +16,7 @@ package io.grpc.android.integrationtest; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import io.grpc.ChannelCredentials; import io.grpc.Grpc; import io.grpc.InsecureChannelCredentials; diff --git a/buildscripts/kokoro/android-interop.sh b/buildscripts/kokoro/android-interop.sh index 50523c8e88e..3046d9bb9e8 100755 --- a/buildscripts/kokoro/android-interop.sh +++ b/buildscripts/kokoro/android-interop.sh @@ -21,10 +21,12 @@ echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3" # Proto deps buildscripts/make_dependencies.sh +GRADLE_FLAGS="-Pandroid.useAndroidX=true" + # Build and run interop instrumentation tests on Firebase Test Lab cd android-interop-testing -../gradlew assembleDebug -../gradlew assembleDebugAndroidTest +../gradlew assembleDebug $GRADLE_FLAGS +../gradlew assembleDebugAndroidTest $GRADLE_FLAGS gcloud firebase test android run \ --type instrumentation \ --app build/outputs/apk/debug/grpc-android-interop-testing-debug.apk \ @@ -41,7 +43,7 @@ gcloud firebase test android run \ # Build and run binderchannel instrumentation tests on Firebase Test Lab cd ../binder -../gradlew assembleDebugAndroidTest +../gradlew assembleDebugAndroidTest $GRADLE_FLAGS gcloud firebase test android run \ --type instrumentation \ --app ../android-interop-testing/build/outputs/apk/debug/grpc-android-interop-testing-debug.apk \ diff --git a/buildscripts/kokoro/android.sh b/buildscripts/kokoro/android.sh index 7b9e7f53885..9318138182e 100755 --- a/buildscripts/kokoro/android.sh +++ b/buildscripts/kokoro/android.sh @@ -28,13 +28,16 @@ echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3" # Proto deps buildscripts/make_dependencies.sh +GRADLE_FLAGS="-Pandroid.useAndroidX=true" + ./gradlew \ :grpc-android-interop-testing:build \ :grpc-android:build \ :grpc-cronet:build \ :grpc-binder:build \ assembleAndroidTest \ - publishToMavenLocal + publishToMavenLocal \ + $GRADLE_FLAGS if [[ ! -z $(git status --porcelain) ]]; then git status @@ -89,7 +92,7 @@ cd $BASE_DIR/github/grpc-java ./gradlew clean git checkout HEAD^ ./gradlew --stop # use a new daemon to build the previous commit -./gradlew publishToMavenLocal +./gradlew publishToMavenLocal $GRADLE_FLAGS cd examples/android/helloworld/ ../../gradlew build diff --git a/buildscripts/kokoro/linux_artifacts.sh b/buildscripts/kokoro/linux_artifacts.sh index c4386b94e07..b4551843c6a 100755 --- a/buildscripts/kokoro/linux_artifacts.sh +++ b/buildscripts/kokoro/linux_artifacts.sh @@ -14,25 +14,29 @@ readonly GRPC_JAVA_DIR="$(cd "$(dirname "$0")"/../.. && pwd)" # use --include-build for its grpc-core dependency echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3" LOCAL_MVN_TEMP=$(mktemp -d) +GRADLE_FLAGS="-Pandroid.useAndroidX=true" pushd "$GRPC_JAVA_DIR/android" ../gradlew publish \ -Dorg.gradle.parallel=false \ -PskipCodegen=true \ - -PrepositoryDir="$LOCAL_MVN_TEMP" + -PrepositoryDir="$LOCAL_MVN_TEMP" \ + $GRADLE_FLAGS popd pushd "$GRPC_JAVA_DIR/cronet" ../gradlew publish \ -Dorg.gradle.parallel=false \ -PskipCodegen=true \ - -PrepositoryDir="$LOCAL_MVN_TEMP" + -PrepositoryDir="$LOCAL_MVN_TEMP" \ + $GRADLE_FLAGS popd pushd "$GRPC_JAVA_DIR/binder" ../gradlew publish \ -Dorg.gradle.parallel=false \ -PskipCodegen=true \ - -PrepositoryDir="$LOCAL_MVN_TEMP" + -PrepositoryDir="$LOCAL_MVN_TEMP" \ + $GRADLE_FLAGS popd readonly MVN_ARTIFACT_DIR="${MVN_ARTIFACT_DIR:-$GRPC_JAVA_DIR/mvn-artifacts}" diff --git a/settings.gradle b/settings.gradle index 114d9af3c91..a09ee35ade4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ pluginManagement { plugins { - id "com.android.application" version "3.5.0" - id "com.android.library" version "3.5.0" + id "com.android.application" version "4.2.0" + id "com.android.library" version "4.2.0" id "com.github.johnrengelman.shadow" version "6.1.0" id "com.github.kt3k.coveralls" version "2.10.2" id "com.google.osdetector" version "1.6.2" From d44de5069df2ef485f19895707868754474f2745 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Fri, 7 Jan 2022 09:54:50 -0800 Subject: [PATCH 0041/2009] Bump to Gradle 6.9 and update plugins These changes make the build compatible with Gradle 7, except for Android which requires plugin updates. I removed animalsniffer from binder because it did nothing (as there were no signatures) and it was failing after setting toolVersion. It failed because animalsniffer is only compatible with java plugin. After this change I put the withId(animalsniffer) loading inside the withId(java) to avoid a plugin ordering failure. That made it safe again for binder to load animalsniffer, but it is still best to remove the plugin from binder as it is misleading. I did not upgrade Android plugin versions as newer versions (even 3.6) require dealing with androidx (#8421). --- all/build.gradle | 4 +- api/build.gradle | 2 +- benchmarks/build.gradle | 12 ++--- binder/build.gradle | 1 - build.gradle | 20 +++++--- context/build.gradle | 2 +- core/build.gradle | 2 +- examples/android/clientcache/build.gradle | 2 +- examples/android/helloworld/build.gradle | 2 +- examples/android/routeguide/build.gradle | 2 +- examples/android/strictmode/build.gradle | 2 +- examples/build.gradle | 46 +++++++++---------- examples/example-alts/build.gradle | 8 ++-- examples/example-gauth/build.gradle | 4 +- examples/example-jwt-auth/build.gradle | 8 ++-- examples/example-tls/build.gradle | 8 ++-- examples/example-xds/build.gradle | 8 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- interop-testing/build.gradle | 18 ++++---- netty/build.gradle | 2 +- settings.gradle | 16 +++---- 22 files changed, 89 insertions(+), 84 deletions(-) diff --git a/all/build.gradle b/all/build.gradle index bfc9ad0e66f..ede0b03c27e 100644 --- a/all/build.gradle +++ b/all/build.gradle @@ -63,8 +63,8 @@ task jacocoMerge(type: JacocoMerge) { jacocoTestReport { dependsOn(jacocoMerge) reports { - xml.enabled = true - html.enabled = true + xml.required = true + html.required = true } subprojects.each { subproject -> diff --git a/api/build.gradle b/api/build.gradle index fa58c96ef8a..1348e49ad60 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -2,7 +2,7 @@ plugins { id "java-library" id "maven-publish" - id "me.champeau.gradle.jmh" + id "me.champeau.jmh" id "ru.vyarus.animalsniffer" } diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index ec071137e0c..48b9030714f 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -4,7 +4,7 @@ plugins { id "maven-publish" id "com.google.protobuf" - id "me.champeau.gradle.jmh" + id "me.champeau.jmh" } description = "grpc Benchmarks" @@ -13,7 +13,7 @@ startScripts.enabled = false run.enabled = false jmh { - jvmArgs = "-server -Xms2g -Xmx2g" + jvmArgs = ["-server", "-Xms2g", "-Xmx2g"] } configurations { @@ -55,7 +55,7 @@ def vmArgs = [ ] task qps_client(type: CreateStartScripts) { - mainClassName = "io.grpc.benchmarks.qps.AsyncClient" + mainClass = "io.grpc.benchmarks.qps.AsyncClient" applicationName = "qps_client" defaultJvmOpts = vmArgs outputDir = new File(project.buildDir, 'tmp/scripts/' + name) @@ -63,7 +63,7 @@ task qps_client(type: CreateStartScripts) { } task openloop_client(type: CreateStartScripts) { - mainClassName = "io.grpc.benchmarks.qps.OpenLoopClient" + mainClass = "io.grpc.benchmarks.qps.OpenLoopClient" applicationName = "openloop_client" defaultJvmOpts = vmArgs outputDir = new File(project.buildDir, 'tmp/scripts/' + name) @@ -71,14 +71,14 @@ task openloop_client(type: CreateStartScripts) { } task qps_server(type: CreateStartScripts) { - mainClassName = "io.grpc.benchmarks.qps.AsyncServer" + mainClass = "io.grpc.benchmarks.qps.AsyncServer" applicationName = "qps_server" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task benchmark_worker(type: CreateStartScripts) { - mainClassName = "io.grpc.benchmarks.driver.LoadWorker" + mainClass = "io.grpc.benchmarks.driver.LoadWorker" applicationName = "benchmark_worker" defaultJvmOpts = vmArgs outputDir = new File(project.buildDir, 'tmp/scripts/' + name) diff --git a/binder/build.gradle b/binder/build.gradle index 04f8444ff01..fa9d0d8cee9 100644 --- a/binder/build.gradle +++ b/binder/build.gradle @@ -1,7 +1,6 @@ plugins { id "maven-publish" id "com.android.library" - id "ru.vyarus.animalsniffer" id "digital.wup.android-maven-publish" } diff --git a/build.gradle b/build.gradle index f68125fa5d7..84b281bc945 100644 --- a/build.gradle +++ b/build.gradle @@ -224,8 +224,6 @@ subprojects { } } - jacoco { toolVersion = "0.8.2" } - checkstyle { configDirectory = file("$rootDir/buildscripts") toolVersion = "6.17" @@ -320,6 +318,14 @@ subprojects { options.errorprone.check("UnnecessaryAnonymousClass", CheckSeverity.OFF) options.errorprone.check("PreferJavaTimeOverload", CheckSeverity.OFF) } + + plugins.withId("ru.vyarus.animalsniffer") { + // Only available after java plugin has loaded + animalsniffer { + // Breaks on upgrade: https://github.com/mojohaus/animal-sniffer/issues/131 + toolVersion = '1.18' + } + } } plugins.withId("java-library") { @@ -335,13 +341,13 @@ subprojects { } } - plugins.withId("me.champeau.gradle.jmh") { - dependencies { - jmh 'org.openjdk.jmh:jmh-core:1.19', - 'org.openjdk.jmh:jmh-generator-bytecode:1.19' - } + plugins.withId("me.champeau.jmh") { // invoke jmh on a single benchmark class like so: // ./gradlew -PjmhIncludeSingleClass=StatsTraceContextBenchmark clean :grpc-core:jmh + compileJmhJava { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } jmh { warmupIterations = 10 iterations = 10 diff --git a/context/build.gradle b/context/build.gradle index 909a7472b1e..35ad0566bb6 100644 --- a/context/build.gradle +++ b/context/build.gradle @@ -3,7 +3,7 @@ plugins { id "maven-publish" id "me.champeau.gradle.japicmp" - id "me.champeau.gradle.jmh" + id "me.champeau.jmh" id "ru.vyarus.animalsniffer" } diff --git a/core/build.gradle b/core/build.gradle index e62ae8a804b..ed8e5400765 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,7 +9,7 @@ plugins { id "maven-publish" id "me.champeau.gradle.japicmp" - id "me.champeau.gradle.jmh" + id "me.champeau.jmh" id "ru.vyarus.animalsniffer" } diff --git a/examples/android/clientcache/build.gradle b/examples/android/clientcache/build.gradle index 0c3acd3f47f..0c3cae44980 100644 --- a/examples/android/clientcache/build.gradle +++ b/examples/android/clientcache/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.0.0' - classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17" + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/android/helloworld/build.gradle b/examples/android/helloworld/build.gradle index 0c3acd3f47f..0c3cae44980 100644 --- a/examples/android/helloworld/build.gradle +++ b/examples/android/helloworld/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.0.0' - classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17" + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/android/routeguide/build.gradle b/examples/android/routeguide/build.gradle index c8958fb8abb..09d5b19589a 100644 --- a/examples/android/routeguide/build.gradle +++ b/examples/android/routeguide/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.0.0' - classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17" + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/android/strictmode/build.gradle b/examples/android/strictmode/build.gradle index 0c3acd3f47f..0c3cae44980 100644 --- a/examples/android/strictmode/build.gradle +++ b/examples/android/strictmode/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.0.0' - classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17" + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/build.gradle b/examples/build.gradle index e95cfd2f33c..45648d4af85 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -2,7 +2,7 @@ plugins { // Provide convenience executables for trying out the examples. id 'application' // ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions - id 'com.google.protobuf' version '0.8.17' + id 'com.google.protobuf' version '0.8.18' // Generate IntelliJ IDEA's .idea & .iml project files id 'idea' } @@ -64,79 +64,79 @@ sourceSets { startScripts.enabled = false task routeGuideServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.routeguide.RouteGuideServer' + mainClass = 'io.grpc.examples.routeguide.RouteGuideServer' applicationName = 'route-guide-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task routeGuideClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.routeguide.RouteGuideClient' + mainClass = 'io.grpc.examples.routeguide.RouteGuideClient' applicationName = 'route-guide-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task helloWorldServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworld.HelloWorldServer' + mainClass = 'io.grpc.examples.helloworld.HelloWorldServer' applicationName = 'hello-world-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task helloWorldClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworld.HelloWorldClient' + mainClass = 'io.grpc.examples.helloworld.HelloWorldClient' applicationName = 'hello-world-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task retryingHelloWorldServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.retrying.RetryingHelloWorldServer' + mainClass = 'io.grpc.examples.retrying.RetryingHelloWorldServer' applicationName = 'retrying-hello-world-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task retryingHelloWorldClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.retrying.RetryingHelloWorldClient' + mainClass = 'io.grpc.examples.retrying.RetryingHelloWorldClient' applicationName = 'retrying-hello-world-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task hedgingHelloWorldServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.hedging.HedgingHelloWorldServer' + mainClass = 'io.grpc.examples.hedging.HedgingHelloWorldServer' applicationName = 'hedging-hello-world-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task hedgingHelloWorldClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.hedging.HedgingHelloWorldClient' + mainClass = 'io.grpc.examples.hedging.HedgingHelloWorldClient' applicationName = 'hedging-hello-world-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task compressingHelloWorldClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.experimental.CompressingHelloWorldClient' + mainClass = 'io.grpc.examples.experimental.CompressingHelloWorldClient' applicationName = 'compressing-hello-world-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task manualFlowControlClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.manualflowcontrol.ManualFlowControlClient' + mainClass = 'io.grpc.examples.manualflowcontrol.ManualFlowControlClient' applicationName = 'manual-flow-control-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task manualFlowControlServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.manualflowcontrol.ManualFlowControlServer' + mainClass = 'io.grpc.examples.manualflowcontrol.ManualFlowControlServer' applicationName = 'manual-flow-control-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index 2cc4ac5afc9..de4e11fd916 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -56,16 +56,16 @@ startScripts.enabled = false task helloWorldAltsServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.alts.HelloWorldAltsServer' + mainClass = 'io.grpc.examples.alts.HelloWorldAltsServer' applicationName = 'hello-world-alts-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task helloWorldAltsClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.alts.HelloWorldAltsClient' + mainClass = 'io.grpc.examples.alts.HelloWorldAltsClient' applicationName = 'hello-world-alts-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index db4baf1cd38..fdde6e01aff 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -61,9 +61,9 @@ sourceSets { startScripts.enabled = false task googleAuthClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.googleAuth.GoogleAuthClient' + mainClass = 'io.grpc.examples.googleAuth.GoogleAuthClient' applicationName = 'google-auth-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index c1470dd693e..8f962a2ffc8 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -64,16 +64,16 @@ sourceSets { startScripts.enabled = false task hellowWorldJwtAuthServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.jwtauth.AuthServer' + mainClass = 'io.grpc.examples.jwtauth.AuthServer' applicationName = 'auth-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task hellowWorldJwtAuthClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.jwtauth.AuthClient' + mainClass = 'io.grpc.examples.jwtauth.AuthClient' applicationName = 'auth-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index bd8d264b7f9..b3b8372e1c4 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -56,16 +56,16 @@ sourceSets { startScripts.enabled = false task helloWorldTlsServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworldtls.HelloWorldServerTls' + mainClass = 'io.grpc.examples.helloworldtls.HelloWorldServerTls' applicationName = 'hello-world-tls-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task helloWorldTlsClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworldtls.HelloWorldClientTls' + mainClass = 'io.grpc.examples.helloworldtls.HelloWorldClientTls' applicationName = 'hello-world-tls-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index 0ce7fbd56b5..2d35f5c40d9 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -49,16 +49,16 @@ protobuf { startScripts.enabled = false task xdsHelloWorldClient(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworldxds.XdsHelloWorldClient' + mainClass = 'io.grpc.examples.helloworldxds.XdsHelloWorldClient' applicationName = 'xds-hello-world-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task xdsHelloWorldServer(type: CreateStartScripts) { - mainClassName = 'io.grpc.examples.helloworldxds.XdsHelloWorldServer' + mainClass = 'io.grpc.examples.helloworldxds.XdsHelloWorldServer' applicationName = 'xds-hello-world-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } diff --git a/examples/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/wrapper/gradle-wrapper.properties index 4d9ca164914..3ab0b725efc 100644 --- a/examples/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4d9ca164914..3ab0b725efc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/interop-testing/build.gradle b/interop-testing/build.gradle index 944c0daab81..3790479f03f 100644 --- a/interop-testing/build.gradle +++ b/interop-testing/build.gradle @@ -68,7 +68,7 @@ test { // Note that OkHttp currently only supports ALPN, so OpenSSL version >= 1.0.2 is required. task test_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.TestServiceClient" + mainClass = "io.grpc.testing.integration.TestServiceClient" applicationName = "test-client" defaultJvmOpts = [ "-javaagent:JAVAAGENT_APP_HOME" + configurations.alpnagent.singleFile.name @@ -82,21 +82,21 @@ task test_client(type: CreateStartScripts) { } task test_server(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.TestServiceServer" + mainClass = "io.grpc.testing.integration.TestServiceServer" applicationName = "test-server" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task reconnect_test_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.ReconnectTestClient" + mainClass = "io.grpc.testing.integration.ReconnectTestClient" applicationName = "reconnect-test-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task stresstest_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.StressTestClient" + mainClass = "io.grpc.testing.integration.StressTestClient" applicationName = "stresstest-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath @@ -107,14 +107,14 @@ task stresstest_client(type: CreateStartScripts) { } task http2_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.Http2Client" + mainClass = "io.grpc.testing.integration.Http2Client" applicationName = "http2-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task grpclb_long_lived_affinity_test_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.GrpclbLongLivedAffinityTestClient" + mainClass = "io.grpc.testing.integration.GrpclbLongLivedAffinityTestClient" applicationName = "grpclb-long-lived-affinity-test-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath @@ -124,7 +124,7 @@ task grpclb_long_lived_affinity_test_client(type: CreateStartScripts) { } task grpclb_fallback_test_client (type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.GrpclbFallbackTestClient" + mainClass = "io.grpc.testing.integration.GrpclbFallbackTestClient" applicationName = "grpclb-fallback-test-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath @@ -134,14 +134,14 @@ task grpclb_fallback_test_client (type: CreateStartScripts) { } task xds_test_client(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.XdsTestClient" + mainClass = "io.grpc.testing.integration.XdsTestClient" applicationName = "xds-test-client" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath } task xds_test_server(type: CreateStartScripts) { - mainClassName = "io.grpc.testing.integration.XdsTestServer" + mainClass = "io.grpc.testing.integration.XdsTestServer" applicationName = "xds-test-server" outputDir = new File(project.buildDir, 'tmp/scripts/' + name) classpath = startScripts.classpath diff --git a/netty/build.gradle b/netty/build.gradle index 00726940cde..5fdc8f20f08 100644 --- a/netty/build.gradle +++ b/netty/build.gradle @@ -3,7 +3,7 @@ plugins { id "maven-publish" id "me.champeau.gradle.japicmp" - id "me.champeau.gradle.jmh" + id "me.champeau.jmh" id "ru.vyarus.animalsniffer" } diff --git a/settings.gradle b/settings.gradle index a09ee35ade4..086a2312137 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,14 +3,14 @@ pluginManagement { id "com.android.application" version "4.2.0" id "com.android.library" version "4.2.0" id "com.github.johnrengelman.shadow" version "6.1.0" - id "com.github.kt3k.coveralls" version "2.10.2" - id "com.google.osdetector" version "1.6.2" - id "com.google.protobuf" version "0.8.17" - id "digital.wup.android-maven-publish" version "3.6.2" - id "me.champeau.gradle.japicmp" version "0.2.5" - id "me.champeau.gradle.jmh" version "0.5.2" - id "net.ltgt.errorprone" version "1.3.0" - id "ru.vyarus.animalsniffer" version "1.5.2" + id "com.github.kt3k.coveralls" version "2.12.0" + id "com.google.osdetector" version "1.7.0" + id "com.google.protobuf" version "0.8.18" + id "digital.wup.android-maven-publish" version "3.6.3" + id "me.champeau.gradle.japicmp" version "0.3.0" + id "me.champeau.jmh" version "0.6.6" + id "net.ltgt.errorprone" version "2.0.2" + id "ru.vyarus.animalsniffer" version "1.5.4" } resolutionStrategy { eachPlugin { From 23a2202efa89ebee83f296e36d01e35cc9489d98 Mon Sep 17 00:00:00 2001 From: Sergii Tkachenko Date: Fri, 7 Jan 2022 16:22:30 -0500 Subject: [PATCH 0042/2009] xds: Rename ring_hash LB Policy to ring_hash_experimental (#8776) Ring hash can only be used from within xds currently, because that's the only way to get a hash assigned to RPCs which is required for it to function. So it should be using the _experimental suffix like the other only-used-from-xds policies. --- xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java | 2 +- .../java/io/grpc/xds/ClusterResolverLoadBalancer.java | 8 ++++---- .../io/grpc/xds/ClusterResolverLoadBalancerProvider.java | 2 +- .../java/io/grpc/xds/RingHashLoadBalancerProvider.java | 4 ++-- xds/src/main/java/io/grpc/xds/XdsClient.java | 4 ++-- xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java | 4 ++-- .../test/java/io/grpc/xds/ClientXdsClientTestBase.java | 4 ++-- xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java | 4 ++-- xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java | 4 ++-- .../java/io/grpc/xds/ClusterResolverLoadBalancerTest.java | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java index 396292a2392..7735199134f 100644 --- a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java +++ b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java @@ -187,7 +187,7 @@ private void handleClusterDiscovered() { LoadBalancerProvider lbProvider = null; Object lbConfig = null; if (root.result.lbPolicy() == LbPolicy.RING_HASH) { - lbProvider = lbRegistry.getProvider("ring_hash"); + lbProvider = lbRegistry.getProvider("ring_hash_experimental"); lbConfig = new RingHashConfig(root.result.minRingSize(), root.result.maxRingSize()); } if (lbProvider == null) { diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java index f4fcabcb21f..e4800cf668c 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java @@ -672,7 +672,7 @@ private static PriorityChildConfig generateDnsBasedPriorityChildConfig( * Generates configs to be used in the priority LB policy for priorities in an EDS cluster. * *

priority LB -> cluster_impl LB (one per priority) -> (weighted_target LB - * -> round_robin (one per locality)) / ring_hash + * -> round_robin (one per locality)) / ring_hash_experimental */ private static Map generateEdsBasedPriorityChildConfigs( String cluster, @Nullable String edsServiceName, @Nullable ServerInfo lrsServerInfo, @@ -687,9 +687,9 @@ private static Map generateEdsBasedPriorityChildCon // created. If the endpoint-level LB policy is round_robin, it creates a two-level LB // hierarchy: a locality-level LB policy that balances load according to locality weights // followed by an endpoint-level LB policy that simply rounds robin the endpoints within - // the locality. If the endpoint-level LB policy is ring_hash, it creates a unified LB - // policy that balances load by weighing the product of each endpoint's weight and the - // weight of the locality it belongs to. + // the locality. If the endpoint-level LB policy is ring_hash_experimental, it creates + // a unified LB policy that balances load by weighing the product of each endpoint's weight + // and the weight of the locality it belongs to. if (endpointLbPolicy.getProvider().getPolicyName().equals("round_robin")) { Map localityWeights = prioritizedLocalityWeights.get(priority); Map targets = new HashMap<>(); diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java index 551c2c296fc..4aaf0dcadde 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancerProvider.java @@ -68,7 +68,7 @@ public LoadBalancer newLoadBalancer(Helper helper) { static final class ClusterResolverConfig { // Ordered list of clusters to be resolved. final List discoveryMechanisms; - // Endpoint-level load balancing policy with config (round_robin or ring_hash). + // Endpoint-level load balancing policy with config (round_robin or ring_hash_experimental). final PolicySelection lbPolicy; ClusterResolverConfig(List discoveryMechanisms, PolicySelection lbPolicy) { diff --git a/xds/src/main/java/io/grpc/xds/RingHashLoadBalancerProvider.java b/xds/src/main/java/io/grpc/xds/RingHashLoadBalancerProvider.java index 102a18000a9..0df4c8c2984 100644 --- a/xds/src/main/java/io/grpc/xds/RingHashLoadBalancerProvider.java +++ b/xds/src/main/java/io/grpc/xds/RingHashLoadBalancerProvider.java @@ -29,7 +29,7 @@ import java.util.Map; /** - * The provider for the "ring_hash" balancing policy. + * The provider for the "ring_hash_experimental" balancing policy. */ @Internal public final class RingHashLoadBalancerProvider extends LoadBalancerProvider { @@ -66,7 +66,7 @@ public int getPriority() { @Override public String getPolicyName() { - return "ring_hash"; + return "ring_hash_experimental"; } @Override diff --git a/xds/src/main/java/io/grpc/xds/XdsClient.java b/xds/src/main/java/io/grpc/xds/XdsClient.java index 65d4d67c427..024500253a3 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClient.java +++ b/xds/src/main/java/io/grpc/xds/XdsClient.java @@ -113,10 +113,10 @@ abstract static class CdsUpdate implements ResourceUpdate { // Endpoint-level load balancing policy. abstract LbPolicy lbPolicy(); - // Only valid if lbPolicy is "ring_hash". + // Only valid if lbPolicy is "ring_hash_experimental". abstract long minRingSize(); - // Only valid if lbPolicy is "ring_hash". + // Only valid if lbPolicy is "ring_hash_experimental". abstract long maxRingSize(); // Alternative resource name to be used in EDS requests. diff --git a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java index 388fc6a8b20..7664660d4c6 100644 --- a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java +++ b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java @@ -120,7 +120,7 @@ public void setUp() { when(helper.getSynchronizationContext()).thenReturn(syncContext); lbRegistry.register(new FakeLoadBalancerProvider(CLUSTER_RESOLVER_POLICY_NAME)); lbRegistry.register(new FakeLoadBalancerProvider("round_robin")); - lbRegistry.register(new FakeLoadBalancerProvider("ring_hash")); + lbRegistry.register(new FakeLoadBalancerProvider("ring_hash_experimental")); loadBalancer = new CdsLoadBalancer2(helper, lbRegistry); loadBalancer.handleResolvedAddresses( ResolvedAddresses.newBuilder() @@ -283,7 +283,7 @@ public void discoverAggregateCluster() { assertDiscoveryMechanism(childLbConfig.discoveryMechanisms.get(2), cluster4, DiscoveryMechanism.Type.EDS, null, null, LRS_SERVER_INFO, 300L, null); assertThat(childLbConfig.lbPolicy.getProvider().getPolicyName()) - .isEqualTo("ring_hash"); // dominated by top-level cluster's config + .isEqualTo("ring_hash_experimental"); // dominated by top-level cluster's config assertThat(((RingHashConfig) childLbConfig.lbPolicy.getConfig()).minRingSize).isEqualTo(100L); assertThat(((RingHashConfig) childLbConfig.lbPolicy.getConfig()).maxRingSize).isEqualTo(1000L); } diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java index 6fdf5e1b811..42cf9baa1d9 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java @@ -1483,8 +1483,8 @@ public void cdsResourceFound_ringHashLbPolicy() { DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher); Message ringHashConfig = mf.buildRingHashLbConfig("xx_hash", 10L, 100L); Any clusterRingHash = Any.pack( - mf.buildEdsCluster(CDS_RESOURCE, null, "ring_hash", ringHashConfig, false, null, - "envoy.transport_sockets.tls", null + mf.buildEdsCluster(CDS_RESOURCE, null, "ring_hash_experimental", ringHashConfig, false, + null, "envoy.transport_sockets.tls", null )); call.sendResponse(ResourceType.CDS, clusterRingHash, VERSION_1, "0000"); diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java index 1a69b6fc650..be28f07b73c 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java @@ -438,7 +438,7 @@ protected Message buildAggregateCluster(String clusterName, String lbPolicy, Cluster.Builder builder = Cluster.newBuilder().setName(clusterName).setClusterType(type); if (lbPolicy.equals("round_robin")) { builder.setLbPolicy(LbPolicy.ROUND_ROBIN); - } else if (lbPolicy.equals("ring_hash")) { + } else if (lbPolicy.equals("ring_hash_experimental")) { builder.setLbPolicy(LbPolicy.RING_HASH); builder.setRingHashLbConfig((RingHashLbConfig) ringHashLbConfig); } else { @@ -454,7 +454,7 @@ private Cluster.Builder initClusterBuilder(String clusterName, String lbPolicy, builder.setName(clusterName); if (lbPolicy.equals("round_robin")) { builder.setLbPolicy(LbPolicy.ROUND_ROBIN); - } else if (lbPolicy.equals("ring_hash")) { + } else if (lbPolicy.equals("ring_hash_experimental")) { builder.setLbPolicy(LbPolicy.RING_HASH); builder.setRingHashLbConfig((RingHashLbConfig) ringHashLbConfig); } else { diff --git a/xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java b/xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java index 6df36e1c31e..69e75292778 100644 --- a/xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java +++ b/xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java @@ -494,7 +494,7 @@ protected Message buildAggregateCluster(String clusterName, String lbPolicy, Cluster.Builder builder = Cluster.newBuilder().setName(clusterName).setClusterType(type); if (lbPolicy.equals("round_robin")) { builder.setLbPolicy(LbPolicy.ROUND_ROBIN); - } else if (lbPolicy.equals("ring_hash")) { + } else if (lbPolicy.equals("ring_hash_experimental")) { builder.setLbPolicy(LbPolicy.RING_HASH); builder.setRingHashLbConfig((RingHashLbConfig) ringHashLbConfig); } else { @@ -511,7 +511,7 @@ private Cluster.Builder initClusterBuilder(String clusterName, String lbPolicy, builder.setName(clusterName); if (lbPolicy.equals("round_robin")) { builder.setLbPolicy(LbPolicy.ROUND_ROBIN); - } else if (lbPolicy.equals("ring_hash")) { + } else if (lbPolicy.equals("ring_hash_experimental")) { builder.setLbPolicy(LbPolicy.RING_HASH); builder.setRingHashLbConfig((RingHashLbConfig) ringHashLbConfig); } else { diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java index ccc1975265d..a85f476ed4b 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java @@ -135,7 +135,7 @@ public void uncaughtException(Thread t, Throwable e) { private final PolicySelection roundRobin = new PolicySelection(new FakeLoadBalancerProvider("round_robin"), null); private final PolicySelection ringHash = new PolicySelection( - new FakeLoadBalancerProvider("ring_hash"), new RingHashConfig(10L, 100L)); + new FakeLoadBalancerProvider("ring_hash_experimental"), new RingHashConfig(10L, 100L)); private final List childBalancers = new ArrayList<>(); private final List resolvers = new ArrayList<>(); private final FakeXdsClient xdsClient = new FakeXdsClient(); @@ -260,7 +260,7 @@ public void edsClustersWithRingHashEndpointLbPolicy() { ClusterImplConfig clusterImplConfig = (ClusterImplConfig) priorityChildConfig.policySelection.getConfig(); assertClusterImplConfig(clusterImplConfig, CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, - tlsContext, Collections.emptyList(), "ring_hash"); + tlsContext, Collections.emptyList(), "ring_hash_experimental"); RingHashConfig ringHashConfig = (RingHashConfig) clusterImplConfig.childPolicy.getConfig(); assertThat(ringHashConfig.minRingSize).isEqualTo(10L); From a74a3ad83498a3a939d863790670914b3ebd6776 Mon Sep 17 00:00:00 2001 From: Jintao Date: Sat, 8 Jan 2022 07:03:14 +0800 Subject: [PATCH 0043/2009] use charset from StandardCharsets instead of 'Charset.forName' (#8779) Co-authored-by: Penn (Dapeng) Zhang --- api/src/jmh/java/io/grpc/StatusBenchmark.java | 8 ++++---- api/src/main/java/io/grpc/DecompressorRegistry.java | 4 ++-- api/src/main/java/io/grpc/InternalMetadata.java | 3 ++- api/src/test/java/io/grpc/StatusTest.java | 4 +++- .../main/java/io/grpc/internal/ClientCallImpl.java | 4 ++-- core/src/main/java/io/grpc/internal/GrpcUtil.java | 3 ++- .../main/java/io/grpc/cronet/CronetClientStream.java | 10 +++++----- .../java/io/grpc/cronet/CronetClientStreamTest.java | 12 ++++++------ .../io/grpc/examples/advanced/JsonMarshaller.java | 3 ++- .../io/grpc/examples/routeguide/RouteGuideUtil.java | 4 ++-- .../grpc/testing/integration/TestServiceClient.java | 3 ++- .../io/grpc/testing/integration/CompressionTest.java | 4 ++-- .../java/io/grpc/okhttp/OkHttpClientStreamTest.java | 4 ++-- .../main/java/io/grpc/okhttp/internal/Util.java | 3 ++- .../io/grpc/protobuf/services/BinlogHelperTest.java | 3 ++- 15 files changed, 40 insertions(+), 32 deletions(-) diff --git a/api/src/jmh/java/io/grpc/StatusBenchmark.java b/api/src/jmh/java/io/grpc/StatusBenchmark.java index e3f087c6204..846682c3298 100644 --- a/api/src/jmh/java/io/grpc/StatusBenchmark.java +++ b/api/src/jmh/java/io/grpc/StatusBenchmark.java @@ -16,7 +16,7 @@ package io.grpc; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -57,7 +57,7 @@ public byte[] messageEncodeEscape() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public String messageDecodePlain() { return Status.MESSAGE_KEY.parseBytes( - "Unexpected RST in stream".getBytes(Charset.forName("US-ASCII"))); + "Unexpected RST in stream".getBytes(StandardCharsets.US_ASCII)); } /** @@ -68,7 +68,7 @@ public String messageDecodePlain() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public String messageDecodeEscape() { return Status.MESSAGE_KEY.parseBytes( - "Some Error%10Wasabi and Horseradish are the same".getBytes(Charset.forName("US-ASCII"))); + "Some Error%10Wasabi and Horseradish are the same".getBytes(StandardCharsets.US_ASCII)); } /** @@ -88,7 +88,7 @@ public byte[] codeEncode() { @BenchmarkMode(Mode.SampleTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public Status codeDecode() { - return Status.CODE_KEY.parseBytes("15".getBytes(Charset.forName("US-ASCII"))); + return Status.CODE_KEY.parseBytes("15".getBytes(StandardCharsets.US_ASCII)); } } diff --git a/api/src/main/java/io/grpc/DecompressorRegistry.java b/api/src/main/java/io/grpc/DecompressorRegistry.java index ea0433d8d0a..b2669d3c0fc 100644 --- a/api/src/main/java/io/grpc/DecompressorRegistry.java +++ b/api/src/main/java/io/grpc/DecompressorRegistry.java @@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Joiner; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; @@ -85,7 +85,7 @@ private DecompressorRegistry(Decompressor d, boolean advertised, DecompressorReg decompressors = Collections.unmodifiableMap(newDecompressors); advertisedDecompressors = ACCEPT_ENCODING_JOINER.join(getAdvertisedMessageEncodings()) - .getBytes(Charset.forName("US-ASCII")); + .getBytes(StandardCharsets.US_ASCII); } private DecompressorRegistry() { diff --git a/api/src/main/java/io/grpc/InternalMetadata.java b/api/src/main/java/io/grpc/InternalMetadata.java index 2823882952f..cb98ad752b2 100644 --- a/api/src/main/java/io/grpc/InternalMetadata.java +++ b/api/src/main/java/io/grpc/InternalMetadata.java @@ -20,6 +20,7 @@ import io.grpc.Metadata.AsciiMarshaller; import io.grpc.Metadata.BinaryStreamMarshaller; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; /** * Internal {@link Metadata} accessor. This is intended for use by io.grpc.internal, and the @@ -42,7 +43,7 @@ public interface TrustedAsciiMarshaller extends Metadata.TrustedAsciiMarshall * Copy of StandardCharsets, which is only available on Java 1.7 and above. */ @Internal - public static final Charset US_ASCII = Charset.forName("US-ASCII"); + public static final Charset US_ASCII = StandardCharsets.US_ASCII; /** * An instance of base64 encoder that omits padding. diff --git a/api/src/test/java/io/grpc/StatusTest.java b/api/src/test/java/io/grpc/StatusTest.java index 9abeba436f7..aca5dc8ee66 100644 --- a/api/src/test/java/io/grpc/StatusTest.java +++ b/api/src/test/java/io/grpc/StatusTest.java @@ -21,6 +21,8 @@ import io.grpc.Status.Code; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -28,7 +30,7 @@ /** Unit tests for {@link Status}. */ @RunWith(JUnit4.class) public class StatusTest { - private final Charset ascii = Charset.forName("US-ASCII"); + private final Charset ascii = StandardCharsets.US_ASCII; @Test public void verifyExceptionMessage() { diff --git a/core/src/main/java/io/grpc/internal/ClientCallImpl.java b/core/src/main/java/io/grpc/internal/ClientCallImpl.java index db1a992b968..e60f9e54b47 100644 --- a/core/src/main/java/io/grpc/internal/ClientCallImpl.java +++ b/core/src/main/java/io/grpc/internal/ClientCallImpl.java @@ -53,7 +53,7 @@ import io.perfmark.PerfMark; import io.perfmark.Tag; import java.io.InputStream; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.concurrent.CancellationException; import java.util.concurrent.Executor; @@ -71,7 +71,7 @@ final class ClientCallImpl extends ClientCall { private static final Logger log = Logger.getLogger(ClientCallImpl.class.getName()); private static final byte[] FULL_STREAM_DECOMPRESSION_ENCODINGS - = "gzip".getBytes(Charset.forName("US-ASCII")); + = "gzip".getBytes(StandardCharsets.US_ASCII); private final MethodDescriptor method; private final Tag tag; diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index c997414eabe..bce1a0f1503 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -55,6 +55,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; @@ -75,7 +76,7 @@ public final class GrpcUtil { private static final Logger log = Logger.getLogger(GrpcUtil.class.getName()); - public static final Charset US_ASCII = Charset.forName("US-ASCII"); + public static final Charset US_ASCII = StandardCharsets.US_ASCII; /** * {@link io.grpc.Metadata.Key} for the timeout header. diff --git a/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java b/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java index d44b716146e..7329ed08c5d 100644 --- a/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java +++ b/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java @@ -44,7 +44,7 @@ import java.lang.reflect.Method; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -408,10 +408,10 @@ private void setGrpcHeaders(BidirectionalStream.Builder builder) { // String and byte array. byte[][] serializedHeaders = TransportFrameUtil.toHttp2Headers(headers); for (int i = 0; i < serializedHeaders.length; i += 2) { - String key = new String(serializedHeaders[i], Charset.forName("UTF-8")); + String key = new String(serializedHeaders[i], StandardCharsets.UTF_8); // TODO(ericgribkoff): log an error or throw an exception if (isApplicationHeader(key)) { - String value = new String(serializedHeaders[i + 1], Charset.forName("UTF-8")); + String value = new String(serializedHeaders[i + 1], StandardCharsets.UTF_8); builder.addHeader(key, value); } } @@ -588,8 +588,8 @@ private void reportHeaders(List> headers, boolean endO byte[][] headerValues = new byte[headerList.size()][]; for (int i = 0; i < headerList.size(); i += 2) { - headerValues[i] = headerList.get(i).getBytes(Charset.forName("UTF-8")); - headerValues[i + 1] = headerList.get(i + 1).getBytes(Charset.forName("UTF-8")); + headerValues[i] = headerList.get(i).getBytes(StandardCharsets.UTF_8); + headerValues[i + 1] = headerList.get(i + 1).getBytes(StandardCharsets.UTF_8); } Metadata metadata = InternalMetadata.newMetadata(TransportFrameUtil.toRawSerializedHeaders(headerValues)); diff --git a/cronet/src/test/java/io/grpc/cronet/CronetClientStreamTest.java b/cronet/src/test/java/io/grpc/cronet/CronetClientStreamTest.java index 48ce71c493f..9b63601d717 100644 --- a/cronet/src/test/java/io/grpc/cronet/CronetClientStreamTest.java +++ b/cronet/src/test/java/io/grpc/cronet/CronetClientStreamTest.java @@ -46,7 +46,7 @@ import java.io.ByteArrayInputStream; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -168,7 +168,7 @@ public void write() { for (int i = 0; i < 5; ++i) { requests[i] = new String("request" + String.valueOf(i)); buffers[i] = allocator.allocate(requests[i].length()); - buffers[i].write(requests[i].getBytes(Charset.forName("UTF-8")), 0, requests[i].length()); + buffers[i].write(requests[i].getBytes(StandardCharsets.UTF_8), 0, requests[i].length()); // The 3rd and 5th writeFrame calls have flush=true. clientStream.abstractClientStreamSink().writeFrame(buffers[i], false, i == 2 || i == 4, 1); } @@ -261,7 +261,7 @@ public void read() { callback.onReadCompleted( cronetStream, info, - createMessageFrame(new String("response1").getBytes(Charset.forName("UTF-8"))), + createMessageFrame(new String("response1").getBytes(StandardCharsets.UTF_8)), false); // Haven't request any message, so no callback is called here. verify(clientListener, times(0)).messagesAvailable(isA(MessageProducer.class)); @@ -293,7 +293,7 @@ public void streamSucceeded() { CronetWritableBufferAllocator allocator = new CronetWritableBufferAllocator(); String request = new String("request"); WritableBuffer writableBuffer = allocator.allocate(request.length()); - writableBuffer.write(request.getBytes(Charset.forName("UTF-8")), 0, request.length()); + writableBuffer.write(request.getBytes(StandardCharsets.UTF_8), 0, request.length()); clientStream.abstractClientStreamSink().writeFrame(writableBuffer, false, true, 1); ArgumentCaptor bufferCaptor = ArgumentCaptor.forClass(ByteBuffer.class); verify(cronetStream, times(1)).write(bufferCaptor.capture(), isA(Boolean.class)); @@ -312,7 +312,7 @@ public void streamSucceeded() { callback.onReadCompleted( cronetStream, info, - createMessageFrame(new String("response").getBytes(Charset.forName("UTF-8"))), + createMessageFrame(new String("response").getBytes(StandardCharsets.UTF_8)), false); verify(clientListener, times(1)).messagesAvailable(isA(MessageProducer.class)); verify(cronetStream, times(2)).read(isA(ByteBuffer.class)); @@ -688,7 +688,7 @@ public void getUnaryRequest() { .newBidirectionalStreamBuilder( isA(String.class), isA(BidirectionalStream.Callback.class), isA(Executor.class)); - byte[] msg = "request".getBytes(Charset.forName("UTF-8")); + byte[] msg = "request".getBytes(StandardCharsets.UTF_8); stream.writeMessage(new ByteArrayInputStream(msg)); // We still haven't built the stream or sent anything. verify(cronetStream, times(0)).write(isA(ByteBuffer.class), isA(Boolean.class)); diff --git a/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java b/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java index 8b3068cc009..fbe3fa50afc 100644 --- a/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java +++ b/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java @@ -30,6 +30,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; /** * A {@link Marshaller} for JSON. This marshals in the Protobuf 3 format described here: @@ -58,7 +59,7 @@ public static Marshaller jsonMarshaller(final T defaultIn public static Marshaller jsonMarshaller( final T defaultInstance, final Parser parser, final Printer printer) { - final Charset charset = Charset.forName("UTF-8"); + final Charset charset = StandardCharsets.UTF_8; return new Marshaller() { @Override diff --git a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideUtil.java b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideUtil.java index 6e49492da06..0794674091f 100644 --- a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideUtil.java +++ b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideUtil.java @@ -22,7 +22,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -58,7 +58,7 @@ public static URL getDefaultFeaturesFile() { public static List parseFeatures(URL file) throws IOException { InputStream input = file.openStream(); try { - Reader reader = new InputStreamReader(input, Charset.forName("UTF-8")); + Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8); try { FeatureDatabase.Builder database = FeatureDatabase.newBuilder(); JsonFormat.parser().merge(reader, database); diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java index 914db12e5a8..8ac50419d5f 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java @@ -40,6 +40,7 @@ import java.io.File; import java.io.FileInputStream; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -50,7 +51,7 @@ */ public class TestServiceClient { - private static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final Charset UTF_8 = StandardCharsets.UTF_8; /** * The main application allowing this client to be launched from the command line. diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/CompressionTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/CompressionTest.java index 208eb40c438..fdd3ac63011 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/CompressionTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/CompressionTest.java @@ -52,7 +52,7 @@ import io.grpc.testing.integration.Messages.SimpleResponse; import io.grpc.testing.integration.TestServiceGrpc.TestServiceBlockingStub; import io.grpc.testing.integration.TransportCompressionTest.Fzip; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -312,6 +312,6 @@ public void onHeaders(Metadata headers) { } private static void assertEqualsString(String expected, byte[] actual) { - assertEquals(expected, new String(actual, Charset.forName("US-ASCII"))); + assertEquals(expected, new String(actual, StandardCharsets.US_ASCII)); } } diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientStreamTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientStreamTest.java index 99a9159eab0..46a49463e5f 100644 --- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientStreamTest.java +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientStreamTest.java @@ -42,7 +42,7 @@ import io.grpc.okhttp.internal.framed.Header; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.junit.Before; @@ -243,7 +243,7 @@ public void getUnaryRequest() throws IOException { eq(false), eq(false), eq(3), eq(0), headersCaptor.capture()); verify(transport, times(0)).streamReadyToStart(isA(OkHttpClientStream.class)); - byte[] msg = "request".getBytes(Charset.forName("UTF-8")); + byte[] msg = "request".getBytes(StandardCharsets.UTF_8); stream.writeMessage(new ByteArrayInputStream(msg)); stream.halfClose(); verify(transport).streamReadyToStart(eq(stream)); diff --git a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/Util.java b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/Util.java index 556d849c705..a961c605656 100644 --- a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/Util.java +++ b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/Util.java @@ -27,6 +27,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; @@ -47,7 +48,7 @@ public final class Util { public static final String[] EMPTY_STRING_ARRAY = new String[0]; /** A cheap and type-safe constant for the UTF-8 Charset. */ - public static final Charset UTF_8 = Charset.forName("UTF-8"); + public static final Charset UTF_8 = StandardCharsets.UTF_8; private Util() { } diff --git a/services/src/test/java/io/grpc/protobuf/services/BinlogHelperTest.java b/services/src/test/java/io/grpc/protobuf/services/BinlogHelperTest.java index 37e503ccd41..23022192be3 100644 --- a/services/src/test/java/io/grpc/protobuf/services/BinlogHelperTest.java +++ b/services/src/test/java/io/grpc/protobuf/services/BinlogHelperTest.java @@ -80,6 +80,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -94,7 +95,7 @@ /** Tests for {@link BinlogHelper}. */ @RunWith(JUnit4.class) public final class BinlogHelperTest { - private static final Charset US_ASCII = Charset.forName("US-ASCII"); + private static final Charset US_ASCII = StandardCharsets.US_ASCII; private static final BinlogHelper HEADER_FULL = new Builder().header(Integer.MAX_VALUE).build(); private static final BinlogHelper HEADER_256 = new Builder().header(256).build(); private static final BinlogHelper MSG_FULL = new Builder().msg(Integer.MAX_VALUE).build(); From d7f951a9d8a259682b786b711cd7431834a283cd Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Fri, 7 Jan 2022 15:34:59 -0800 Subject: [PATCH 0044/2009] all: update netty to 4.1.72.Final and tcnative to 2.0.46.Final (#8780) --- SECURITY.md | 3 ++- build.gradle | 4 ++-- buildscripts/kokoro/macos.cfg | 1 + .../java/io/grpc/netty/NettyTestUtil.java | 4 +++- .../grpc/netty/ProtocolNegotiatorsTest.java | 14 ++++++++++- repositories.bzl | 24 +++++++++---------- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index df9061eab8f..44efbe8d42e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -409,7 +409,8 @@ grpc-netty version | netty-handler version | netty-tcnative-boringssl-static ver 1.29.x-1.31.x | 4.1.48.Final | 2.0.30.Final 1.32.x-1.34.x | 4.1.51.Final | 2.0.31.Final 1.35.x-1.41.x | 4.1.52.Final | 2.0.34.Final -1.42.x- | 4.1.63.Final | 2.0.38.Final +1.42.x-1.43.x | 4.1.63.Final | 2.0.38.Final +1.44.x | 4.1.72.Final | 2.0.46.Final _(grpc-netty-shaded avoids issues with keeping these versions in sync.)_ diff --git a/build.gradle b/build.gradle index 84b281bc945..fa281a3a0d9 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ subprojects { protocPluginBaseName = 'protoc-gen-grpc-java' javaPluginPath = "$rootDir/compiler/build/exe/java_plugin/$protocPluginBaseName$exeSuffix" - nettyVersion = '4.1.63.Final' + nettyVersion = '4.1.72.Final' guavaVersion = '30.1.1-android' googleauthVersion = '0.22.2' protobufVersion = '3.19.2' @@ -176,7 +176,7 @@ subprojects { // SECURITY.md (multiple occurrences) // examples/example-tls/build.gradle // examples/example-tls/pom.xml - netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:2.0.38.Final', + netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:2.0.46.Final', conscrypt: 'org.conscrypt:conscrypt-openjdk-uber:2.5.1', re2j: 'com.google.re2j:re2j:1.5', diff --git a/buildscripts/kokoro/macos.cfg b/buildscripts/kokoro/macos.cfg index 310e1130416..a6bf290d1ec 100644 --- a/buildscripts/kokoro/macos.cfg +++ b/buildscripts/kokoro/macos.cfg @@ -15,6 +15,7 @@ env_vars { # We always build mvn artifacts. action { define_artifacts { + regex: "github/grpc-java/**/build/reports/**" regex: "github/grpc-java/mvn-artifacts/**" } } diff --git a/netty/src/test/java/io/grpc/netty/NettyTestUtil.java b/netty/src/test/java/io/grpc/netty/NettyTestUtil.java index d030f53d118..802a6efcd58 100644 --- a/netty/src/test/java/io/grpc/netty/NettyTestUtil.java +++ b/netty/src/test/java/io/grpc/netty/NettyTestUtil.java @@ -67,7 +67,9 @@ public Executor getObject() { inUse = true; return new Executor() { @Override - public void execute(Runnable var1) { } + public void execute(Runnable var1) { + var1.run(); + } }; } diff --git a/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java b/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java index d333d1cc8c6..ca1ccde101c 100644 --- a/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java +++ b/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java @@ -48,6 +48,7 @@ import io.grpc.ServerCredentials; import io.grpc.ServerStreamTracer; import io.grpc.Status; +import io.grpc.StatusException; import io.grpc.StatusRuntimeException; import io.grpc.TlsChannelCredentials; import io.grpc.TlsServerCredentials; @@ -132,6 +133,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManagerFactory; import org.junit.After; @@ -415,7 +417,17 @@ public void from_tls_clientAuthRequire_noClientCert() throws Exception { .trustManager(caCert) .build(); Status status = expectFailedHandshake(channelCreds, serverCreds); - assertThat(status.getDescription()).isEqualTo("ssl exception"); + assertEquals(Status.Code.UNAVAILABLE, status.getCode()); + StatusException sre = status.asException(); + // because of netty/netty#11604 we need to check for both TLSv1.2 and v1.3 behaviors + if (sre.getCause() instanceof SSLHandshakeException) { + assertThat(sre).hasCauseThat().isInstanceOf(SSLHandshakeException.class); + assertThat(sre).hasCauseThat().hasMessageThat().contains("SSLV3_ALERT_HANDSHAKE_FAILURE"); + } else { + // Client cert verification is after handshake in TLSv1.3 + assertThat(sre).hasCauseThat().hasCauseThat().isInstanceOf(SSLException.class); + assertThat(sre).hasCauseThat().hasMessageThat().contains("CERTIFICATE_REQUIRED"); + } } @Test diff --git a/repositories.bzl b/repositories.bzl index e5e5ccb0a55..8ad5f109e6f 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -25,18 +25,18 @@ IO_GRPC_GRPC_JAVA_ARTIFACTS = [ "com.google.truth:truth:1.0.1", "com.squareup.okhttp:okhttp:2.7.4", "com.squareup.okio:okio:1.17.5", - "io.netty:netty-buffer:4.1.63.Final", - "io.netty:netty-codec-http2:4.1.63.Final", - "io.netty:netty-codec-http:4.1.63.Final", - "io.netty:netty-codec-socks:4.1.63.Final", - "io.netty:netty-codec:4.1.63.Final", - "io.netty:netty-common:4.1.63.Final", - "io.netty:netty-handler-proxy:4.1.63.Final", - "io.netty:netty-handler:4.1.63.Final", - "io.netty:netty-resolver:4.1.63.Final", - "io.netty:netty-tcnative-boringssl-static:2.0.38.Final", - "io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.63.Final", - "io.netty:netty-transport:4.1.63.Final", + "io.netty:netty-buffer:4.1.72.Final", + "io.netty:netty-codec-http2:4.1.72.Final", + "io.netty:netty-codec-http:4.1.72.Final", + "io.netty:netty-codec-socks:4.1.72.Final", + "io.netty:netty-codec:4.1.72.Final", + "io.netty:netty-common:4.1.72.Final", + "io.netty:netty-handler-proxy:4.1.72.Final", + "io.netty:netty-handler:4.1.72.Final", + "io.netty:netty-resolver:4.1.72.Final", + "io.netty:netty-tcnative-boringssl-static:2.0.46.Final", + "io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.72.Final", + "io.netty:netty-transport:4.1.72.Final", "io.opencensus:opencensus-api:0.24.0", "io.opencensus:opencensus-contrib-grpc-metrics:0.24.0", "io.perfmark:perfmark-api:0.23.0", From e0dca93c6a96e1aa5bcb09d3f410f36da97bd4ce Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Mon, 10 Jan 2022 10:28:42 -0800 Subject: [PATCH 0045/2009] Bump to Gradle 7.3.3 Android Gradle plugin bumped to 4.2.0 in examples, for Gradle 7 compat and to match main build. Jib 3 changed default base image away from distroless, but we do want to use distroless. --- examples/android/clientcache/app/build.gradle | 4 +- examples/android/clientcache/build.gradle | 2 +- examples/android/helloworld/app/build.gradle | 4 +- examples/android/helloworld/build.gradle | 2 +- examples/android/routeguide/app/build.gradle | 4 +- examples/android/routeguide/build.gradle | 2 +- examples/android/strictmode/app/build.gradle | 4 +- examples/android/strictmode/build.gradle | 2 +- examples/example-hostname/build.gradle | 3 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- examples/gradlew | 282 +++++++++++------- examples/gradlew.bat | 43 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 +++++++++++------- gradlew.bat | 43 +-- settings.gradle | 2 +- 16 files changed, 409 insertions(+), 274 deletions(-) diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 1b00d689488..a71611df7a5 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -6,12 +6,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - compileSdkVersion 27 + compileSdkVersion 29 defaultConfig { applicationId "io.grpc.clientcacheexample" minSdkVersion 19 - targetSdkVersion 27 + targetSdkVersion 29 multiDexEnabled true versionCode 1 versionName "1.0" diff --git a/examples/android/clientcache/build.gradle b/examples/android/clientcache/build.gradle index 0c3cae44980..8a94a30191e 100644 --- a/examples/android/clientcache/build.gradle +++ b/examples/android/clientcache/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.2.0' classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 82c4abe7550..cc84e9bcc5c 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -6,12 +6,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - compileSdkVersion 27 + compileSdkVersion 29 defaultConfig { applicationId "io.grpc.helloworldexample" minSdkVersion 19 - targetSdkVersion 27 + targetSdkVersion 29 versionCode 1 versionName "1.0" } diff --git a/examples/android/helloworld/build.gradle b/examples/android/helloworld/build.gradle index 0c3cae44980..8a94a30191e 100644 --- a/examples/android/helloworld/build.gradle +++ b/examples/android/helloworld/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.2.0' classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index 8e33ac40d39..5a43416a5fb 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -6,12 +6,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - compileSdkVersion 27 + compileSdkVersion 29 defaultConfig { applicationId "io.grpc.routeguideexample" minSdkVersion 19 - targetSdkVersion 27 + targetSdkVersion 29 versionCode 1 versionName "1.0" } diff --git a/examples/android/routeguide/build.gradle b/examples/android/routeguide/build.gradle index 09d5b19589a..b1083bb867a 100644 --- a/examples/android/routeguide/build.gradle +++ b/examples/android/routeguide/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.2.0' classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index 7b3de25c3f5..ad74597ed27 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -6,13 +6,13 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "io.grpc.strictmodehelloworldexample" // API level 28 is required for StrictMode penaltyListener minSdkVersion 28 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" } diff --git a/examples/android/strictmode/build.gradle b/examples/android/strictmode/build.gradle index 0c3cae44980..8a94a30191e 100644 --- a/examples/android/strictmode/build.gradle +++ b/examples/android/strictmode/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.2.0' classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index e1476fe11f8..f40528e56ea 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -3,7 +3,7 @@ plugins { id 'java' id "com.google.protobuf" version "0.8.17" - id 'com.google.cloud.tools.jib' version '2.7.0' // For releasing to Docker Hub + id 'com.google.cloud.tools.jib' version '3.1.4' // For releasing to Docker Hub } repositories { @@ -56,6 +56,7 @@ mainClassName = 'io.grpc.examples.hostname.HostnameServer' // For releasing to Docker Hub jib { + from.image = "gcr.io/distroless/java:8" container.ports = ['50051'] outputPaths { tar = 'build/example-hostname.tar' diff --git a/examples/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/wrapper/gradle-wrapper.properties index 3ab0b725efc..2e6e5897b52 100644 --- a/examples/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/examples/gradlew b/examples/gradlew index cccdd3d517f..1b6c787337f 100755 --- a/examples/gradlew +++ b/examples/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 +# +# https://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. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/examples/gradlew.bat b/examples/gradlew.bat index e95643d6a2c..ac1b06f9382 100644 --- a/examples/gradlew.bat +++ b/examples/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ab0b725efc..2e6e5897b52 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d517f..1b6c787337f 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 +# +# https://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. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6a2c..ac1b06f9382 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index 086a2312137..d60cddcbbac 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,7 @@ pluginManagement { plugins { id "com.android.application" version "4.2.0" id "com.android.library" version "4.2.0" - id "com.github.johnrengelman.shadow" version "6.1.0" + id "com.github.johnrengelman.shadow" version "7.1.2" id "com.github.kt3k.coveralls" version "2.12.0" id "com.google.osdetector" version "1.7.0" id "com.google.protobuf" version "0.8.18" From 9e8375850b8b9709a040930ad686851f0eb25c94 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Mon, 10 Jan 2022 14:59:19 -0800 Subject: [PATCH 0046/2009] build.gradle: Add missing dependsOn for generated code sync When messing with error prone for another commit, Gradle started producing a clear warning the dependsOn was missing. But the warning was not reliable. However, even when no warning was printed it is clear the task was broken. --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index fa281a3a0d9..149ade4ae02 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,7 @@ plugins { } import net.ltgt.gradle.errorprone.CheckSeverity +import org.gradle.util.GUtil subprojects { apply plugin: "checkstyle" @@ -97,6 +98,11 @@ subprojects { def syncTask = project.tasks.register("syncGeneratedSources${variantOrSourceSet}", Sync) { from "$buildDir/generated/source/proto/${variantOrSourceSet}/grpc" into "$generatedSourcePath/${variantOrSourceSet}/grpc" + String source = GUtil.toCamelCase(variantOrSourceSet) + if (source == "Main") { + source = "" + } + dependsOn "generate${source}Proto" } syncGeneratedSources.dependsOn syncTask From 56e9321d8a082f7f8a438cfa57a612d40c730219 Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Tue, 11 Jan 2022 09:12:46 -0800 Subject: [PATCH 0047/2009] android-interop-testing: add the linter error message ignore annotation in the source xml file (#8821) --- .../src/main/res/layout/activity_tester.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/android-interop-testing/src/main/res/layout/activity_tester.xml b/android-interop-testing/src/main/res/layout/activity_tester.xml index f1339330227..9c511cab8da 100644 --- a/android-interop-testing/src/main/res/layout/activity_tester.xml +++ b/android-interop-testing/src/main/res/layout/activity_tester.xml @@ -46,6 +46,7 @@ android:layout_height="wrap_content" android:onClick="startEmptyUnary" android:text="Empty Unary" + tools:ignore="OnClick" />