|
17 | 17 | package io.grpc.xds;
|
18 | 18 |
|
19 | 19 | import com.google.common.annotations.VisibleForTesting;
|
| 20 | +import com.google.common.collect.ImmutableList; |
| 21 | +import com.google.common.collect.ImmutableMap; |
20 | 22 | import io.grpc.ChannelCredentials;
|
21 | 23 | import io.grpc.InsecureChannelCredentials;
|
22 | 24 | import io.grpc.Internal;
|
|
33 | 35 | import java.nio.charset.StandardCharsets;
|
34 | 36 | import java.nio.file.Files;
|
35 | 37 | import java.nio.file.Paths;
|
36 |
| -import java.util.ArrayList; |
37 | 38 | import java.util.HashMap;
|
38 | 39 | import java.util.List;
|
39 | 40 | import java.util.Map;
|
@@ -121,41 +122,14 @@ public BootstrapInfo bootstrap() throws XdsInitializationException {
|
121 | 122 |
|
122 | 123 | @Override
|
123 | 124 | BootstrapInfo bootstrap(Map<String, ?> rawData) throws XdsInitializationException {
|
124 |
| - List<ServerInfo> servers = new ArrayList<>(); |
| 125 | + BootstrapInfo.Builder builder = BootstrapInfo.builder(); |
| 126 | + |
125 | 127 | List<?> rawServerConfigs = JsonUtil.getList(rawData, "xds_servers");
|
126 | 128 | if (rawServerConfigs == null) {
|
127 | 129 | throw new XdsInitializationException("Invalid bootstrap: 'xds_servers' does not exist.");
|
128 | 130 | }
|
129 |
| - logger.log(XdsLogLevel.INFO, "Configured with {0} xDS servers", rawServerConfigs.size()); |
130 |
| - // TODO(chengyuanzhang): require at least one server URI. |
131 |
| - List<Map<String, ?>> serverConfigList = JsonUtil.checkObjectList(rawServerConfigs); |
132 |
| - for (Map<String, ?> serverConfig : serverConfigList) { |
133 |
| - String serverUri = JsonUtil.getString(serverConfig, "server_uri"); |
134 |
| - if (serverUri == null) { |
135 |
| - throw new XdsInitializationException("Invalid bootstrap: missing 'server_uri'"); |
136 |
| - } |
137 |
| - logger.log(XdsLogLevel.INFO, "xDS server URI: {0}", serverUri); |
138 |
| - |
139 |
| - List<?> rawChannelCredsList = JsonUtil.getList(serverConfig, "channel_creds"); |
140 |
| - if (rawChannelCredsList == null || rawChannelCredsList.isEmpty()) { |
141 |
| - throw new XdsInitializationException( |
142 |
| - "Invalid bootstrap: server " + serverUri + " 'channel_creds' required"); |
143 |
| - } |
144 |
| - ChannelCredentials channelCredentials = |
145 |
| - parseChannelCredentials(JsonUtil.checkObjectList(rawChannelCredsList), serverUri); |
146 |
| - if (channelCredentials == null) { |
147 |
| - throw new XdsInitializationException( |
148 |
| - "Server " + serverUri + ": no supported channel credentials found"); |
149 |
| - } |
150 |
| - |
151 |
| - boolean useProtocolV3 = false; |
152 |
| - List<String> serverFeatures = JsonUtil.getListOfStrings(serverConfig, "server_features"); |
153 |
| - if (serverFeatures != null) { |
154 |
| - logger.log(XdsLogLevel.INFO, "Server features: {0}", serverFeatures); |
155 |
| - useProtocolV3 = serverFeatures.contains(XDS_V3_SERVER_FEATURE); |
156 |
| - } |
157 |
| - servers.add(ServerInfo.create(serverUri, channelCredentials, useProtocolV3)); |
158 |
| - } |
| 131 | + List<ServerInfo> servers = parseServerInfos(rawServerConfigs, logger); |
| 132 | + builder.servers(servers); |
159 | 133 |
|
160 | 134 | Node.Builder nodeBuilder = Node.newBuilder();
|
161 | 135 | Map<String, ?> rawNode = JsonUtil.getObject(rawData, "node");
|
@@ -200,29 +174,110 @@ BootstrapInfo bootstrap(Map<String, ?> rawData) throws XdsInitializationExceptio
|
200 | 174 | nodeBuilder.setUserAgentName(buildVersion.getUserAgent());
|
201 | 175 | nodeBuilder.setUserAgentVersion(buildVersion.getImplementationVersion());
|
202 | 176 | nodeBuilder.addClientFeatures(CLIENT_FEATURE_DISABLE_OVERPROVISIONING);
|
| 177 | + builder.node(nodeBuilder.build()); |
203 | 178 |
|
204 | 179 | Map<String, ?> certProvidersBlob = JsonUtil.getObject(rawData, "certificate_providers");
|
205 |
| - Map<String, CertificateProviderInfo> certProviders = null; |
206 | 180 | if (certProvidersBlob != null) {
|
207 |
| - certProviders = new HashMap<>(certProvidersBlob.size()); |
| 181 | + logger.log(XdsLogLevel.INFO, "Configured with {0} cert providers", certProvidersBlob.size()); |
| 182 | + Map<String, CertificateProviderInfo> certProviders = new HashMap<>(certProvidersBlob.size()); |
208 | 183 | for (String name : certProvidersBlob.keySet()) {
|
209 | 184 | Map<String, ?> valueMap = JsonUtil.getObject(certProvidersBlob, name);
|
210 | 185 | String pluginName =
|
211 | 186 | checkForNull(JsonUtil.getString(valueMap, "plugin_name"), "plugin_name");
|
| 187 | + logger.log(XdsLogLevel.INFO, "cert provider: {0}, plugin name: {1}", name, pluginName); |
212 | 188 | Map<String, ?> config = checkForNull(JsonUtil.getObject(valueMap, "config"), "config");
|
213 | 189 | CertificateProviderInfo certificateProviderInfo =
|
214 | 190 | CertificateProviderInfo.create(pluginName, config);
|
215 | 191 | certProviders.put(name, certificateProviderInfo);
|
216 | 192 | }
|
| 193 | + builder.certProviders(certProviders); |
217 | 194 | }
|
| 195 | + |
218 | 196 | String grpcServerResourceId =
|
219 | 197 | JsonUtil.getString(rawData, "server_listener_resource_name_template");
|
220 |
| - return BootstrapInfo.builder() |
221 |
| - .servers(servers) |
222 |
| - .node(nodeBuilder.build()) |
223 |
| - .certProviders(certProviders) |
224 |
| - .serverListenerResourceNameTemplate(grpcServerResourceId) |
225 |
| - .build(); |
| 198 | + logger.log( |
| 199 | + XdsLogLevel.INFO, "server_listener_resource_name_template: {0}", grpcServerResourceId); |
| 200 | + builder.serverListenerResourceNameTemplate(grpcServerResourceId); |
| 201 | + |
| 202 | + String grpcClientDefaultListener = |
| 203 | + JsonUtil.getString(rawData, "client_default_listener_resource_name_template"); |
| 204 | + logger.log( |
| 205 | + XdsLogLevel.INFO, "client_default_listener_resource_name_template: {0}", |
| 206 | + grpcClientDefaultListener); |
| 207 | + if (grpcClientDefaultListener != null) { |
| 208 | + builder.clientDefaultListenerResourceNameTemplate(grpcClientDefaultListener); |
| 209 | + } |
| 210 | + |
| 211 | + Map<String, ?> rawAuthoritiesMap = |
| 212 | + JsonUtil.getObject(rawData, "authorities"); |
| 213 | + ImmutableMap.Builder<String, AuthorityInfo> authorityInfoMapBuilder = ImmutableMap.builder(); |
| 214 | + if (rawAuthoritiesMap != null) { |
| 215 | + logger.log( |
| 216 | + XdsLogLevel.INFO, "Configured with {0} xDS server authorities", rawAuthoritiesMap.size()); |
| 217 | + for (String authorityName : rawAuthoritiesMap.keySet()) { |
| 218 | + logger.log(XdsLogLevel.INFO, "xDS server authority: {0}", authorityName); |
| 219 | + Map<String, ?> rawAuthority = JsonUtil.getObject(rawAuthoritiesMap, authorityName); |
| 220 | + String clientListnerTemplate = |
| 221 | + JsonUtil.getString(rawAuthority, "client_listener_resource_name_template"); |
| 222 | + logger.log( |
| 223 | + XdsLogLevel.INFO, "client_listener_resource_name_template: {0}", clientListnerTemplate); |
| 224 | + String prefix = "xdstp://" + authorityName + "/"; |
| 225 | + if (clientListnerTemplate == null) { |
| 226 | + clientListnerTemplate = prefix + "envoy.config.listener.v3.Listener/%s"; |
| 227 | + } else if (!clientListnerTemplate.startsWith(prefix)) { |
| 228 | + throw new XdsInitializationException( |
| 229 | + "client_listener_resource_name_template: '" + clientListnerTemplate |
| 230 | + + "' does not start with " + prefix); |
| 231 | + } |
| 232 | + List<?> rawAuthorityServers = JsonUtil.getList(rawAuthority, "xds_servers"); |
| 233 | + List<ServerInfo> authorityServers; |
| 234 | + if (rawAuthorityServers == null || rawAuthorityServers.isEmpty()) { |
| 235 | + authorityServers = servers; |
| 236 | + } else { |
| 237 | + authorityServers = parseServerInfos(rawAuthorityServers, logger); |
| 238 | + } |
| 239 | + authorityInfoMapBuilder.put( |
| 240 | + authorityName, AuthorityInfo.create(clientListnerTemplate, authorityServers)); |
| 241 | + } |
| 242 | + builder.authorities(authorityInfoMapBuilder.build()); |
| 243 | + } |
| 244 | + |
| 245 | + return builder.build(); |
| 246 | + } |
| 247 | + |
| 248 | + private static List<ServerInfo> parseServerInfos(List<?> rawServerConfigs, XdsLogger logger) |
| 249 | + throws XdsInitializationException { |
| 250 | + logger.log(XdsLogLevel.INFO, "Configured with {0} xDS servers", rawServerConfigs.size()); |
| 251 | + ImmutableList.Builder<ServerInfo> servers = ImmutableList.builder(); |
| 252 | + List<Map<String, ?>> serverConfigList = JsonUtil.checkObjectList(rawServerConfigs); |
| 253 | + for (Map<String, ?> serverConfig : serverConfigList) { |
| 254 | + String serverUri = JsonUtil.getString(serverConfig, "server_uri"); |
| 255 | + if (serverUri == null) { |
| 256 | + throw new XdsInitializationException("Invalid bootstrap: missing 'server_uri'"); |
| 257 | + } |
| 258 | + logger.log(XdsLogLevel.INFO, "xDS server URI: {0}", serverUri); |
| 259 | + |
| 260 | + List<?> rawChannelCredsList = JsonUtil.getList(serverConfig, "channel_creds"); |
| 261 | + if (rawChannelCredsList == null || rawChannelCredsList.isEmpty()) { |
| 262 | + throw new XdsInitializationException( |
| 263 | + "Invalid bootstrap: server " + serverUri + " 'channel_creds' required"); |
| 264 | + } |
| 265 | + ChannelCredentials channelCredentials = |
| 266 | + parseChannelCredentials(JsonUtil.checkObjectList(rawChannelCredsList), serverUri); |
| 267 | + if (channelCredentials == null) { |
| 268 | + throw new XdsInitializationException( |
| 269 | + "Server " + serverUri + ": no supported channel credentials found"); |
| 270 | + } |
| 271 | + |
| 272 | + boolean useProtocolV3 = false; |
| 273 | + List<String> serverFeatures = JsonUtil.getListOfStrings(serverConfig, "server_features"); |
| 274 | + if (serverFeatures != null) { |
| 275 | + logger.log(XdsLogLevel.INFO, "Server features: {0}", serverFeatures); |
| 276 | + useProtocolV3 = serverFeatures.contains(XDS_V3_SERVER_FEATURE); |
| 277 | + } |
| 278 | + servers.add(ServerInfo.create(serverUri, channelCredentials, useProtocolV3)); |
| 279 | + } |
| 280 | + return servers.build(); |
226 | 281 | }
|
227 | 282 |
|
228 | 283 | @VisibleForTesting
|
|
0 commit comments