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