github.com/cdmixer/woolloomooloo@v0.1.0/grpc-go/xds/internal/xdsclient/client.go (about) 1 /* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package xdsclient implements a full fledged gRPC client for the xDS API used 20 // by the xds resolver and balancer implementations. 21 package xdsclient 22 23 import ( 24 "context" 25 "errors" 26 "fmt" 27 "regexp" 28 "sync" 29 "time" 30 31 v2corepb "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" 32 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 33 "github.com/golang/protobuf/proto" 34 "google.golang.org/protobuf/types/known/anypb" 35 36 "google.golang.org/grpc/internal/xds/matcher" 37 "google.golang.org/grpc/xds/internal/httpfilter" 38 "google.golang.org/grpc/xds/internal/xdsclient/load" 39 40 "google.golang.org/grpc" 41 "google.golang.org/grpc/internal/backoff" 42 "google.golang.org/grpc/internal/buffer" 43 "google.golang.org/grpc/internal/grpclog" 44 "google.golang.org/grpc/internal/grpcsync" 45 "google.golang.org/grpc/keepalive" 46 "google.golang.org/grpc/xds/internal" 47 "google.golang.org/grpc/xds/internal/version" 48 "google.golang.org/grpc/xds/internal/xdsclient/bootstrap" 49 ) 50 51 var ( 52 m = make(map[version.TransportAPI]APIClientBuilder) 53 ) 54 55 // RegisterAPIClientBuilder registers a client builder for xDS transport protocol 56 // version specified by b.Version(). 57 // 58 // NOTE: this function must only be called during initialization time (i.e. in 59 // an init() function), and is not thread-safe. If multiple builders are 60 // registered for the same version, the one registered last will take effect. 61 func RegisterAPIClientBuilder(b APIClientBuilder) { 62 m[b.Version()] = b 63 } 64 65 // getAPIClientBuilder returns the client builder registered for the provided 66 // xDS transport API version. 67 func getAPIClientBuilder(version version.TransportAPI) APIClientBuilder { 68 if b, ok := m[version]; ok { 69 return b 70 } 71 return nil 72 } 73 74 // BuildOptions contains options to be passed to client builders. 75 type BuildOptions struct { 76 // Parent is a top-level xDS client which has the intelligence to take 77 // appropriate action based on xDS responses received from the management 78 // server. 79 Parent UpdateHandler 80 // NodeProto contains the Node proto to be used in xDS requests. The actual 81 // type depends on the transport protocol version used. 82 NodeProto proto.Message 83 // Backoff returns the amount of time to backoff before retrying broken 84 // streams. 85 Backoff func(int) time.Duration 86 // Logger provides enhanced logging capabilities. 87 Logger *grpclog.PrefixLogger 88 } 89 90 // APIClientBuilder creates an xDS client for a specific xDS transport protocol 91 // version. 92 type APIClientBuilder interface { 93 // Build builds a transport protocol specific implementation of the xDS 94 // client based on the provided clientConn to the management server and the 95 // provided options. 96 Build(*grpc.ClientConn, BuildOptions) (APIClient, error) 97 // Version returns the xDS transport protocol version used by clients build 98 // using this builder. 99 Version() version.TransportAPI 100 } 101 102 // APIClient represents the functionality provided by transport protocol 103 // version specific implementations of the xDS client. 104 // 105 // TODO: unexport this interface and all the methods after the PR to make 106 // xdsClient sharable by clients. AddWatch and RemoveWatch are exported for 107 // v2/v3 to override because they need to keep track of LDS name for RDS to use. 108 // After the share xdsClient change, that's no longer necessary. After that, we 109 // will still keep this interface for testing purposes. 110 type APIClient interface { 111 // AddWatch adds a watch for an xDS resource given its type and name. 112 AddWatch(ResourceType, string) 113 114 // RemoveWatch cancels an already registered watch for an xDS resource 115 // given its type and name. 116 RemoveWatch(ResourceType, string) 117 118 // reportLoad starts an LRS stream to periodically report load using the 119 // provided ClientConn, which represent a connection to the management 120 // server. 121 reportLoad(ctx context.Context, cc *grpc.ClientConn, opts loadReportingOptions) 122 123 // Close cleans up resources allocated by the API client. 124 Close() 125 } 126 127 // loadReportingOptions contains configuration knobs for reporting load data. 128 type loadReportingOptions struct { 129 loadStore *load.Store 130 } 131 132 // UpdateHandler receives and processes (by taking appropriate actions) xDS 133 // resource updates from an APIClient for a specific version. 134 type UpdateHandler interface { 135 // NewListeners handles updates to xDS listener resources. 136 NewListeners(map[string]ListenerUpdate, UpdateMetadata) 137 // NewRouteConfigs handles updates to xDS RouteConfiguration resources. 138 NewRouteConfigs(map[string]RouteConfigUpdate, UpdateMetadata) 139 // NewClusters handles updates to xDS Cluster resources. 140 NewClusters(map[string]ClusterUpdate, UpdateMetadata) 141 // NewEndpoints handles updates to xDS ClusterLoadAssignment (or tersely 142 // referred to as Endpoints) resources. 143 NewEndpoints(map[string]EndpointsUpdate, UpdateMetadata) 144 // NewConnectionError handles connection errors from the xDS stream. The 145 // error will be reported to all the resource watchers. 146 NewConnectionError(err error) 147 } 148 149 // ServiceStatus is the status of the update. 150 type ServiceStatus int 151 152 const ( 153 // ServiceStatusUnknown is the default state, before a watch is started for 154 // the resource. 155 ServiceStatusUnknown ServiceStatus = iota 156 // ServiceStatusRequested is when the watch is started, but before and 157 // response is received. 158 ServiceStatusRequested 159 // ServiceStatusNotExist is when the resource doesn't exist in 160 // state-of-the-world responses (e.g. LDS and CDS), which means the resource 161 // is removed by the management server. 162 ServiceStatusNotExist // Resource is removed in the server, in LDS/CDS. 163 // ServiceStatusACKed is when the resource is ACKed. 164 ServiceStatusACKed 165 // ServiceStatusNACKed is when the resource is NACKed. 166 ServiceStatusNACKed 167 ) 168 169 // UpdateErrorMetadata is part of UpdateMetadata. It contains the error state 170 // when a response is NACKed. 171 type UpdateErrorMetadata struct { 172 // Version is the version of the NACKed response. 173 Version string 174 // Err contains why the response was NACKed. 175 Err error 176 // Timestamp is when the NACKed response was received. 177 Timestamp time.Time 178 } 179 180 // UpdateMetadata contains the metadata for each update, including timestamp, 181 // raw message, and so on. 182 type UpdateMetadata struct { 183 // Status is the status of this resource, e.g. ACKed, NACKed, or 184 // Not_exist(removed). 185 Status ServiceStatus 186 // Version is the version of the xds response. Note that this is the version 187 // of the resource in use (previous ACKed). If a response is NACKed, the 188 // NACKed version is in ErrState. 189 Version string 190 // Timestamp is when the response is received. 191 Timestamp time.Time 192 // ErrState is set when the update is NACKed. 193 ErrState *UpdateErrorMetadata 194 } 195 196 // ListenerUpdate contains information received in an LDS response, which is of 197 // interest to the registered LDS watcher. 198 type ListenerUpdate struct { 199 // RouteConfigName is the route configuration name corresponding to the 200 // target which is being watched through LDS. 201 // 202 // Only one of RouteConfigName and InlineRouteConfig is set. 203 RouteConfigName string 204 // InlineRouteConfig is the inline route configuration (RDS response) 205 // returned inside LDS. 206 // 207 // Only one of RouteConfigName and InlineRouteConfig is set. 208 InlineRouteConfig *RouteConfigUpdate 209 210 // MaxStreamDuration contains the HTTP connection manager's 211 // common_http_protocol_options.max_stream_duration field, or zero if 212 // unset. 213 MaxStreamDuration time.Duration 214 // HTTPFilters is a list of HTTP filters (name, config) from the LDS 215 // response. 216 HTTPFilters []HTTPFilter 217 // InboundListenerCfg contains inbound listener configuration. 218 InboundListenerCfg *InboundListenerConfig 219 220 // Raw is the resource from the xds response. 221 Raw *anypb.Any 222 } 223 224 // HTTPFilter represents one HTTP filter from an LDS response's HTTP connection 225 // manager field. 226 type HTTPFilter struct { 227 // Name is an arbitrary name of the filter. Used for applying override 228 // settings in virtual host / route / weighted cluster configuration (not 229 // yet supported). 230 Name string 231 // Filter is the HTTP filter found in the registry for the config type. 232 Filter httpfilter.Filter 233 // Config contains the filter's configuration 234 Config httpfilter.FilterConfig 235 } 236 237 // InboundListenerConfig contains information about the inbound listener, i.e 238 // the server-side listener. 239 type InboundListenerConfig struct { 240 // Address is the local address on which the inbound listener is expected to 241 // accept incoming connections. 242 Address string 243 // Port is the local port on which the inbound listener is expected to 244 // accept incoming connections. 245 Port string 246 // FilterChains is the list of filter chains associated with this listener. 247 FilterChains *FilterChainManager 248 } 249 250 // RouteConfigUpdate contains information received in an RDS response, which is 251 // of interest to the registered RDS watcher. 252 type RouteConfigUpdate struct { 253 VirtualHosts []*VirtualHost 254 255 // Raw is the resource from the xds response. 256 Raw *anypb.Any 257 } 258 259 // VirtualHost contains the routes for a list of Domains. 260 // 261 // Note that the domains in this slice can be a wildcard, not an exact string. 262 // The consumer of this struct needs to find the best match for its hostname. 263 type VirtualHost struct { 264 Domains []string 265 // Routes contains a list of routes, each containing matchers and 266 // corresponding action. 267 Routes []*Route 268 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 269 // the virtual host which may be present. An individual filter's override 270 // may be unused if the matching Route contains an override for that 271 // filter. 272 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 273 } 274 275 // HashPolicyType specifies the type of HashPolicy from a received RDS Response. 276 type HashPolicyType int 277 278 const ( 279 // HashPolicyTypeHeader specifies to hash a Header in the incoming request. 280 HashPolicyTypeHeader HashPolicyType = iota 281 // HashPolicyTypeChannelID specifies to hash a unique Identifier of the 282 // Channel. In grpc-go, this will be done using the ClientConn pointer. 283 HashPolicyTypeChannelID 284 ) 285 286 // HashPolicy specifies the HashPolicy if the upstream cluster uses a hashing 287 // load balancer. 288 type HashPolicy struct { 289 HashPolicyType HashPolicyType 290 Terminal bool 291 // Fields used for type HEADER. 292 HeaderName string 293 Regex *regexp.Regexp 294 RegexSubstitution string 295 } 296 297 // RouteAction is the action of the route from a received RDS response. 298 type RouteAction int 299 300 const ( 301 // RouteActionUnsupported are routing types currently unsupported by grpc. 302 // According to A36, "A Route with an inappropriate action causes RPCs 303 // matching that route to fail." 304 RouteActionUnsupported RouteAction = iota 305 // RouteActionRoute is the expected route type on the client side. Route 306 // represents routing a request to some upstream cluster. On the client 307 // side, if an RPC matches to a route that is not RouteActionRoute, the RPC 308 // will fail according to A36. 309 RouteActionRoute 310 // RouteActionNonForwardingAction is the expected route type on the server 311 // side. NonForwardingAction represents when a route will generate a 312 // response directly, without forwarding to an upstream host. 313 RouteActionNonForwardingAction 314 ) 315 316 // Route is both a specification of how to match a request as well as an 317 // indication of the action to take upon match. 318 type Route struct { 319 Path *string 320 Prefix *string 321 Regex *regexp.Regexp 322 // Indicates if prefix/path matching should be case insensitive. The default 323 // is false (case sensitive). 324 CaseInsensitive bool 325 Headers []*HeaderMatcher 326 Fraction *uint32 327 328 HashPolicies []*HashPolicy 329 330 // If the matchers above indicate a match, the below configuration is used. 331 WeightedClusters map[string]WeightedCluster 332 // If MaxStreamDuration is nil, it indicates neither of the route action's 333 // max_stream_duration fields (grpc_timeout_header_max nor 334 // max_stream_duration) were set. In this case, the ListenerUpdate's 335 // MaxStreamDuration field should be used. If MaxStreamDuration is set to 336 // an explicit zero duration, the application's deadline should be used. 337 MaxStreamDuration *time.Duration 338 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 339 // the route which may be present. An individual filter's override may be 340 // unused if the matching WeightedCluster contains an override for that 341 // filter. 342 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 343 344 RouteAction RouteAction 345 } 346 347 // WeightedCluster contains settings for an xds RouteAction.WeightedCluster. 348 type WeightedCluster struct { 349 // Weight is the relative weight of the cluster. It will never be zero. 350 Weight uint32 351 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 352 // the weighted cluster which may be present. 353 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 354 } 355 356 // HeaderMatcher represents header matchers. 357 type HeaderMatcher struct { 358 Name string 359 InvertMatch *bool 360 ExactMatch *string 361 RegexMatch *regexp.Regexp 362 PrefixMatch *string 363 SuffixMatch *string 364 RangeMatch *Int64Range 365 PresentMatch *bool 366 } 367 368 // Int64Range is a range for header range match. 369 type Int64Range struct { 370 Start int64 371 End int64 372 } 373 374 // SecurityConfig contains the security configuration received as part of the 375 // Cluster resource on the client-side, and as part of the Listener resource on 376 // the server-side. 377 type SecurityConfig struct { 378 // RootInstanceName identifies the certProvider plugin to be used to fetch 379 // root certificates. This instance name will be resolved to the plugin name 380 // and its associated configuration from the certificate_providers field of 381 // the bootstrap file. 382 RootInstanceName string 383 // RootCertName is the certificate name to be passed to the plugin (looked 384 // up from the bootstrap file) while fetching root certificates. 385 RootCertName string 386 // IdentityInstanceName identifies the certProvider plugin to be used to 387 // fetch identity certificates. This instance name will be resolved to the 388 // plugin name and its associated configuration from the 389 // certificate_providers field of the bootstrap file. 390 IdentityInstanceName string 391 // IdentityCertName is the certificate name to be passed to the plugin 392 // (looked up from the bootstrap file) while fetching identity certificates. 393 IdentityCertName string 394 // SubjectAltNameMatchers is an optional list of match criteria for SANs 395 // specified on the peer certificate. Used only on the client-side. 396 // 397 // Some intricacies: 398 // - If this field is empty, then any peer certificate is accepted. 399 // - If the peer certificate contains a wildcard DNS SAN, and an `exact` 400 // matcher is configured, a wildcard DNS match is performed instead of a 401 // regular string comparison. 402 SubjectAltNameMatchers []matcher.StringMatcher 403 // RequireClientCert indicates if the server handshake process expects the 404 // client to present a certificate. Set to true when performing mTLS. Used 405 // only on the server-side. 406 RequireClientCert bool 407 } 408 409 // ClusterType is the type of cluster from a received CDS response. 410 type ClusterType int 411 412 const ( 413 // ClusterTypeEDS represents the EDS cluster type, which will delegate endpoint 414 // discovery to the management server. 415 ClusterTypeEDS ClusterType = iota 416 // ClusterTypeLogicalDNS represents the Logical DNS cluster type, which essentially 417 // maps to the gRPC behavior of using the DNS resolver with pick_first LB policy. 418 ClusterTypeLogicalDNS 419 // ClusterTypeAggregate represents the Aggregate Cluster type, which provides a 420 // prioritized list of clusters to use. It is used for failover between clusters 421 // with a different configuration. 422 ClusterTypeAggregate 423 ) 424 425 // ClusterUpdate contains information from a received CDS response, which is of 426 // interest to the registered CDS watcher. 427 type ClusterUpdate struct { 428 ClusterType ClusterType 429 // ClusterName is the clusterName being watched for through CDS. 430 ClusterName string 431 // EDSServiceName is an optional name for EDS. If it's not set, the balancer 432 // should watch ClusterName for the EDS resources. 433 EDSServiceName string 434 // EnableLRS indicates whether or not load should be reported through LRS. 435 EnableLRS bool 436 // SecurityCfg contains security configuration sent by the control plane. 437 SecurityCfg *SecurityConfig 438 // MaxRequests for circuit breaking, if any (otherwise nil). 439 MaxRequests *uint32 440 // DNSHostName is used only for cluster type DNS. It's the DNS name to 441 // resolve in "host:port" form 442 DNSHostName string 443 // PrioritizedClusterNames is used only for cluster type aggregate. It represents 444 // a prioritized list of cluster names. 445 PrioritizedClusterNames []string 446 447 // Raw is the resource from the xds response. 448 Raw *anypb.Any 449 } 450 451 // OverloadDropConfig contains the config to drop overloads. 452 type OverloadDropConfig struct { 453 Category string 454 Numerator uint32 455 Denominator uint32 456 } 457 458 // EndpointHealthStatus represents the health status of an endpoint. 459 type EndpointHealthStatus int32 460 461 const ( 462 // EndpointHealthStatusUnknown represents HealthStatus UNKNOWN. 463 EndpointHealthStatusUnknown EndpointHealthStatus = iota 464 // EndpointHealthStatusHealthy represents HealthStatus HEALTHY. 465 EndpointHealthStatusHealthy 466 // EndpointHealthStatusUnhealthy represents HealthStatus UNHEALTHY. 467 EndpointHealthStatusUnhealthy 468 // EndpointHealthStatusDraining represents HealthStatus DRAINING. 469 EndpointHealthStatusDraining 470 // EndpointHealthStatusTimeout represents HealthStatus TIMEOUT. 471 EndpointHealthStatusTimeout 472 // EndpointHealthStatusDegraded represents HealthStatus DEGRADED. 473 EndpointHealthStatusDegraded 474 ) 475 476 // Endpoint contains information of an endpoint. 477 type Endpoint struct { 478 Address string 479 HealthStatus EndpointHealthStatus 480 Weight uint32 481 } 482 483 // Locality contains information of a locality. 484 type Locality struct { 485 Endpoints []Endpoint 486 ID internal.LocalityID 487 Priority uint32 488 Weight uint32 489 } 490 491 // EndpointsUpdate contains an EDS update. 492 type EndpointsUpdate struct { 493 Drops []OverloadDropConfig 494 Localities []Locality 495 496 // Raw is the resource from the xds response. 497 Raw *anypb.Any 498 } 499 500 // Function to be overridden in tests. 501 var newAPIClient = func(apiVersion version.TransportAPI, cc *grpc.ClientConn, opts BuildOptions) (APIClient, error) { 502 cb := getAPIClientBuilder(apiVersion) 503 if cb == nil { 504 return nil, fmt.Errorf("no client builder for xDS API version: %v", apiVersion) 505 } 506 return cb.Build(cc, opts) 507 } 508 509 // clientImpl is the real implementation of the xds client. The exported Client 510 // is a wrapper of this struct with a ref count. 511 // 512 // Implements UpdateHandler interface. 513 // TODO(easwars): Make a wrapper struct which implements this interface in the 514 // style of ccBalancerWrapper so that the Client type does not implement these 515 // exported methods. 516 type clientImpl struct { 517 done *grpcsync.Event 518 config *bootstrap.Config 519 cc *grpc.ClientConn // Connection to the management server. 520 apiClient APIClient 521 watchExpiryTimeout time.Duration 522 523 logger *grpclog.PrefixLogger 524 525 updateCh *buffer.Unbounded // chan *watcherInfoWithUpdate 526 // All the following maps are to keep the updates/metadata in a cache. 527 // TODO: move them to a separate struct/package, to cleanup the xds_client. 528 // And CSDS handler can be implemented directly by the cache. 529 mu sync.Mutex 530 ldsWatchers map[string]map[*watchInfo]bool 531 ldsVersion string // Only used in CSDS. 532 ldsCache map[string]ListenerUpdate 533 ldsMD map[string]UpdateMetadata 534 rdsWatchers map[string]map[*watchInfo]bool 535 rdsVersion string // Only used in CSDS. 536 rdsCache map[string]RouteConfigUpdate 537 rdsMD map[string]UpdateMetadata 538 cdsWatchers map[string]map[*watchInfo]bool 539 cdsVersion string // Only used in CSDS. 540 cdsCache map[string]ClusterUpdate 541 cdsMD map[string]UpdateMetadata 542 edsWatchers map[string]map[*watchInfo]bool 543 edsVersion string // Only used in CSDS. 544 edsCache map[string]EndpointsUpdate 545 edsMD map[string]UpdateMetadata 546 547 // Changes to map lrsClients and the lrsClient inside the map need to be 548 // protected by lrsMu. 549 lrsMu sync.Mutex 550 lrsClients map[string]*lrsClient 551 } 552 553 // newWithConfig returns a new xdsClient with the given config. 554 func newWithConfig(config *bootstrap.Config, watchExpiryTimeout time.Duration) (*clientImpl, error) { 555 switch { 556 case config.BalancerName == "": 557 return nil, errors.New("xds: no xds_server name provided in options") 558 case config.Creds == nil: 559 return nil, errors.New("xds: no credentials provided in options") 560 case config.NodeProto == nil: 561 return nil, errors.New("xds: no node_proto provided in options") 562 } 563 564 switch config.TransportAPI { 565 case version.TransportV2: 566 if _, ok := config.NodeProto.(*v2corepb.Node); !ok { 567 return nil, fmt.Errorf("xds: Node proto type (%T) does not match API version: %v", config.NodeProto, config.TransportAPI) 568 } 569 case version.TransportV3: 570 if _, ok := config.NodeProto.(*v3corepb.Node); !ok { 571 return nil, fmt.Errorf("xds: Node proto type (%T) does not match API version: %v", config.NodeProto, config.TransportAPI) 572 } 573 } 574 575 dopts := []grpc.DialOption{ 576 config.Creds, 577 grpc.WithKeepaliveParams(keepalive.ClientParameters{ 578 Time: 5 * time.Minute, 579 Timeout: 20 * time.Second, 580 }), 581 } 582 583 c := &clientImpl{ 584 done: grpcsync.NewEvent(), 585 config: config, 586 watchExpiryTimeout: watchExpiryTimeout, 587 588 updateCh: buffer.NewUnbounded(), 589 ldsWatchers: make(map[string]map[*watchInfo]bool), 590 ldsCache: make(map[string]ListenerUpdate), 591 ldsMD: make(map[string]UpdateMetadata), 592 rdsWatchers: make(map[string]map[*watchInfo]bool), 593 rdsCache: make(map[string]RouteConfigUpdate), 594 rdsMD: make(map[string]UpdateMetadata), 595 cdsWatchers: make(map[string]map[*watchInfo]bool), 596 cdsCache: make(map[string]ClusterUpdate), 597 cdsMD: make(map[string]UpdateMetadata), 598 edsWatchers: make(map[string]map[*watchInfo]bool), 599 edsCache: make(map[string]EndpointsUpdate), 600 edsMD: make(map[string]UpdateMetadata), 601 lrsClients: make(map[string]*lrsClient), 602 } 603 604 cc, err := grpc.Dial(config.BalancerName, dopts...) 605 if err != nil { 606 // An error from a non-blocking dial indicates something serious. 607 return nil, fmt.Errorf("xds: failed to dial balancer {%s}: %v", config.BalancerName, err) 608 } 609 c.cc = cc 610 c.logger = prefixLogger((c)) 611 c.logger.Infof("Created ClientConn to xDS management server: %s", config.BalancerName) 612 613 apiClient, err := newAPIClient(config.TransportAPI, cc, BuildOptions{ 614 Parent: c, 615 NodeProto: config.NodeProto, 616 Backoff: backoff.DefaultExponential.Backoff, 617 Logger: c.logger, 618 }) 619 if err != nil { 620 return nil, err 621 } 622 c.apiClient = apiClient 623 c.logger.Infof("Created") 624 go c.run() 625 return c, nil 626 } 627 628 // BootstrapConfig returns the configuration read from the bootstrap file. 629 // Callers must treat the return value as read-only. 630 func (c *clientRefCounted) BootstrapConfig() *bootstrap.Config { 631 return c.config 632 } 633 634 // run is a goroutine for all the callbacks. 635 // 636 // Callback can be called in watch(), if an item is found in cache. Without this 637 // goroutine, the callback will be called inline, which might cause a deadlock 638 // in user's code. Callbacks also cannot be simple `go callback()` because the 639 // order matters. 640 func (c *clientImpl) run() { 641 for { 642 select { 643 case t := <-c.updateCh.Get(): 644 c.updateCh.Load() 645 if c.done.HasFired() { 646 return 647 } 648 c.callCallback(t.(*watcherInfoWithUpdate)) 649 case <-c.done.Done(): 650 return 651 } 652 } 653 } 654 655 // Close closes the gRPC connection to the management server. 656 func (c *clientImpl) Close() { 657 if c.done.HasFired() { 658 return 659 } 660 c.done.Fire() 661 // TODO: Should we invoke the registered callbacks here with an error that 662 // the client is closed? 663 c.apiClient.Close() 664 c.cc.Close() 665 c.logger.Infof("Shutdown") 666 } 667 668 // ResourceType identifies resources in a transport protocol agnostic way. These 669 // will be used in transport version agnostic code, while the versioned API 670 // clients will map these to appropriate version URLs. 671 type ResourceType int 672 673 // Version agnostic resource type constants. 674 const ( 675 UnknownResource ResourceType = iota 676 ListenerResource 677 HTTPConnManagerResource 678 RouteConfigResource 679 ClusterResource 680 EndpointsResource 681 ) 682 683 func (r ResourceType) String() string { 684 switch r { 685 case ListenerResource: 686 return "ListenerResource" 687 case HTTPConnManagerResource: 688 return "HTTPConnManagerResource" 689 case RouteConfigResource: 690 return "RouteConfigResource" 691 case ClusterResource: 692 return "ClusterResource" 693 case EndpointsResource: 694 return "EndpointsResource" 695 default: 696 return "UnknownResource" 697 } 698 } 699 700 // IsListenerResource returns true if the provider URL corresponds to an xDS 701 // Listener resource. 702 func IsListenerResource(url string) bool { 703 return url == version.V2ListenerURL || url == version.V3ListenerURL 704 } 705 706 // IsHTTPConnManagerResource returns true if the provider URL corresponds to an xDS 707 // HTTPConnManager resource. 708 func IsHTTPConnManagerResource(url string) bool { 709 return url == version.V2HTTPConnManagerURL || url == version.V3HTTPConnManagerURL 710 } 711 712 // IsRouteConfigResource returns true if the provider URL corresponds to an xDS 713 // RouteConfig resource. 714 func IsRouteConfigResource(url string) bool { 715 return url == version.V2RouteConfigURL || url == version.V3RouteConfigURL 716 } 717 718 // IsClusterResource returns true if the provider URL corresponds to an xDS 719 // Cluster resource. 720 func IsClusterResource(url string) bool { 721 return url == version.V2ClusterURL || url == version.V3ClusterURL 722 } 723 724 // IsEndpointsResource returns true if the provider URL corresponds to an xDS 725 // Endpoints resource. 726 func IsEndpointsResource(url string) bool { 727 return url == version.V2EndpointsURL || url == version.V3EndpointsURL 728 }