diff --git a/pkg/client/netmap.go b/pkg/client/netmap.go new file mode 100644 index 0000000..c400332 --- /dev/null +++ b/pkg/client/netmap.go @@ -0,0 +1,93 @@ +package client + +import ( + "context" + + "github.com/nspcc-dev/neofs-api-go/v2/client" + "github.com/nspcc-dev/neofs-api-go/v2/netmap" + v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature" + "github.com/pkg/errors" +) + +// EndpointInfo returns attributes, address and public key of the node, specified +// in client constructor via address or open connection. This can be used as a +// health check to see if node is alive and responses to requests. +func (c Client) EndpointInfo(ctx context.Context, opts ...CallOption) (*netmap.NodeInfo, error) { + switch c.remoteNode.Version.GetMajor() { + case 2: + return c.endpointInfoV2(ctx, opts...) + default: + return nil, unsupportedProtocolErr + } +} + +func (c Client) endpointInfoV2(ctx context.Context, opts ...CallOption) (*netmap.NodeInfo, error) { + // apply all available options + callOptions := defaultCallOptions() + for i := range opts { + opts[i].apply(&callOptions) + } + + reqBody := new(netmap.LocalNodeInfoRequestBody) + + req := new(netmap.LocalNodeInfoRequest) + req.SetBody(reqBody) + req.SetMetaHeader(v2MetaHeaderFromOpts(callOptions)) + + err := v2signature.SignServiceMessage(c.key, req) + if err != nil { + return nil, err + } + + switch c.remoteNode.Protocol { + case GRPC: + cli, err := v2NetmapClientFromOptions(c.opts) + if err != nil { + return nil, errors.Wrap(err, "can't create grpc client") + } + + resp, err := cli.LocalNodeInfo(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "transport error") + } + + err = v2signature.VerifyServiceMessage(resp) + if err != nil { + return nil, errors.Wrap(err, "can't verify response message") + } + + return resp.GetBody().GetNodeInfo(), nil + default: + return nil, unsupportedProtocolErr + } +} + +func v2NetmapClientFromOptions(opts *clientOptions) (cli *netmap.Client, err error) { + switch { + case opts.grpcOpts.v2NetmapClient != nil: + // return value from client cache + return opts.grpcOpts.v2NetmapClient, nil + + case opts.grpcOpts.conn != nil: + cli, err = netmap.NewClient(netmap.WithGlobalOpts( + client.WithGRPCConn(opts.grpcOpts.conn)), + ) + + case opts.addr != "": + cli, err = netmap.NewClient(netmap.WithGlobalOpts( + client.WithNetworkAddress(opts.addr)), + ) + + default: + return nil, errors.New("lack of sdk client options to create accounting client") + } + + // check if client correct and save in cache + if err != nil { + return nil, err + } + + opts.grpcOpts.v2NetmapClient = cli + + return cli, nil +} diff --git a/pkg/client/opts.go b/pkg/client/opts.go index ec329f1..ff3546d 100644 --- a/pkg/client/opts.go +++ b/pkg/client/opts.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/pkg/token" v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting" v2container "github.com/nspcc-dev/neofs-api-go/v2/container" + v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap" v2object "github.com/nspcc-dev/neofs-api-go/v2/object" "github.com/nspcc-dev/neofs-api-go/v2/refs" v2session "github.com/nspcc-dev/neofs-api-go/v2/session" @@ -44,6 +45,7 @@ type ( v2ContainerClient *v2container.Client v2AccountingClient *v2accounting.Client v2SessionClient *v2session.Client + v2NetmapClient *v2netmap.Client objectClientV2 *v2object.Client }