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.checkArgument; 20 21 import com.google.auto.value.AutoValue; 22 import com.google.common.annotations.VisibleForTesting; 23 import com.google.common.collect.ImmutableList; 24 import com.google.common.collect.ImmutableMap; 25 import io.grpc.ChannelCredentials; 26 import io.grpc.Internal; 27 import io.grpc.xds.EnvoyProtoData.Node; 28 import java.util.List; 29 import java.util.Map; 30 import javax.annotation.Nullable; 31 32 /** 33 * Loads configuration information to bootstrap gRPC's integration of xDS protocol. 34 */ 35 @Internal 36 public abstract class Bootstrapper { 37 38 static final String XDSTP_SCHEME = "xdstp:"; 39 40 /** 41 * Returns system-loaded bootstrap configuration. 42 */ bootstrap()43 public abstract BootstrapInfo bootstrap() throws XdsInitializationException; 44 45 /** 46 * Returns bootstrap configuration given by the raw data in JSON format. 47 */ bootstrap(Map<String, ?> rawData)48 BootstrapInfo bootstrap(Map<String, ?> rawData) throws XdsInitializationException { 49 throw new UnsupportedOperationException(); 50 } 51 52 /** 53 * Data class containing xDS server information, such as server URI and channel credentials 54 * to be used for communication. 55 */ 56 @AutoValue 57 @Internal 58 abstract static class ServerInfo { target()59 abstract String target(); 60 channelCredentials()61 abstract ChannelCredentials channelCredentials(); 62 ignoreResourceDeletion()63 abstract boolean ignoreResourceDeletion(); 64 65 @VisibleForTesting create( String target, ChannelCredentials channelCredentials)66 static ServerInfo create( 67 String target, ChannelCredentials channelCredentials) { 68 return new AutoValue_Bootstrapper_ServerInfo(target, channelCredentials, false); 69 } 70 71 @VisibleForTesting create( String target, ChannelCredentials channelCredentials, boolean ignoreResourceDeletion)72 static ServerInfo create( 73 String target, ChannelCredentials channelCredentials, 74 boolean ignoreResourceDeletion) { 75 return new AutoValue_Bootstrapper_ServerInfo(target, channelCredentials, 76 ignoreResourceDeletion); 77 } 78 } 79 80 /** 81 * Data class containing Certificate provider information: the plugin-name and an opaque 82 * Map that represents the config for that plugin. 83 */ 84 @AutoValue 85 @Internal 86 public abstract static class CertificateProviderInfo { pluginName()87 public abstract String pluginName(); 88 config()89 public abstract ImmutableMap<String, ?> config(); 90 91 @VisibleForTesting create(String pluginName, Map<String, ?> config)92 public static CertificateProviderInfo create(String pluginName, Map<String, ?> config) { 93 return new AutoValue_Bootstrapper_CertificateProviderInfo( 94 pluginName, ImmutableMap.copyOf(config)); 95 } 96 } 97 98 @AutoValue 99 abstract static class AuthorityInfo { 100 101 /** 102 * A template for the name of the Listener resource to subscribe to for a gRPC client 103 * channel. Used only when the channel is created using an "xds:" URI with this authority 104 * name. 105 * 106 * <p>The token "%s", if present in this string, will be replaced with %-encoded 107 * service authority (i.e., the path part of the target URI used to create the gRPC channel). 108 * 109 * <p>Return value must start with {@code "xdstp://<authority_name>/"}. 110 */ clientListenerResourceNameTemplate()111 abstract String clientListenerResourceNameTemplate(); 112 113 /** 114 * Ordered list of xDS servers to contact for this authority. 115 * 116 * <p>If the same server is listed in multiple authorities, the entries will be de-duped (i.e., 117 * resources for both authorities will be fetched on the same ADS stream). 118 * 119 * <p>Defaults to the top-level server list {@link BootstrapInfo#servers()}. Must not be empty. 120 */ xdsServers()121 abstract ImmutableList<ServerInfo> xdsServers(); 122 create( String clientListenerResourceNameTemplate, List<ServerInfo> xdsServers)123 static AuthorityInfo create( 124 String clientListenerResourceNameTemplate, List<ServerInfo> xdsServers) { 125 checkArgument(!xdsServers.isEmpty(), "xdsServers must not be empty"); 126 return new AutoValue_Bootstrapper_AuthorityInfo( 127 clientListenerResourceNameTemplate, ImmutableList.copyOf(xdsServers)); 128 } 129 } 130 131 /** 132 * Data class containing the results of reading bootstrap. 133 */ 134 @AutoValue 135 @Internal 136 public abstract static class BootstrapInfo { 137 /** Returns the list of xDS servers to be connected to. Must not be empty. */ servers()138 abstract ImmutableList<ServerInfo> servers(); 139 140 /** Returns the node identifier to be included in xDS requests. */ node()141 public abstract Node node(); 142 143 /** Returns the cert-providers config map. */ 144 @Nullable certProviders()145 public abstract ImmutableMap<String, CertificateProviderInfo> certProviders(); 146 147 /** 148 * A template for the name of the Listener resource to subscribe to for a gRPC server. 149 * 150 * <p>If starts with "xdstp:", will be interpreted as a new-style name, in which case the 151 * authority of the URI will be used to select the relevant configuration in the 152 * "authorities" map. The token "%s", if present in this string, will be replaced with 153 * the IP and port on which the server is listening. If the template starts with "xdstp:", 154 * the replaced string will be %-encoded. 155 * 156 * <p>There is no default; if unset, xDS-based server creation fails. 157 */ 158 @Nullable serverListenerResourceNameTemplate()159 public abstract String serverListenerResourceNameTemplate(); 160 161 /** 162 * A template for the name of the Listener resource to subscribe to for a gRPC client channel. 163 * Used only when the channel is created with an "xds:" URI with no authority. 164 * 165 * <p>If starts with "xdstp:", will be interpreted as a new-style name, in which case the 166 * authority of the URI will be used to select the relevant configuration in the "authorities" 167 * map. 168 * 169 * <p>The token "%s", if present in this string, will be replaced with the service authority 170 * (i.e., the path part of the target URI used to create the gRPC channel). If the template 171 * starts with "xdstp:", the replaced string will be %-encoded. 172 * 173 * <p>Defaults to {@code "%s"}. 174 */ clientDefaultListenerResourceNameTemplate()175 abstract String clientDefaultListenerResourceNameTemplate(); 176 177 /** 178 * A map of authority name to corresponding configuration. 179 * 180 * <p>This is used in the following cases: 181 * 182 * <ul> 183 * <li>A gRPC client channel is created using an "xds:" URI that includes an 184 * authority.</li> 185 * 186 * <li>A gRPC client channel is created using an "xds:" URI with no authority, 187 * but the "client_default_listener_resource_name_template" field above turns it into an 188 * "xdstp:" URI.</li> 189 * 190 * <li>A gRPC server is created and the "server_listener_resource_name_template" field is an 191 * "xdstp:" URI.</li> 192 * </ul> 193 * 194 * <p>In any of those cases, it is an error if the specified authority is not present in this 195 * map. 196 * 197 * <p>Defaults to an empty map. 198 */ authorities()199 abstract ImmutableMap<String, AuthorityInfo> authorities(); 200 201 @VisibleForTesting builder()202 static Builder builder() { 203 return new AutoValue_Bootstrapper_BootstrapInfo.Builder() 204 .clientDefaultListenerResourceNameTemplate("%s") 205 .authorities(ImmutableMap.<String, AuthorityInfo>of()); 206 } 207 208 @AutoValue.Builder 209 @VisibleForTesting 210 abstract static class Builder { 211 servers(List<ServerInfo> servers)212 abstract Builder servers(List<ServerInfo> servers); 213 node(Node node)214 abstract Builder node(Node node); 215 certProviders(@ullable Map<String, CertificateProviderInfo> certProviders)216 abstract Builder certProviders(@Nullable Map<String, CertificateProviderInfo> certProviders); 217 serverListenerResourceNameTemplate( @ullable String serverListenerResourceNameTemplate)218 abstract Builder serverListenerResourceNameTemplate( 219 @Nullable String serverListenerResourceNameTemplate); 220 clientDefaultListenerResourceNameTemplate( String clientDefaultListenerResourceNameTemplate)221 abstract Builder clientDefaultListenerResourceNameTemplate( 222 String clientDefaultListenerResourceNameTemplate); 223 authorities(Map<String, AuthorityInfo> authorities)224 abstract Builder authorities(Map<String, AuthorityInfo> authorities); 225 build()226 abstract BootstrapInfo build(); 227 } 228 } 229 } 230