xref: /aosp_15_r20/external/grpc-grpc-java/xds/src/main/java/io/grpc/xds/XdsNameResolverProvider.java (revision e07d83d3ffcef9ecfc9f7f475418ec639ff0e5fe)
1 /*
2  * Copyright 2019 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 static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.base.Preconditions;
22 import io.grpc.Internal;
23 import io.grpc.NameResolver.Args;
24 import io.grpc.NameResolverProvider;
25 import io.grpc.internal.ObjectPool;
26 import java.net.InetSocketAddress;
27 import java.net.SocketAddress;
28 import java.net.URI;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Map;
32 import java.util.concurrent.atomic.AtomicLong;
33 import javax.annotation.Nullable;
34 
35 /**
36  * A provider for {@link XdsNameResolver}.
37  *
38  * <p>It resolves a target URI whose scheme is {@code "xds"}. The authority of the
39  * target URI is never used for current release. The path of the target URI, excluding the leading
40  * slash {@code '/'}, will indicate the name to use in the VHDS query.
41  *
42  * <p>This class should not be directly referenced in code. The resolver should be accessed
43  * through {@link io.grpc.NameResolverRegistry} with the URI scheme "xds".
44  */
45 @Internal
46 public final class XdsNameResolverProvider extends NameResolverProvider {
47 
48   private static final String SCHEME = "xds";
49   private final String scheme;
50   private final Map<String, ?> bootstrapOverride;
51 
XdsNameResolverProvider()52   public XdsNameResolverProvider() {
53     this(SCHEME, null);
54   }
55 
XdsNameResolverProvider(String scheme, @Nullable Map<String, ?> bootstrapOverride)56   private XdsNameResolverProvider(String scheme,
57                                  @Nullable Map<String, ?> bootstrapOverride) {
58     this.scheme = checkNotNull(scheme, "scheme");
59     this.bootstrapOverride = bootstrapOverride;
60   }
61 
62   /**
63    * A convenient method to allow creating a {@link XdsNameResolverProvider} with custom scheme
64    * and bootstrap.
65    */
createForTest(String scheme, @Nullable Map<String, ?> bootstrapOverride)66   public static XdsNameResolverProvider createForTest(String scheme,
67                                                       @Nullable Map<String, ?> bootstrapOverride) {
68     return new XdsNameResolverProvider(scheme, bootstrapOverride);
69   }
70 
71   @Override
newNameResolver(URI targetUri, Args args)72   public XdsNameResolver newNameResolver(URI targetUri, Args args) {
73     if (scheme.equals(targetUri.getScheme())) {
74       String targetPath = checkNotNull(targetUri.getPath(), "targetPath");
75       Preconditions.checkArgument(
76           targetPath.startsWith("/"),
77           "the path component (%s) of the target (%s) must start with '/'",
78           targetPath,
79           targetUri);
80       String name = targetPath.substring(1);
81       return new XdsNameResolver(
82           targetUri.getAuthority(), name, args.getOverrideAuthority(),
83           args.getServiceConfigParser(), args.getSynchronizationContext(),
84           args.getScheduledExecutorService(),
85           bootstrapOverride);
86     }
87     return null;
88   }
89 
90   @Override
getDefaultScheme()91   public String getDefaultScheme() {
92     return scheme;
93   }
94 
95   @Override
isAvailable()96   protected boolean isAvailable() {
97     return true;
98   }
99 
100   @Override
priority()101   protected int priority() {
102     // Set priority value to be < 5 as we still want DNS resolver to be the primary default
103     // resolver.
104     return 4;
105   }
106 
107   @Override
getProducedSocketAddressTypes()108   protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() {
109     return Collections.singleton(InetSocketAddress.class);
110   }
111 
112   interface XdsClientPoolFactory {
setBootstrapOverride(Map<String, ?> bootstrap)113     void setBootstrapOverride(Map<String, ?> bootstrap);
114 
115     @Nullable
get()116     ObjectPool<XdsClient> get();
117 
getOrCreate()118     ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException;
119   }
120 
121   /**
122    * Provides the counter for aggregating outstanding requests per cluster:eds_service_name.
123    */
124   interface CallCounterProvider {
getOrCreate(String cluster, @Nullable String edsServiceName)125     AtomicLong getOrCreate(String cluster, @Nullable String edsServiceName);
126   }
127 }
128