github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/discovery/discovery.go (about)

     1  package discovery
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  	"strconv"
     8  
     9  	"github.com/ydb-platform/ydb-go-genproto/Ydb_Discovery_V1"
    10  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
    11  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Discovery"
    12  	"google.golang.org/grpc"
    13  
    14  	"github.com/ydb-platform/ydb-go-sdk/v3/discovery"
    15  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/discovery/config"
    16  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/endpoint"
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/stack"
    18  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
    19  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
    20  )
    21  
    22  //go:generate mockgen -destination grpc_client_mock_test.go --typed -package discovery -write_package_comment=false github.com/ydb-platform/ydb-go-genproto/Ydb_Discovery_V1 DiscoveryServiceClient
    23  
    24  func New(ctx context.Context, cc grpc.ClientConnInterface, config *config.Config) *Client {
    25  	return &Client{
    26  		config: config,
    27  		cc:     cc,
    28  		client: Ydb_Discovery_V1.NewDiscoveryServiceClient(cc),
    29  	}
    30  }
    31  
    32  var _ discovery.Client = &Client{}
    33  
    34  type Client struct {
    35  	config *config.Config
    36  	cc     grpc.ClientConnInterface
    37  	client Ydb_Discovery_V1.DiscoveryServiceClient
    38  }
    39  
    40  func discover(
    41  	ctx context.Context,
    42  	client Ydb_Discovery_V1.DiscoveryServiceClient,
    43  	config *config.Config,
    44  ) (endpoints []endpoint.Endpoint, location string, err error) {
    45  	var (
    46  		request = Ydb_Discovery.ListEndpointsRequest{
    47  			Database: config.Database(),
    48  		}
    49  		response *Ydb_Discovery.ListEndpointsResponse
    50  		result   Ydb_Discovery.ListEndpointsResult
    51  	)
    52  
    53  	response, err = client.ListEndpoints(ctx, &request)
    54  	if err != nil {
    55  		return nil, location, xerrors.WithStackTrace(err)
    56  	}
    57  
    58  	if response.GetOperation().GetStatus() != Ydb.StatusIds_SUCCESS {
    59  		return nil, location, xerrors.WithStackTrace(
    60  			xerrors.FromOperation(response.GetOperation()),
    61  		)
    62  	}
    63  
    64  	err = response.GetOperation().GetResult().UnmarshalTo(&result)
    65  	if err != nil {
    66  		return nil, location, xerrors.WithStackTrace(err)
    67  	}
    68  
    69  	location = result.GetSelfLocation()
    70  	endpoints = make([]endpoint.Endpoint, 0, len(result.GetEndpoints()))
    71  	for _, e := range result.GetEndpoints() {
    72  		if e.GetSsl() == config.Secure() {
    73  			endpoints = append(endpoints, endpoint.New(
    74  				net.JoinHostPort(
    75  					config.MutateAddress(e.GetAddress()),
    76  					strconv.Itoa(int(e.GetPort())),
    77  				),
    78  				endpoint.WithLocation(e.GetLocation()),
    79  				endpoint.WithID(e.GetNodeId()),
    80  				endpoint.WithLoadFactor(e.GetLoadFactor()),
    81  				endpoint.WithLocalDC(e.GetLocation() == location),
    82  				endpoint.WithServices(e.GetService()),
    83  				endpoint.WithLastUpdated(config.Clock().Now()),
    84  				endpoint.WithIPV4(e.GetIpV4()),
    85  				endpoint.WithIPV6(e.GetIpV6()),
    86  				endpoint.WithSslTargetNameOverride(e.GetSslTargetNameOverride()),
    87  			))
    88  		}
    89  	}
    90  
    91  	return endpoints, result.GetSelfLocation(), nil
    92  }
    93  
    94  // Discover cluster endpoints
    95  func (c *Client) Discover(ctx context.Context) (endpoints []endpoint.Endpoint, finalErr error) {
    96  	var (
    97  		onDone = trace.DiscoveryOnDiscover(
    98  			c.config.Trace(), &ctx,
    99  			stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/discovery.(*Client).Discover"),
   100  			c.config.Endpoint(), c.config.Database(),
   101  		)
   102  		location string
   103  	)
   104  	defer func() {
   105  		nodes := make([]trace.EndpointInfo, 0, len(endpoints))
   106  		for _, e := range endpoints {
   107  			nodes = append(nodes, e.Copy())
   108  		}
   109  		onDone(location, nodes, finalErr)
   110  	}()
   111  
   112  	ctx, err := c.config.Meta().Context(ctx)
   113  	if err != nil {
   114  		return nil, xerrors.WithStackTrace(err)
   115  	}
   116  
   117  	endpoints, location, err = discover(ctx, c.client, c.config)
   118  	if err != nil {
   119  		return nil, xerrors.WithStackTrace(err)
   120  	}
   121  
   122  	return endpoints, nil
   123  }
   124  
   125  func (c *Client) WhoAmI(ctx context.Context) (whoAmI *discovery.WhoAmI, err error) {
   126  	var (
   127  		onDone = trace.DiscoveryOnWhoAmI(c.config.Trace(), &ctx,
   128  			stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/discovery.(*Client).WhoAmI"),
   129  		)
   130  		request            = Ydb_Discovery.WhoAmIRequest{}
   131  		response           *Ydb_Discovery.WhoAmIResponse
   132  		whoAmIResultResult Ydb_Discovery.WhoAmIResult
   133  	)
   134  	defer func() {
   135  		if err != nil {
   136  			onDone("", nil, err)
   137  		} else {
   138  			onDone(whoAmI.User, whoAmI.Groups, err)
   139  		}
   140  	}()
   141  
   142  	ctx, err = c.config.Meta().Context(ctx)
   143  	if err != nil {
   144  		return nil, xerrors.WithStackTrace(err)
   145  	}
   146  
   147  	response, err = c.client.WhoAmI(ctx, &request)
   148  	if err != nil {
   149  		return nil, xerrors.WithStackTrace(err)
   150  	}
   151  
   152  	if response.GetOperation().GetStatus() != Ydb.StatusIds_SUCCESS {
   153  		return nil, xerrors.WithStackTrace(
   154  			xerrors.FromOperation(
   155  				response.GetOperation(),
   156  			),
   157  		)
   158  	}
   159  
   160  	result := response.GetOperation().GetResult()
   161  	if result == nil {
   162  		return &discovery.WhoAmI{}, nil
   163  	}
   164  
   165  	err = response.GetOperation().GetResult().UnmarshalTo(&whoAmIResultResult)
   166  	if err != nil {
   167  		return nil, xerrors.WithStackTrace(err)
   168  	}
   169  
   170  	return &discovery.WhoAmI{
   171  		User:   whoAmIResultResult.GetUser(),
   172  		Groups: whoAmIResultResult.GetGroups(),
   173  	}, nil
   174  }
   175  
   176  func (c *Client) Close(context.Context) error {
   177  	if cc, has := c.cc.(io.Closer); has {
   178  		return cc.Close()
   179  	}
   180  
   181  	return nil
   182  }