Repository: grpc/grpc-go
File: xds/internal/clients/grpctransport/grpc_transport.go (Go)

Code before:

// ServerConfigExtension holds the settings for connecting to an xDS management server
// using gRPC.
type ServerConfigExtension struct {
	// Credentials is the credential bundle containing the gRPC credentials for
	// connecting to the xDS management server.
	Credentials credentials.Bundle
}

// Builder provides a way to build a gRPC-based transport to an xDS management
// server.
type Builder struct{}

func init() {
	encoding.RegisterCodec(&byteCodec{})
}

// Build creates a new gRPC-based transport to an xDS management server using
// the provided clients.ServerConfig. This involves creating a
// grpc.ClientConn to the server using the provided credentials and server URI,
// and byteCodec which is byte-based implementation of encoding.Codec to send
// and receive messages as bytes on the stream.
//
// If any of ServerURI or Extensions of `sc` are not present, Build() will return
// an error.
func (b *Builder) Build(sc clients.ServerConfig) (clients.Transport, error) {
	if sc.ServerURI == "" {
		return nil, fmt.Errorf("xds: ServerConfig's ServerURI field cannot be empty")
	}
	if sc.Extensions == nil {
		return nil, fmt.Errorf("xds: ServerConfig's Extensions field cannot be nil for gRPC transport")
	}
	gtsce, ok := sc.Extensions.(ServerConfigExtension)
	if !ok {
		return nil, fmt.Errorf("xds: ServerConfig's Extensions field cannot be anything other than grpctransport.ServerConfigExtension for gRPC transport")
	}
	if gtsce.Credentials == nil {
		return nil, fmt.Errorf("xsd: ServerConfigExtensions's Credentials field cannot be nil for gRPC transport")
	}

	// TODO: Incorporate reference count map for existing transports and
	// deduplicate transports based on server URI and credentials so that
	// transport channel to same server can be shared between xDS and LRS
	// client.

	// Dial the xDS management server with the provided credentials, server URI,
	// and a static keepalive configuration that is common across gRPC language
	// implementations.
	kpCfg := grpc.WithKeepaliveParams(keepalive.ClientParameters{
		Time:    5 * time.Minute,
		Timeout: 20 * time.Second,

Review comment (suggestion):
```suggestion
	if !ok {
		return nil, fmt.Errorf("ServerConfig Extensions field is %T, but must be %T", sc.Extensions, ServerConfigExtension{})
	}
```

Code after:
// ServerConfigExtension holds settings for connecting to a gRPC server,
// such as an xDS management or an LRS server.
type ServerConfigExtension struct {
	// Credentials will be used for all gRPC transports. If it is unset,
	// transport creation will fail.
	Credentials credentials.Bundle
}

// Builder creates gRPC-based Transports. It must be paired with ServerConfigs
// that contain an Extension field of type ServerConfigExtension.
type Builder struct{}

// Build returns a gRPC-based clients.Transport.
//
// The Extension field of the ServerConfig must be a ServerConfigExtension.
func (b *Builder) Build(sc clients.ServerConfig) (clients.Transport, error) {
	if sc.ServerURI == "" {
		return nil, fmt.Errorf("grpctransport: ServerURI is not set in ServerConfig")
	}
	if sc.Extensions == nil {
		return nil, fmt.Errorf("grpctransport: Extensions is not set in ServerConfig")
	}
	sce, ok := sc.Extensions.(ServerConfigExtension)
	if !ok {
		return nil, fmt.Errorf("grpctransport: Extensions field is %T, but must be %T in ServerConfig", sc.Extensions, ServerConfigExtension{})
	}
	if sce.Credentials == nil {
		return nil, fmt.Errorf("grptransport: Credentials field is not set in ServerConfigExtension")
	}

	// TODO: Incorporate reference count map for existing transports and
	// deduplicate transports based on the provided ServerConfig so that
	// transport channel to same server can be shared between xDS and LRS
	// client.

	// Create a new gRPC client/channel for the server with the provided
	// credentials, server URI, and a byte codec to send and receive messages.
	// Also set a static keepalive configuration that is common across gRPC
	// language implementations.
	kpCfg := grpc.WithKeepaliveParams(keepalive.ClientParameters{
		Time:    5 * time.Minute,
		Timeout: 20 * time.Second,
	})
	cc, err := grpc.NewClient(sc.ServerURI, kpCfg, grpc.WithCredentialsBundle(sce.Credentials), grpc.WithDefaultCallOptions(grpc.ForceCodec(&byteCodec{})))
	if err != nil {
		return nil, fmt.Errorf("grpctransport: failed to create transport to server %q: %v", sc.ServerURI, err)
	}

	return &grpcTransport{cc: cc}, nil
}