|
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