|
32 | 32 | import com.google.api.core.ApiFunction;
|
33 | 33 | import com.google.api.core.BetaApi;
|
34 | 34 | import com.google.api.core.InternalApi;
|
35 |
| -import com.google.api.core.InternalExtensionOnly; |
36 | 35 | import com.google.api.gax.core.ExecutorProvider;
|
37 | 36 | import com.google.api.gax.rpc.FixedHeaderProvider;
|
38 | 37 | import com.google.api.gax.rpc.HeaderProvider;
|
|
82 | 81 | * <p>The client lib header and generator header values are used to form a value that goes into the
|
83 | 82 | * http header of requests to the service.
|
84 | 83 | */
|
85 |
| -@InternalExtensionOnly |
86 | 84 | public final class InstantiatingGrpcChannelProvider implements TransportChannelProvider {
|
| 85 | + |
| 86 | + static String systemProductName; |
| 87 | + |
| 88 | + static { |
| 89 | + try { |
| 90 | + systemProductName = |
| 91 | + Files.asCharSource(new File("/sys/class/dmi/id/product_name"), StandardCharsets.UTF_8) |
| 92 | + .readFirstLine(); |
| 93 | + } catch (IOException e) { |
| 94 | + // If not on Compute Engine, FileNotFoundException will be thrown. Use empty string |
| 95 | + // as it won't match with the GCE_PRODUCTION_NAME constants |
| 96 | + systemProductName = ""; |
| 97 | + } |
| 98 | + } |
| 99 | + |
87 | 100 | @VisibleForTesting
|
88 | 101 | static final Logger LOG = Logger.getLogger(InstantiatingGrpcChannelProvider.class.getName());
|
89 | 102 |
|
90 |
| - private static final String DIRECT_PATH_ENV_DISABLE_DIRECT_PATH = |
91 |
| - "GOOGLE_CLOUD_DISABLE_DIRECT_PATH"; |
| 103 | + static final String DIRECT_PATH_ENV_DISABLE_DIRECT_PATH = "GOOGLE_CLOUD_DISABLE_DIRECT_PATH"; |
92 | 104 | private static final String DIRECT_PATH_ENV_ENABLE_XDS = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS";
|
93 | 105 | static final long DIRECT_PATH_KEEP_ALIVE_TIME_SECONDS = 3600;
|
94 | 106 | static final long DIRECT_PATH_KEEP_ALIVE_TIMEOUT_SECONDS = 20;
|
@@ -147,6 +159,19 @@ private InstantiatingGrpcChannelProvider(Builder builder) {
|
147 | 159 | : builder.directPathServiceConfig;
|
148 | 160 | }
|
149 | 161 |
|
| 162 | + /** |
| 163 | + * Package-Private constructor that is only visible for testing DirectPath functionality inside |
| 164 | + * tests. This overrides the computed systemProductName when the class is initialized to help |
| 165 | + * configure the result of {@link #isOnComputeEngine()} check. |
| 166 | + * |
| 167 | + * <p>If productName is null, that represents the result of an IOException |
| 168 | + */ |
| 169 | + @VisibleForTesting |
| 170 | + InstantiatingGrpcChannelProvider(Builder builder, String productName) { |
| 171 | + this(builder); |
| 172 | + systemProductName = productName; |
| 173 | + } |
| 174 | + |
150 | 175 | /**
|
151 | 176 | * @deprecated If executor is not set, this channel provider will create channels with default
|
152 | 177 | * grpc executor.
|
@@ -257,8 +282,8 @@ private boolean isDirectPathEnabled() {
|
257 | 282 | return false;
|
258 | 283 | }
|
259 | 284 |
|
260 |
| - @VisibleForTesting |
261 |
| - boolean isDirectPathXdsEnabled() { |
| 285 | + @InternalApi |
| 286 | + public boolean isDirectPathXdsEnabled() { |
262 | 287 | // Method 1: Enable DirectPath xDS by option.
|
263 | 288 | if (Boolean.TRUE.equals(attemptDirectPathXds)) {
|
264 | 289 | return true;
|
@@ -320,15 +345,9 @@ boolean isCredentialDirectPathCompatible() {
|
320 | 345 | static boolean isOnComputeEngine() {
|
321 | 346 | String osName = System.getProperty("os.name");
|
322 | 347 | if ("Linux".equals(osName)) {
|
323 |
| - try { |
324 |
| - String result = |
325 |
| - Files.asCharSource(new File("/sys/class/dmi/id/product_name"), StandardCharsets.UTF_8) |
326 |
| - .readFirstLine(); |
327 |
| - return result.contains(GCE_PRODUCTION_NAME_PRIOR_2016) |
328 |
| - || result.contains(GCE_PRODUCTION_NAME_AFTER_2016); |
329 |
| - } catch (IOException ignored) { |
330 |
| - return false; |
331 |
| - } |
| 348 | + // systemProductName will be empty string if not on Compute Engine |
| 349 | + return systemProductName.contains(GCE_PRODUCTION_NAME_PRIOR_2016) |
| 350 | + || systemProductName.contains(GCE_PRODUCTION_NAME_AFTER_2016); |
332 | 351 | }
|
333 | 352 | return false;
|
334 | 353 | }
|
@@ -370,10 +389,7 @@ private ManagedChannel createSingleChannel() throws IOException {
|
370 | 389 |
|
371 | 390 | // Check DirectPath traffic.
|
372 | 391 | boolean useDirectPathXds = false;
|
373 |
| - if (isDirectPathEnabled() |
374 |
| - && isCredentialDirectPathCompatible() |
375 |
| - && isOnComputeEngine() |
376 |
| - && canUseDirectPathWithUniverseDomain()) { |
| 392 | + if (canUseDirectPath()) { |
377 | 393 | CallCredentials callCreds = MoreCallCredentials.from(credentials);
|
378 | 394 | ChannelCredentials channelCreds =
|
379 | 395 | GoogleDefaultChannelCredentials.newBuilder().callCredentials(callCreds).build();
|
@@ -446,6 +462,24 @@ && canUseDirectPathWithUniverseDomain()) {
|
446 | 462 | return managedChannel;
|
447 | 463 | }
|
448 | 464 |
|
| 465 | + /** |
| 466 | + * Marked as Internal Api and intended for internal use. DirectPath must be enabled via the |
| 467 | + * settings and a few other configurations/settings must also be valid for the request to go |
| 468 | + * through DirectPath. |
| 469 | + * |
| 470 | + * <p>Checks: 1. Credentials are compatible 2.Running on Compute Engine 3. Universe Domain is |
| 471 | + * configured to for the Google Default Universe |
| 472 | + * |
| 473 | + * @return if DirectPath is enabled for the client AND if the configurations are valid |
| 474 | + */ |
| 475 | + @InternalApi |
| 476 | + public boolean canUseDirectPath() { |
| 477 | + return isDirectPathEnabled() |
| 478 | + && isCredentialDirectPathCompatible() |
| 479 | + && isOnComputeEngine() |
| 480 | + && canUseDirectPathWithUniverseDomain(); |
| 481 | + } |
| 482 | + |
449 | 483 | /** The endpoint to be used for the channel. */
|
450 | 484 | @Override
|
451 | 485 | public String getEndpoint() {
|
@@ -753,6 +787,12 @@ public Builder setAttemptDirectPathXds() {
|
753 | 787 | return this;
|
754 | 788 | }
|
755 | 789 |
|
| 790 | + @VisibleForTesting |
| 791 | + Builder setEnvProvider(EnvironmentProvider envProvider) { |
| 792 | + this.envProvider = envProvider; |
| 793 | + return this; |
| 794 | + } |
| 795 | + |
756 | 796 | /**
|
757 | 797 | * Sets a service config for direct path. If direct path is not enabled, the provided service
|
758 | 798 | * config will be ignored.
|
|
0 commit comments