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 client implements a full fledged gRPC client for the xDS API used by 20// the xds resolver and balancer implementations. 21package client 22 23import ( 24 "context" 25 "errors" 26 "fmt" 27 "net" 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" 37 "google.golang.org/grpc/xds/internal/client/load" 38 "google.golang.org/grpc/xds/internal/httpfilter" 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/client/bootstrap" 48 "google.golang.org/grpc/xds/internal/version" 49) 50 51var ( 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. 61func 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. 67func 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. 75type 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. 92type 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. 110type 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. 128type 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. 134type 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} 145 146// ServiceStatus is the status of the update. 147type ServiceStatus int 148 149const ( 150 // ServiceStatusUnknown is the default state, before a watch is started for 151 // the resource. 152 ServiceStatusUnknown ServiceStatus = iota 153 // ServiceStatusRequested is when the watch is started, but before and 154 // response is received. 155 ServiceStatusRequested 156 // ServiceStatusNotExist is when the resource doesn't exist in 157 // state-of-the-world responses (e.g. LDS and CDS), which means the resource 158 // is removed by the management server. 159 ServiceStatusNotExist // Resource is removed in the server, in LDS/CDS. 160 // ServiceStatusACKed is when the resource is ACKed. 161 ServiceStatusACKed 162 // ServiceStatusNACKed is when the resource is NACKed. 163 ServiceStatusNACKed 164) 165 166// UpdateErrorMetadata is part of UpdateMetadata. It contains the error state 167// when a response is NACKed. 168type UpdateErrorMetadata struct { 169 // Version is the version of the NACKed response. 170 Version string 171 // Err contains why the response was NACKed. 172 Err error 173 // Timestamp is when the NACKed response was received. 174 Timestamp time.Time 175} 176 177// UpdateMetadata contains the metadata for each update, including timestamp, 178// raw message, and so on. 179type UpdateMetadata struct { 180 // Status is the status of this resource, e.g. ACKed, NACKed, or 181 // Not_exist(removed). 182 Status ServiceStatus 183 // Version is the version of the xds response. Note that this is the version 184 // of the resource in use (previous ACKed). If a response is NACKed, the 185 // NACKed version is in ErrState. 186 Version string 187 // Timestamp is when the response is received. 188 Timestamp time.Time 189 // ErrState is set when the update is NACKed. 190 ErrState *UpdateErrorMetadata 191} 192 193// ListenerUpdate contains information received in an LDS response, which is of 194// interest to the registered LDS watcher. 195type ListenerUpdate struct { 196 // RouteConfigName is the route configuration name corresponding to the 197 // target which is being watched through LDS. 198 RouteConfigName string 199 // MaxStreamDuration contains the HTTP connection manager's 200 // common_http_protocol_options.max_stream_duration field, or zero if 201 // unset. 202 MaxStreamDuration time.Duration 203 // HTTPFilters is a list of HTTP filters (name, config) from the LDS 204 // response. 205 HTTPFilters []HTTPFilter 206 // InboundListenerCfg contains inbound listener configuration. 207 InboundListenerCfg *InboundListenerConfig 208 209 // Raw is the resource from the xds response. 210 Raw *anypb.Any 211} 212 213// HTTPFilter represents one HTTP filter from an LDS response's HTTP connection 214// manager field. 215type HTTPFilter struct { 216 // Name is an arbitrary name of the filter. Used for applying override 217 // settings in virtual host / route / weighted cluster configuration (not 218 // yet supported). 219 Name string 220 // Filter is the HTTP filter found in the registry for the config type. 221 Filter httpfilter.Filter 222 // Config contains the filter's configuration 223 Config httpfilter.FilterConfig 224} 225 226// InboundListenerConfig contains information about the inbound listener, i.e 227// the server-side listener. 228type InboundListenerConfig struct { 229 // Address is the local address on which the inbound listener is expected to 230 // accept incoming connections. 231 Address string 232 // Port is the local port on which the inbound listener is expected to 233 // accept incoming connections. 234 Port string 235 // FilterChains is the list of filter chains associated with this listener. 236 FilterChains []*FilterChain 237 // DefaultFilterChain is the filter chain to be used when none of the above 238 // filter chains matches an incoming connection. 239 DefaultFilterChain *FilterChain 240} 241 242// FilterChain wraps a set of match criteria and associated security 243// configuration. 244// 245// The actual set filters associated with this filter chain are not captured 246// here, since we do not support these filters on the server yet. 247type FilterChain struct { 248 // Match contains the criteria to use when matching a connection to this 249 // filter chain. 250 Match *FilterChainMatch 251 // SecurityCfg contains transport socket security configuration. 252 SecurityCfg *SecurityConfig 253} 254 255// SourceType specifies the connection source IP match type. 256type SourceType int 257 258const ( 259 // SourceTypeAny matches connection attempts from any source. 260 SourceTypeAny SourceType = iota 261 // SourceTypeSameOrLoopback matches connection attempts from the same host. 262 SourceTypeSameOrLoopback 263 // SourceTypeExternal matches connection attempts from a different host. 264 SourceTypeExternal 265) 266 267// FilterChainMatch specifies the match criteria for selecting a specific filter 268// chain of a listener, for an incoming connection. 269// 270// The xDS FilterChainMatch proto specifies 8 match criteria. But we only have a 271// subset of those fields here because we explicitly ignore filter chains whose 272// match criteria specifies values for fields like destination_port, 273// server_names, application_protocols, transport_protocol. 274type FilterChainMatch struct { 275 // DestPrefixRanges specifies a set of IP addresses and prefix lengths to 276 // match the destination address of the incoming connection when the 277 // listener is bound to 0.0.0.0/[::]. If this field is empty, the 278 // destination address is ignored. 279 DestPrefixRanges []net.IP 280 // SourceType specifies the connection source IP match type. Can be any, 281 // local or external network. 282 SourceType SourceType 283 // SourcePrefixRanges specifies a set of IP addresses and prefix lengths to 284 // match the source address of the incoming connection. If this field is 285 // empty, the source address is ignored. 286 SourcePrefixRanges []net.IP 287 // SourcePorts specifies a set of ports to match the source port of the 288 // incoming connection. If this field is empty, the source port is ignored. 289 SourcePorts []uint32 290} 291 292// RouteConfigUpdate contains information received in an RDS response, which is 293// of interest to the registered RDS watcher. 294type RouteConfigUpdate struct { 295 VirtualHosts []*VirtualHost 296 297 // Raw is the resource from the xds response. 298 Raw *anypb.Any 299} 300 301// VirtualHost contains the routes for a list of Domains. 302// 303// Note that the domains in this slice can be a wildcard, not an exact string. 304// The consumer of this struct needs to find the best match for its hostname. 305type VirtualHost struct { 306 Domains []string 307 // Routes contains a list of routes, each containing matchers and 308 // corresponding action. 309 Routes []*Route 310 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 311 // the virtual host which may be present. An individual filter's override 312 // may be unused if the matching Route contains an override for that 313 // filter. 314 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 315} 316 317// Route is both a specification of how to match a request as well as an 318// indication of the action to take upon match. 319type Route struct { 320 Path, Prefix, Regex *string 321 // Indicates if prefix/path matching should be case insensitive. The default 322 // is false (case sensitive). 323 CaseInsensitive bool 324 Headers []*HeaderMatcher 325 Fraction *uint32 326 327 // If the matchers above indicate a match, the below configuration is used. 328 WeightedClusters map[string]WeightedCluster 329 // If MaxStreamDuration is nil, it indicates neither of the route action's 330 // max_stream_duration fields (grpc_timeout_header_max nor 331 // max_stream_duration) were set. In this case, the ListenerUpdate's 332 // MaxStreamDuration field should be used. If MaxStreamDuration is set to 333 // an explicit zero duration, the application's deadline should be used. 334 MaxStreamDuration *time.Duration 335 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 336 // the route which may be present. An individual filter's override may be 337 // unused if the matching WeightedCluster contains an override for that 338 // filter. 339 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 340} 341 342// WeightedCluster contains settings for an xds RouteAction.WeightedCluster. 343type WeightedCluster struct { 344 // Weight is the relative weight of the cluster. It will never be zero. 345 Weight uint32 346 // HTTPFilterConfigOverride contains any HTTP filter config overrides for 347 // the weighted cluster which may be present. 348 HTTPFilterConfigOverride map[string]httpfilter.FilterConfig 349} 350 351// HeaderMatcher represents header matchers. 352type HeaderMatcher struct { 353 Name string `json:"name"` 354 InvertMatch *bool `json:"invertMatch,omitempty"` 355 ExactMatch *string `json:"exactMatch,omitempty"` 356 RegexMatch *string `json:"regexMatch,omitempty"` 357 PrefixMatch *string `json:"prefixMatch,omitempty"` 358 SuffixMatch *string `json:"suffixMatch,omitempty"` 359 RangeMatch *Int64Range `json:"rangeMatch,omitempty"` 360 PresentMatch *bool `json:"presentMatch,omitempty"` 361} 362 363// Int64Range is a range for header range match. 364type Int64Range struct { 365 Start int64 `json:"start"` 366 End int64 `json:"end"` 367} 368 369// SecurityConfig contains the security configuration received as part of the 370// Cluster resource on the client-side, and as part of the Listener resource on 371// the server-side. 372type SecurityConfig struct { 373 // RootInstanceName identifies the certProvider plugin to be used to fetch 374 // root certificates. This instance name will be resolved to the plugin name 375 // and its associated configuration from the certificate_providers field of 376 // the bootstrap file. 377 RootInstanceName string 378 // RootCertName is the certificate name to be passed to the plugin (looked 379 // up from the bootstrap file) while fetching root certificates. 380 RootCertName string 381 // IdentityInstanceName identifies the certProvider plugin to be used to 382 // fetch identity certificates. This instance name will be resolved to the 383 // plugin name and its associated configuration from the 384 // certificate_providers field of the bootstrap file. 385 IdentityInstanceName string 386 // IdentityCertName is the certificate name to be passed to the plugin 387 // (looked up from the bootstrap file) while fetching identity certificates. 388 IdentityCertName string 389 // SubjectAltNameMatchers is an optional list of match criteria for SANs 390 // specified on the peer certificate. Used only on the client-side. 391 // 392 // Some intricacies: 393 // - If this field is empty, then any peer certificate is accepted. 394 // - If the peer certificate contains a wildcard DNS SAN, and an `exact` 395 // matcher is configured, a wildcard DNS match is performed instead of a 396 // regular string comparison. 397 SubjectAltNameMatchers []xds.StringMatcher 398 // RequireClientCert indicates if the server handshake process expects the 399 // client to present a certificate. Set to true when performing mTLS. Used 400 // only on the server-side. 401 RequireClientCert bool 402} 403 404// ClusterUpdate contains information from a received CDS response, which is of 405// interest to the registered CDS watcher. 406type ClusterUpdate struct { 407 // ServiceName is the service name corresponding to the clusterName which 408 // is being watched for through CDS. 409 ServiceName string 410 // EnableLRS indicates whether or not load should be reported through LRS. 411 EnableLRS bool 412 // SecurityCfg contains security configuration sent by the control plane. 413 SecurityCfg *SecurityConfig 414 // MaxRequests for circuit breaking, if any (otherwise nil). 415 MaxRequests *uint32 416 417 // Raw is the resource from the xds response. 418 Raw *anypb.Any 419} 420 421// OverloadDropConfig contains the config to drop overloads. 422type OverloadDropConfig struct { 423 Category string 424 Numerator uint32 425 Denominator uint32 426} 427 428// EndpointHealthStatus represents the health status of an endpoint. 429type EndpointHealthStatus int32 430 431const ( 432 // EndpointHealthStatusUnknown represents HealthStatus UNKNOWN. 433 EndpointHealthStatusUnknown EndpointHealthStatus = iota 434 // EndpointHealthStatusHealthy represents HealthStatus HEALTHY. 435 EndpointHealthStatusHealthy 436 // EndpointHealthStatusUnhealthy represents HealthStatus UNHEALTHY. 437 EndpointHealthStatusUnhealthy 438 // EndpointHealthStatusDraining represents HealthStatus DRAINING. 439 EndpointHealthStatusDraining 440 // EndpointHealthStatusTimeout represents HealthStatus TIMEOUT. 441 EndpointHealthStatusTimeout 442 // EndpointHealthStatusDegraded represents HealthStatus DEGRADED. 443 EndpointHealthStatusDegraded 444) 445 446// Endpoint contains information of an endpoint. 447type Endpoint struct { 448 Address string 449 HealthStatus EndpointHealthStatus 450 Weight uint32 451} 452 453// Locality contains information of a locality. 454type Locality struct { 455 Endpoints []Endpoint 456 ID internal.LocalityID 457 Priority uint32 458 Weight uint32 459} 460 461// EndpointsUpdate contains an EDS update. 462type EndpointsUpdate struct { 463 Drops []OverloadDropConfig 464 Localities []Locality 465 466 // Raw is the resource from the xds response. 467 Raw *anypb.Any 468} 469 470// Function to be overridden in tests. 471var newAPIClient = func(apiVersion version.TransportAPI, cc *grpc.ClientConn, opts BuildOptions) (APIClient, error) { 472 cb := getAPIClientBuilder(apiVersion) 473 if cb == nil { 474 return nil, fmt.Errorf("no client builder for xDS API version: %v", apiVersion) 475 } 476 return cb.Build(cc, opts) 477} 478 479// clientImpl is the real implementation of the xds client. The exported Client 480// is a wrapper of this struct with a ref count. 481// 482// Implements UpdateHandler interface. 483// TODO(easwars): Make a wrapper struct which implements this interface in the 484// style of ccBalancerWrapper so that the Client type does not implement these 485// exported methods. 486type clientImpl struct { 487 done *grpcsync.Event 488 config *bootstrap.Config 489 cc *grpc.ClientConn // Connection to the management server. 490 apiClient APIClient 491 watchExpiryTimeout time.Duration 492 493 logger *grpclog.PrefixLogger 494 495 updateCh *buffer.Unbounded // chan *watcherInfoWithUpdate 496 // All the following maps are to keep the updates/metadata in a cache. 497 // TODO: move them to a separate struct/package, to cleanup the xds_client. 498 // And CSDS handler can be implemented directly by the cache. 499 mu sync.Mutex 500 ldsWatchers map[string]map[*watchInfo]bool 501 ldsVersion string // Only used in CSDS. 502 ldsCache map[string]ListenerUpdate 503 ldsMD map[string]UpdateMetadata 504 rdsWatchers map[string]map[*watchInfo]bool 505 rdsVersion string // Only used in CSDS. 506 rdsCache map[string]RouteConfigUpdate 507 rdsMD map[string]UpdateMetadata 508 cdsWatchers map[string]map[*watchInfo]bool 509 cdsVersion string // Only used in CSDS. 510 cdsCache map[string]ClusterUpdate 511 cdsMD map[string]UpdateMetadata 512 edsWatchers map[string]map[*watchInfo]bool 513 edsVersion string // Only used in CSDS. 514 edsCache map[string]EndpointsUpdate 515 edsMD map[string]UpdateMetadata 516 517 // Changes to map lrsClients and the lrsClient inside the map need to be 518 // protected by lrsMu. 519 lrsMu sync.Mutex 520 lrsClients map[string]*lrsClient 521} 522 523// newWithConfig returns a new xdsClient with the given config. 524func newWithConfig(config *bootstrap.Config, watchExpiryTimeout time.Duration) (*clientImpl, error) { 525 switch { 526 case config.BalancerName == "": 527 return nil, errors.New("xds: no xds_server name provided in options") 528 case config.Creds == nil: 529 return nil, errors.New("xds: no credentials provided in options") 530 case config.NodeProto == nil: 531 return nil, errors.New("xds: no node_proto provided in options") 532 } 533 534 switch config.TransportAPI { 535 case version.TransportV2: 536 if _, ok := config.NodeProto.(*v2corepb.Node); !ok { 537 return nil, fmt.Errorf("xds: Node proto type (%T) does not match API version: %v", config.NodeProto, config.TransportAPI) 538 } 539 case version.TransportV3: 540 if _, ok := config.NodeProto.(*v3corepb.Node); !ok { 541 return nil, fmt.Errorf("xds: Node proto type (%T) does not match API version: %v", config.NodeProto, config.TransportAPI) 542 } 543 } 544 545 dopts := []grpc.DialOption{ 546 config.Creds, 547 grpc.WithKeepaliveParams(keepalive.ClientParameters{ 548 Time: 5 * time.Minute, 549 Timeout: 20 * time.Second, 550 }), 551 } 552 553 c := &clientImpl{ 554 done: grpcsync.NewEvent(), 555 config: config, 556 watchExpiryTimeout: watchExpiryTimeout, 557 558 updateCh: buffer.NewUnbounded(), 559 ldsWatchers: make(map[string]map[*watchInfo]bool), 560 ldsCache: make(map[string]ListenerUpdate), 561 ldsMD: make(map[string]UpdateMetadata), 562 rdsWatchers: make(map[string]map[*watchInfo]bool), 563 rdsCache: make(map[string]RouteConfigUpdate), 564 rdsMD: make(map[string]UpdateMetadata), 565 cdsWatchers: make(map[string]map[*watchInfo]bool), 566 cdsCache: make(map[string]ClusterUpdate), 567 cdsMD: make(map[string]UpdateMetadata), 568 edsWatchers: make(map[string]map[*watchInfo]bool), 569 edsCache: make(map[string]EndpointsUpdate), 570 edsMD: make(map[string]UpdateMetadata), 571 lrsClients: make(map[string]*lrsClient), 572 } 573 574 cc, err := grpc.Dial(config.BalancerName, dopts...) 575 if err != nil { 576 // An error from a non-blocking dial indicates something serious. 577 return nil, fmt.Errorf("xds: failed to dial balancer {%s}: %v", config.BalancerName, err) 578 } 579 c.cc = cc 580 c.logger = prefixLogger((c)) 581 c.logger.Infof("Created ClientConn to xDS management server: %s", config.BalancerName) 582 583 apiClient, err := newAPIClient(config.TransportAPI, cc, BuildOptions{ 584 Parent: c, 585 NodeProto: config.NodeProto, 586 Backoff: backoff.DefaultExponential.Backoff, 587 Logger: c.logger, 588 }) 589 if err != nil { 590 return nil, err 591 } 592 c.apiClient = apiClient 593 c.logger.Infof("Created") 594 go c.run() 595 return c, nil 596} 597 598// BootstrapConfig returns the configuration read from the bootstrap file. 599// Callers must treat the return value as read-only. 600func (c *Client) BootstrapConfig() *bootstrap.Config { 601 return c.config 602} 603 604// run is a goroutine for all the callbacks. 605// 606// Callback can be called in watch(), if an item is found in cache. Without this 607// goroutine, the callback will be called inline, which might cause a deadlock 608// in user's code. Callbacks also cannot be simple `go callback()` because the 609// order matters. 610func (c *clientImpl) run() { 611 for { 612 select { 613 case t := <-c.updateCh.Get(): 614 c.updateCh.Load() 615 if c.done.HasFired() { 616 return 617 } 618 c.callCallback(t.(*watcherInfoWithUpdate)) 619 case <-c.done.Done(): 620 return 621 } 622 } 623} 624 625// Close closes the gRPC connection to the management server. 626func (c *clientImpl) Close() { 627 if c.done.HasFired() { 628 return 629 } 630 c.done.Fire() 631 // TODO: Should we invoke the registered callbacks here with an error that 632 // the client is closed? 633 c.apiClient.Close() 634 c.cc.Close() 635 c.logger.Infof("Shutdown") 636} 637 638// ResourceType identifies resources in a transport protocol agnostic way. These 639// will be used in transport version agnostic code, while the versioned API 640// clients will map these to appropriate version URLs. 641type ResourceType int 642 643// Version agnostic resource type constants. 644const ( 645 UnknownResource ResourceType = iota 646 ListenerResource 647 HTTPConnManagerResource 648 RouteConfigResource 649 ClusterResource 650 EndpointsResource 651) 652 653func (r ResourceType) String() string { 654 switch r { 655 case ListenerResource: 656 return "ListenerResource" 657 case HTTPConnManagerResource: 658 return "HTTPConnManagerResource" 659 case RouteConfigResource: 660 return "RouteConfigResource" 661 case ClusterResource: 662 return "ClusterResource" 663 case EndpointsResource: 664 return "EndpointsResource" 665 default: 666 return "UnknownResource" 667 } 668} 669 670// IsListenerResource returns true if the provider URL corresponds to an xDS 671// Listener resource. 672func IsListenerResource(url string) bool { 673 return url == version.V2ListenerURL || url == version.V3ListenerURL 674} 675 676// IsHTTPConnManagerResource returns true if the provider URL corresponds to an xDS 677// HTTPConnManager resource. 678func IsHTTPConnManagerResource(url string) bool { 679 return url == version.V2HTTPConnManagerURL || url == version.V3HTTPConnManagerURL 680} 681 682// IsRouteConfigResource returns true if the provider URL corresponds to an xDS 683// RouteConfig resource. 684func IsRouteConfigResource(url string) bool { 685 return url == version.V2RouteConfigURL || url == version.V3RouteConfigURL 686} 687 688// IsClusterResource returns true if the provider URL corresponds to an xDS 689// Cluster resource. 690func IsClusterResource(url string) bool { 691 return url == version.V2ClusterURL || url == version.V3ClusterURL 692} 693 694// IsEndpointsResource returns true if the provider URL corresponds to an xDS 695// Endpoints resource. 696func IsEndpointsResource(url string) bool { 697 return url == version.V2EndpointsURL || url == version.V3EndpointsURL 698} 699