Skip to content

Commit

Permalink
xds/federation: support populating resource template in xds-resolver (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
menghanl committed Nov 8, 2021
1 parent 79e9c95 commit c53203c
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 78 deletions.
45 changes: 40 additions & 5 deletions xds/internal/resolver/xds_resolver.go
Expand Up @@ -22,6 +22,7 @@ package resolver
import (
"errors"
"fmt"
"strings"

"google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/grpclog"
Expand All @@ -30,6 +31,7 @@ import (
iresolver "google.golang.org/grpc/internal/resolver"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/xds/internal/xdsclient"
"google.golang.org/grpc/xds/internal/xdsclient/bootstrap"
)

const xdsScheme = "xds"
Expand Down Expand Up @@ -60,15 +62,22 @@ type xdsResolverBuilder struct {
//
// The xds bootstrap process is performed (and a new xds client is built) every
// time an xds resolver is built.
func (b *xdsResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
func (b *xdsResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (_ resolver.Resolver, retErr error) {
r := &xdsResolver{
target: t,
cc: cc,
closed: grpcsync.NewEvent(),
updateCh: make(chan suWithError, 1),
activeClusters: make(map[string]*clusterInfo),
}
r.logger = prefixLogger((r))
defer func() {
if retErr != nil {
if r.client != nil {
r.client.Close()
}
}
}()
r.logger = prefixLogger(r)
r.logger.Infof("Creating resolver for target: %+v", t)

newXDSClient := newXDSClient
Expand All @@ -81,6 +90,10 @@ func (b *xdsResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, op
return nil, fmt.Errorf("xds: failed to create xds-client: %v", err)
}
r.client = client
bootstrapConfig := client.BootstrapConfig()
if bootstrapConfig == nil {
return nil, errors.New("bootstrap configuration is empty")
}

// If xds credentials were specified by the user, but bootstrap configs do
// not contain any certificate provider configuration, it is better to fail
Expand All @@ -94,14 +107,36 @@ func (b *xdsResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, op
creds = opts.CredsBundle.TransportCredentials()
}
if xc, ok := creds.(interface{ UsesXDS() bool }); ok && xc.UsesXDS() {
bc := client.BootstrapConfig()
if len(bc.CertProviderConfigs) == 0 {
if len(bootstrapConfig.CertProviderConfigs) == 0 {
return nil, errors.New("xds: xdsCreds specified but certificate_providers config missing in bootstrap file")
}
}

// Find the client listener template to use from the bootstrap config:
// - If authority is not set in the target, use the top level template
// - If authority is set, use the template from the authority map.
template := bootstrapConfig.ClientDefaultListenerResourceNameTemplate
if authority := r.target.URL.Host; authority != "" {
a := bootstrapConfig.Authorities[authority]
if a == nil {
return nil, fmt.Errorf("xds: authority %q is not found in the bootstrap file", authority)
}
if a.ClientListenerResourceNameTemplate != "" {
// This check will never be false, because
// ClientListenerResourceNameTemplate is required to start with
// xdstp://, and has a default value (not an empty string) if unset.
template = a.ClientListenerResourceNameTemplate
}
}
endpoint := r.target.URL.Path
if endpoint == "" {
endpoint = r.target.URL.Opaque
}
endpoint = strings.TrimPrefix(endpoint, "/")
resourceName := bootstrap.PopulateResourceTemplate(template, endpoint)

// Register a watch on the xdsClient for the user's dial target.
cancelWatch := watchService(r.client, r.target.Endpoint, r.handleServiceUpdate, r.logger)
cancelWatch := watchService(r.client, resourceName, r.handleServiceUpdate, r.logger)
r.logger.Infof("Watch started on resource name %v with xds-client %p", r.target.Endpoint, r.client)
r.cancelWatch = func() {
cancelWatch()
Expand Down

0 comments on commit c53203c

Please sign in to comment.