• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20033

29 Oct 2025 04:43PM UTC coverage: 88.533% (-0.03%) from 88.561%
#20033

push

github

web-flow
xds,googleapis: Allow wrapping NameResolver to inject XdsClient (#12450)

Since there is no longer a single global XdsClient, it makes more sense
to allow things like the c2p name resolver to inject its own bootstrap
even if there is one defined in an environment variable.
GoogleCloudToProdNameResolver can now pass an XdsClient instance to
XdsNameResolver, and SharedXdsClientPoolProvider allows
GoogleCloudToProdNameResolver to choose the bootstrap for that one
specific target.

Since XdsNameResolver is no longer in control of the XdsClient pool the
XdsClient instance is now passed to ClusterImplLb. A channel will now
only access the global XdsClient pool exactly once: in the name
resolver.

BootstrapInfo is purposefully being shared across channels, as we really
want to share things like credentials which can have significant memory
use and may have caches which reduce I/O when shared. That is why
SharedXdsClientPoolProvider receives BootstrapInfo instead of
Map<String,?>.

Verifying BootstrapInfo.server() is not empty was moved from
SharedXdsClientPoolProvider to GrpcBootstrapperImpl so avoid
getOrCreate() throwing an exception in only that one case. It might make
sense to move that to BootstrapperImpl, but that will need more
investigation.

A lot of tests needed updating because XdsClientPoolProvider is no
longer responsible for parsing the bootstrap, so we now need bootstraps
even if XdsClientPoolProvider will ignore it.

This also fixes a bug in GoogleCloudToProdNameResolver where it would
initialize the delegate even when it failed to create the bootstrap.
That would certainly cause all RPCs on the channel to fail because of
the missing bootstrap and it defeated the point of `succeeded == false`
and `refresh()` which was supposed to retry contacting the metadata
server.

The server tests were enhanced to give a useful error when
server.start() throws an exception, as otherwise the real error is lost.

b/442819521

34966 of 39495 relevant lines covered (88.53%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/../xds/src/main/java/io/grpc/xds/InternalSharedXdsClientPoolProvider.java
1
/*
2
 * Copyright 2022 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.xds;
18

19
import io.grpc.CallCredentials;
20
import io.grpc.Internal;
21
import io.grpc.MetricRecorder;
22
import io.grpc.internal.ObjectPool;
23
import io.grpc.xds.client.Bootstrapper.BootstrapInfo;
24
import io.grpc.xds.client.XdsClient;
25
import io.grpc.xds.client.XdsInitializationException;
26
import java.util.Map;
27

28
/**
29
 * Accessor for global factory for managing XdsClient instance.
30
 */
31
@Internal
32
public final class InternalSharedXdsClientPoolProvider {
33
  // Prevent instantiation
34
  private InternalSharedXdsClientPoolProvider() {}
35

36
  /**
37
   * Override the global bootstrap.
38
   *
39
   * @deprecated Use InternalGrpcBootstrapperImpl.parseBootstrap() and pass the result to
40
   *     getOrCreate().
41
   */
42
  @Deprecated
43
  public static void setDefaultProviderBootstrapOverride(Map<String, ?> bootstrap) {
44
    SharedXdsClientPoolProvider.getDefaultProvider().setBootstrapOverride(bootstrap);
×
45
  }
×
46

47
  /**
48
   * Get an XdsClient pool.
49
   *
50
   * @deprecated Use InternalGrpcBootstrapperImpl.parseBootstrap() and pass the result to the other
51
   *     getOrCreate().
52
   */
53
  @Deprecated
54
  public static ObjectPool<XdsClient> getOrCreate(String target)
55
      throws XdsInitializationException {
56
    return getOrCreate(target, new MetricRecorder() {});
×
57
  }
58

59
  /**
60
   * Get an XdsClient pool.
61
   *
62
   * @deprecated Use InternalGrpcBootstrapperImpl.parseBootstrap() and pass the result to the other
63
   *     getOrCreate().
64
   */
65
  @Deprecated
66
  public static ObjectPool<XdsClient> getOrCreate(String target, MetricRecorder metricRecorder)
67
      throws XdsInitializationException {
68
    return getOrCreate(target, metricRecorder, null);
×
69
  }
70

71
  /**
72
   * Get an XdsClient pool.
73
   *
74
   * @deprecated Use InternalGrpcBootstrapperImpl.parseBootstrap() and pass the result to the other
75
   *     getOrCreate().
76
   */
77
  @Deprecated
78
  public static ObjectPool<XdsClient> getOrCreate(
79
      String target, MetricRecorder metricRecorder, CallCredentials transportCallCredentials)
80
      throws XdsInitializationException {
81
    return SharedXdsClientPoolProvider.getDefaultProvider()
×
82
        .getOrCreate(target, metricRecorder, transportCallCredentials);
×
83
  }
84

85
  public static XdsClientResult getOrCreate(
86
      String target, BootstrapInfo bootstrapInfo, MetricRecorder metricRecorder,
87
      CallCredentials transportCallCredentials) {
88
    return new XdsClientResult(SharedXdsClientPoolProvider.getDefaultProvider()
×
89
        .getOrCreate(target, bootstrapInfo, metricRecorder, transportCallCredentials));
×
90
  }
91

92
  /**
93
   * An ObjectPool, except without exposing io.grpc.internal, which must not be used for
94
   * cross-package APIs.
95
   */
96
  public static final class XdsClientResult {
97
    private final ObjectPool<XdsClient> xdsClientPool;
98

99
    XdsClientResult(ObjectPool<XdsClient> xdsClientPool) {
×
100
      this.xdsClientPool = xdsClientPool;
×
101
    }
×
102

103
    public XdsClient getObject() {
104
      return xdsClientPool.getObject();
×
105
    }
106

107
    public XdsClient returnObject(XdsClient xdsClient) {
108
      return xdsClientPool.returnObject(xdsClient);
×
109
    }
110
  }
111
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc