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 }