forked from TrueCloudLab/frostfs-node
[#961] *: Support NeoFS API status returns
Upgrade NeoFS API Go library to version with status returns. Make all API clients to pull out and return errors from failed statuses. Make signature service to respond with status if client version supports it. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
44d0d453ef
commit
7f5fb130c0
27 changed files with 600 additions and 336 deletions
|
@ -2,18 +2,17 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/version"
|
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,12 +24,12 @@ type BalanceOfPrm struct {
|
||||||
|
|
||||||
// BalanceOfRes groups resulting values of BalanceOf operation.
|
// BalanceOfRes groups resulting values of BalanceOf operation.
|
||||||
type BalanceOfRes struct {
|
type BalanceOfRes struct {
|
||||||
cliRes *accounting.Decimal
|
cliRes *client.BalanceOfRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balance returns current balance.
|
// Balance returns current balance.
|
||||||
func (x BalanceOfRes) Balance() *accounting.Decimal {
|
func (x BalanceOfRes) Balance() *accounting.Decimal {
|
||||||
return x.cliRes
|
return x.cliRes.Amount()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceOf requests current balance of NeoFS user.
|
// BalanceOf requests current balance of NeoFS user.
|
||||||
|
@ -40,6 +39,10 @@ func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) {
|
||||||
res.cliRes, err = prm.cli.GetBalance(context.Background(), prm.ownerID,
|
res.cliRes, err = prm.cli.GetBalance(context.Background(), prm.ownerID,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -52,12 +55,12 @@ type ListContainersPrm struct {
|
||||||
|
|
||||||
// ListContainersRes groups resulting values of ListContainers operation.
|
// ListContainersRes groups resulting values of ListContainers operation.
|
||||||
type ListContainersRes struct {
|
type ListContainersRes struct {
|
||||||
cliRes []*cid.ID
|
cliRes *client.ContainerListRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDList returns list of identifiers of user's containers.
|
// IDList returns list of identifiers of user's containers.
|
||||||
func (x ListContainersRes) IDList() []*cid.ID {
|
func (x ListContainersRes) IDList() []*cid.ID {
|
||||||
return x.cliRes
|
return x.cliRes.IDList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListContainers requests list of NeoFS user's containers.
|
// ListContainers requests list of NeoFS user's containers.
|
||||||
|
@ -67,6 +70,10 @@ func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) {
|
||||||
res.cliRes, err = prm.cli.ListContainers(context.Background(), prm.ownerID,
|
res.cliRes, err = prm.cli.ListContainers(context.Background(), prm.ownerID,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -86,12 +93,12 @@ func (x *PutContainerPrm) SetContainer(cnr *container.Container) {
|
||||||
|
|
||||||
// PutContainerRes groups resulting values of PutContainer operation.
|
// PutContainerRes groups resulting values of PutContainer operation.
|
||||||
type PutContainerRes struct {
|
type PutContainerRes struct {
|
||||||
cliRes *cid.ID
|
cliRes *client.ContainerPutRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns identifier of the created container.
|
// ID returns identifier of the created container.
|
||||||
func (x PutContainerRes) ID() *cid.ID {
|
func (x PutContainerRes) ID() *cid.ID {
|
||||||
return x.cliRes
|
return x.cliRes.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutContainer sends request to save container in NeoFS.
|
// PutContainer sends request to save container in NeoFS.
|
||||||
|
@ -107,6 +114,10 @@ func PutContainer(prm PutContainerPrm) (res PutContainerRes, err error) {
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -119,12 +130,12 @@ type GetContainerPrm struct {
|
||||||
|
|
||||||
// GetContainerRes groups resulting values of GetContainer operation.
|
// GetContainerRes groups resulting values of GetContainer operation.
|
||||||
type GetContainerRes struct {
|
type GetContainerRes struct {
|
||||||
cliRes *container.Container
|
cliRes *client.ContainerGetRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container returns structured of the requested container.
|
// Container returns structured of the requested container.
|
||||||
func (x GetContainerRes) Container() *container.Container {
|
func (x GetContainerRes) Container() *container.Container {
|
||||||
return x.cliRes
|
return x.cliRes.Container()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainer reads container from NeoFS by ID.
|
// GetContainer reads container from NeoFS by ID.
|
||||||
|
@ -134,6 +145,10 @@ func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) {
|
||||||
res.cliRes, err = prm.cli.GetContainer(context.Background(), prm.cnrID,
|
res.cliRes, err = prm.cli.GetContainer(context.Background(), prm.cnrID,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -157,10 +172,16 @@ type DeleteContainerRes struct{}
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func DeleteContainer(prm DeleteContainerPrm) (res DeleteContainerRes, err error) {
|
func DeleteContainer(prm DeleteContainerPrm) (res DeleteContainerRes, err error) {
|
||||||
err = prm.cli.DeleteContainer(context.Background(), prm.cnrID,
|
var cliRes *client.ContainerDeleteRes
|
||||||
|
|
||||||
|
cliRes, err = prm.cli.DeleteContainer(context.Background(), prm.cnrID,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -173,21 +194,25 @@ type EACLPrm struct {
|
||||||
|
|
||||||
// EACLRes groups resulting values of EACL operation.
|
// EACLRes groups resulting values of EACL operation.
|
||||||
type EACLRes struct {
|
type EACLRes struct {
|
||||||
cliRes *client.EACLWithSignature
|
cliRes *client.EACLRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// EACL returns requested eACL table.
|
// EACL returns requested eACL table.
|
||||||
func (x EACLRes) EACL() *eacl.Table {
|
func (x EACLRes) EACL() *eacl.Table {
|
||||||
return x.cliRes.EACL()
|
return x.cliRes.Table()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EACL reads eACL table from NeoFS by container ID.
|
// EACL reads eACL table from NeoFS by container ID.
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func EACL(prm EACLPrm) (res EACLRes, err error) {
|
func EACL(prm EACLPrm) (res EACLRes, err error) {
|
||||||
res.cliRes, err = prm.cli.GetEACL(context.Background(), prm.cnrID,
|
res.cliRes, err = prm.cli.EACL(context.Background(), prm.cnrID,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -217,10 +242,16 @@ type SetEACLRes struct{}
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func SetEACL(prm SetEACLPrm) (res SetEACLRes, err error) {
|
func SetEACL(prm SetEACLPrm) (res SetEACLRes, err error) {
|
||||||
err = prm.cli.SetEACL(context.Background(), prm.eaclTable,
|
var cliRes *client.SetEACLRes
|
||||||
|
|
||||||
|
cliRes, err = prm.cli.SetEACL(context.Background(), prm.eaclTable,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -232,12 +263,12 @@ type NetworkInfoPrm struct {
|
||||||
|
|
||||||
// NetworkInfoRes groups resulting values of NetworkInfo operation.
|
// NetworkInfoRes groups resulting values of NetworkInfo operation.
|
||||||
type NetworkInfoRes struct {
|
type NetworkInfoRes struct {
|
||||||
cliRes *netmap.NetworkInfo
|
cliRes *client.NetworkInfoRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInfo returns structured information about the NeoFS network.
|
// NetworkInfo returns structured information about the NeoFS network.
|
||||||
func (x NetworkInfoRes) NetworkInfo() *netmap.NetworkInfo {
|
func (x NetworkInfoRes) NetworkInfo() *netmap.NetworkInfo {
|
||||||
return x.cliRes
|
return x.cliRes.Info()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInfo reads information about the NeoFS network.
|
// NetworkInfo reads information about the NeoFS network.
|
||||||
|
@ -247,6 +278,10 @@ func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) {
|
||||||
res.cliRes, err = prm.cli.NetworkInfo(context.Background(),
|
res.cliRes, err = prm.cli.NetworkInfo(context.Background(),
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -258,17 +293,17 @@ type NodeInfoPrm struct {
|
||||||
|
|
||||||
// NodeInfoRes groups resulting values of NodeInfo operation.
|
// NodeInfoRes groups resulting values of NodeInfo operation.
|
||||||
type NodeInfoRes struct {
|
type NodeInfoRes struct {
|
||||||
cliRes *client.EndpointInfo
|
cliRes *client.EndpointInfoRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeInfo returns information about the node from netmap.
|
// NodeInfo returns information about the node from netmap.
|
||||||
func (x NodeInfoRes) NodeInfo() *netmap.NodeInfo {
|
func (x NodeInfoRes) NodeInfo() *netmap.NodeInfo {
|
||||||
return x.cliRes.NodeInfo()
|
return x.cliRes.Info().NodeInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LatestVersion returns latest NeoFS API version in use.
|
// LatestVersion returns latest NeoFS API version in use.
|
||||||
func (x NodeInfoRes) LatestVersion() *version.Version {
|
func (x NodeInfoRes) LatestVersion() *version.Version {
|
||||||
return x.cliRes.LatestVersion()
|
return x.cliRes.Info().LatestVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeInfo requests information about the remote server from NeoFS netmap.
|
// NodeInfo requests information about the remote server from NeoFS netmap.
|
||||||
|
@ -278,6 +313,10 @@ func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) {
|
||||||
res.cliRes, err = prm.cli.EndpointInfo(context.Background(),
|
res.cliRes, err = prm.cli.EndpointInfo(context.Background(),
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -289,7 +328,7 @@ type CreateSessionPrm struct {
|
||||||
|
|
||||||
// CreateSessionRes groups resulting values of CreateSession operation.
|
// CreateSessionRes groups resulting values of CreateSession operation.
|
||||||
type CreateSessionRes struct {
|
type CreateSessionRes struct {
|
||||||
cliRes *session.Token
|
cliRes *client.CreateSessionRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns session identifier.
|
// ID returns session identifier.
|
||||||
|
@ -309,6 +348,10 @@ func CreateSession(prm CreateSessionPrm) (res CreateSessionRes, err error) {
|
||||||
res.cliRes, err = prm.cli.CreateSession(context.Background(), math.MaxUint64,
|
res.cliRes, err = prm.cli.CreateSession(context.Background(), math.MaxUint64,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -334,12 +377,12 @@ func (x *PutObjectPrm) SetPayloadReader(rdr io.Reader) {
|
||||||
|
|
||||||
// PutObjectRes groups resulting values of PutObject operation.
|
// PutObjectRes groups resulting values of PutObject operation.
|
||||||
type PutObjectRes struct {
|
type PutObjectRes struct {
|
||||||
cliRes *object.ID
|
cliRes *client.ObjectPutRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns identifier of the created object.
|
// ID returns identifier of the created object.
|
||||||
func (x PutObjectRes) ID() *object.ID {
|
func (x PutObjectRes) ID() *object.ID {
|
||||||
return x.cliRes
|
return x.cliRes.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObject saves the object in NeoFS network.
|
// PutObject saves the object in NeoFS network.
|
||||||
|
@ -356,6 +399,10 @@ func PutObject(prm PutObjectPrm) (res PutObjectRes, err error) {
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -368,12 +415,12 @@ type DeleteObjectPrm struct {
|
||||||
|
|
||||||
// DeleteObjectRes groups resulting values of DeleteObject operation.
|
// DeleteObjectRes groups resulting values of DeleteObject operation.
|
||||||
type DeleteObjectRes struct {
|
type DeleteObjectRes struct {
|
||||||
cliRes *object.Address
|
cliRes *client.ObjectDeleteRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// TombstoneAddress returns address of the created object with tombstone.
|
// TombstoneAddress returns address of the created object with tombstone.
|
||||||
func (x DeleteObjectRes) TombstoneAddress() *object.Address {
|
func (x DeleteObjectRes) TombstoneAddress() *object.Address {
|
||||||
return x.cliRes
|
return x.cliRes.TombstoneAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObject marks object to be removed from NeoFS through tombstone placement.
|
// DeleteObject marks object to be removed from NeoFS through tombstone placement.
|
||||||
|
@ -384,11 +431,15 @@ func DeleteObject(prm DeleteObjectPrm) (res DeleteObjectRes, err error) {
|
||||||
|
|
||||||
delPrm.WithAddress(prm.objAddr)
|
delPrm.WithAddress(prm.objAddr)
|
||||||
|
|
||||||
res.cliRes, err = client.DeleteObject(context.Background(), prm.cli, &delPrm, append(prm.opts,
|
res.cliRes, err = prm.cli.DeleteObject(context.Background(), &delPrm, append(prm.opts,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -403,12 +454,12 @@ type GetObjectPrm struct {
|
||||||
|
|
||||||
// GetObjectRes groups resulting values of GetObject operation.
|
// GetObjectRes groups resulting values of GetObject operation.
|
||||||
type GetObjectRes struct {
|
type GetObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectGetRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object returns header of the request object.
|
// Object returns header of the request object.
|
||||||
func (x GetObjectRes) Header() *object.Object {
|
func (x GetObjectRes) Header() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObject reads the object by address.
|
// GetObject reads the object by address.
|
||||||
|
@ -429,6 +480,10 @@ func GetObject(prm GetObjectPrm) (res GetObjectRes, err error) {
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -449,12 +504,12 @@ func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) {
|
||||||
|
|
||||||
// HeadObjectRes groups resulting values of HeadObject operation.
|
// HeadObjectRes groups resulting values of HeadObject operation.
|
||||||
type HeadObjectRes struct {
|
type HeadObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectHeadRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns requested object header.
|
// Header returns requested object header.
|
||||||
func (x HeadObjectRes) Header() *object.Object {
|
func (x HeadObjectRes) Header() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeadObject reads object header by address.
|
// HeadObject reads object header by address.
|
||||||
|
@ -473,11 +528,15 @@ func HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) {
|
||||||
cliPrm.WithAllFields()
|
cliPrm.WithAllFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
res.cliRes, err = prm.cli.GetObjectHeader(context.Background(), &cliPrm, append(prm.opts,
|
res.cliRes, err = prm.cli.HeadObject(context.Background(), &cliPrm, append(prm.opts,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -497,12 +556,12 @@ func (x *SearchObjectsPrm) SetFilters(filters object.SearchFilters) {
|
||||||
|
|
||||||
// SearchObjectsRes groups resulting values of SearchObjects operation.
|
// SearchObjectsRes groups resulting values of SearchObjects operation.
|
||||||
type SearchObjectsRes struct {
|
type SearchObjectsRes struct {
|
||||||
cliRes []*object.ID
|
cliRes *client.ObjectSearchRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDList returns identifiers of the matched objects.
|
// IDList returns identifiers of the matched objects.
|
||||||
func (x SearchObjectsRes) IDList() []*object.ID {
|
func (x SearchObjectsRes) IDList() []*object.ID {
|
||||||
return x.cliRes
|
return x.cliRes.IDList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchObjects selects objects from container which match the filters.
|
// SearchObjects selects objects from container which match the filters.
|
||||||
|
@ -514,11 +573,15 @@ func SearchObjects(prm SearchObjectsPrm) (res SearchObjectsRes, err error) {
|
||||||
cliPrm.WithSearchFilters(prm.filters)
|
cliPrm.WithSearchFilters(prm.filters)
|
||||||
cliPrm.WithContainerID(prm.cnrID)
|
cliPrm.WithContainerID(prm.cnrID)
|
||||||
|
|
||||||
res.cliRes, err = prm.cli.SearchObject(context.Background(), &cliPrm, append(prm.opts,
|
res.cliRes, err = prm.cli.SearchObjects(context.Background(), &cliPrm, append(prm.opts,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -552,12 +615,12 @@ func (x *HashPayloadRangesPrm) SetSalt(salt []byte) {
|
||||||
|
|
||||||
// HashPayloadRangesRes groups resulting values of HashPayloadRanges operation.
|
// HashPayloadRangesRes groups resulting values of HashPayloadRanges operation.
|
||||||
type HashPayloadRangesRes struct {
|
type HashPayloadRangesRes struct {
|
||||||
cliRes [][]byte
|
cliRes *client.ObjectRangeHashRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashList returns list of hashes of the payload ranges keeping order.
|
// HashList returns list of hashes of the payload ranges keeping order.
|
||||||
func (x HashPayloadRangesRes) HashList() [][]byte {
|
func (x HashPayloadRangesRes) HashList() [][]byte {
|
||||||
return x.cliRes
|
return x.cliRes.Hashes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashPayloadRanges requests hashes (by default SHA256) of the object payload ranges.
|
// HashPayloadRanges requests hashes (by default SHA256) of the object payload ranges.
|
||||||
|
@ -572,35 +635,17 @@ func HashPayloadRanges(prm HashPayloadRangesPrm) (res HashPayloadRangesRes, err
|
||||||
cliPrm.WithRangeList(prm.rngs...)
|
cliPrm.WithRangeList(prm.rngs...)
|
||||||
|
|
||||||
if prm.tz {
|
if prm.tz {
|
||||||
var hs [][sha256.Size]byte
|
cliPrm.TZ()
|
||||||
|
}
|
||||||
|
|
||||||
hs, err = prm.cli.ObjectPayloadRangeSHA256(context.Background(), &cliPrm, append(prm.opts,
|
res.cliRes, err = prm.cli.HashObjectPayloadRanges(context.Background(), &cliPrm, append(prm.opts,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
res.cliRes = make([][]byte, 0, len(hs))
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
for i := range hs {
|
|
||||||
res.cliRes = append(res.cliRes, hs[i][:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var hs [][client.TZSize]byte
|
|
||||||
|
|
||||||
hs, err = prm.cli.ObjectPayloadRangeTZ(context.Background(), &cliPrm, append(prm.opts,
|
|
||||||
client.WithKey(prm.privKey),
|
|
||||||
client.WithSession(prm.sessionToken),
|
|
||||||
client.WithBearer(prm.bearerToken),
|
|
||||||
)...)
|
|
||||||
if err == nil {
|
|
||||||
res.cliRes = make([][]byte, 0, len(hs))
|
|
||||||
|
|
||||||
for i := range hs {
|
|
||||||
res.cliRes = append(res.cliRes, hs[i][:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -638,11 +683,17 @@ func PayloadRange(prm PayloadRangePrm) (res PayloadRangeRes, err error) {
|
||||||
cliPrm.WithDataWriter(prm.wrt)
|
cliPrm.WithDataWriter(prm.wrt)
|
||||||
cliPrm.WithRange(prm.rng)
|
cliPrm.WithRange(prm.rng)
|
||||||
|
|
||||||
_, err = prm.cli.ObjectPayloadRangeData(context.Background(), &cliPrm, append(prm.opts,
|
var cliRes *client.ObjectRangeRes
|
||||||
|
|
||||||
|
cliRes, err = prm.cli.ObjectPayloadRangeData(context.Background(), &cliPrm, append(prm.opts,
|
||||||
client.WithKey(prm.privKey),
|
client.WithKey(prm.privKey),
|
||||||
client.WithSession(prm.sessionToken),
|
client.WithSession(prm.sessionToken),
|
||||||
client.WithBearer(prm.bearerToken),
|
client.WithBearer(prm.bearerToken),
|
||||||
)...)
|
)...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,7 +312,8 @@ func (r *remoteLoadAnnounceWriter) Put(a containerSDK.UsedSpaceAnnouncement) err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteLoadAnnounceWriter) Close() error {
|
func (r *remoteLoadAnnounceWriter) Close() error {
|
||||||
return r.client.AnnounceContainerUsedSpace(r.ctx, r.buf, apiClient.WithKey(r.key))
|
_, err := r.client.AnnounceContainerUsedSpace(r.ctx, r.buf, apiClient.WithKey(r.key))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type loadPlacementBuilder struct {
|
type loadPlacementBuilder struct {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
|
@ -474,68 +473,60 @@ func (c *reputationClient) submitResult(err error) {
|
||||||
c.cons.trustStorage.Update(prm)
|
c.cons.trustStorage.Update(prm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) PutObject(ctx context.Context, prm *client.PutObjectParams, opts ...client.CallOption) (*objectSDK.ID, error) {
|
func (c *reputationClient) PutObject(ctx context.Context, prm *client.PutObjectParams, opts ...client.CallOption) (*client.ObjectPutRes, error) {
|
||||||
id, err := c.Client.PutObject(ctx, prm, opts...)
|
res, err := c.Client.PutObject(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return id, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) DeleteObject(ctx context.Context, prm *client.DeleteObjectParams, opts ...client.CallOption) error {
|
func (c *reputationClient) DeleteObject(ctx context.Context, prm *client.DeleteObjectParams, opts ...client.CallOption) (*client.ObjectDeleteRes, error) {
|
||||||
err := c.Client.DeleteObject(ctx, prm, opts...)
|
res, err := c.Client.DeleteObject(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) GetObject(ctx context.Context, prm *client.GetObjectParams, opts ...client.CallOption) (*objectSDK.Object, error) {
|
func (c *reputationClient) GetObject(ctx context.Context, prm *client.GetObjectParams, opts ...client.CallOption) (*client.ObjectGetRes, error) {
|
||||||
obj, err := c.Client.GetObject(ctx, prm, opts...)
|
res, err := c.Client.GetObject(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return obj, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) GetObjectHeader(ctx context.Context, prm *client.ObjectHeaderParams, opts ...client.CallOption) (*objectSDK.Object, error) {
|
func (c *reputationClient) HeadObject(ctx context.Context, prm *client.ObjectHeaderParams, opts ...client.CallOption) (*client.ObjectHeadRes, error) {
|
||||||
obj, err := c.Client.GetObjectHeader(ctx, prm, opts...)
|
res, err := c.Client.HeadObject(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return obj, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) ObjectPayloadRangeData(ctx context.Context, prm *client.RangeDataParams, opts ...client.CallOption) ([]byte, error) {
|
func (c *reputationClient) ObjectPayloadRangeData(ctx context.Context, prm *client.RangeDataParams, opts ...client.CallOption) (*client.ObjectRangeRes, error) {
|
||||||
rng, err := c.Client.ObjectPayloadRangeData(ctx, prm, opts...)
|
res, err := c.Client.ObjectPayloadRangeData(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return rng, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) ObjectPayloadRangeSHA256(ctx context.Context, prm *client.RangeChecksumParams, opts ...client.CallOption) ([][sha256.Size]byte, error) {
|
func (c *reputationClient) HashObjectPayloadRanges(ctx context.Context, prm *client.RangeChecksumParams, opts ...client.CallOption) (*client.ObjectRangeHashRes, error) {
|
||||||
hashes, err := c.Client.ObjectPayloadRangeSHA256(ctx, prm, opts...)
|
res, err := c.Client.HashObjectPayloadRanges(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return hashes, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClient) ObjectPayloadRangeTZ(ctx context.Context, prm *client.RangeChecksumParams, opts ...client.CallOption) ([][client.TZSize]byte, error) {
|
func (c *reputationClient) SearchObjects(ctx context.Context, prm *client.SearchObjectParams, opts ...client.CallOption) (*client.ObjectSearchRes, error) {
|
||||||
hashes, err := c.Client.ObjectPayloadRangeTZ(ctx, prm, opts...)
|
res, err := c.Client.SearchObjects(ctx, prm, opts...)
|
||||||
|
|
||||||
c.submitResult(err)
|
c.submitResult(err)
|
||||||
|
|
||||||
return hashes, err
|
return res, err
|
||||||
}
|
|
||||||
|
|
||||||
func (c *reputationClient) SearchObject(ctx context.Context, prm *client.SearchObjectParams, opts ...client.CallOption) ([]*objectSDK.ID, error) {
|
|
||||||
ids, err := c.Client.SearchObject(ctx, prm, opts...)
|
|
||||||
|
|
||||||
c.submitResult(err)
|
|
||||||
|
|
||||||
return ids, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *reputationClientConstructor) Get(info coreclient.NodeInfo) (client.Client, error) {
|
func (c *reputationClientConstructor) Get(info coreclient.NodeInfo) (client.Client, error) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/reputation"
|
"github.com/nspcc-dev/neofs-sdk-go/reputation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,7 +66,13 @@ type AnnounceLocalRes struct{}
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func AnnounceLocal(prm AnnounceLocalPrm) (res AnnounceLocalRes, err error) {
|
func AnnounceLocal(prm AnnounceLocalPrm) (res AnnounceLocalRes, err error) {
|
||||||
_, err = prm.cli.AnnounceLocalTrust(prm.ctx, prm.cliPrm, prm.opts...)
|
var cliRes *client.AnnounceLocalTrustRes
|
||||||
|
|
||||||
|
cliRes, err = prm.cli.AnnounceLocalTrust(prm.ctx, prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -102,7 +109,13 @@ type AnnounceIntermediateRes struct{}
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func AnnounceIntermediate(prm AnnounceIntermediatePrm) (res AnnounceIntermediateRes, err error) {
|
func AnnounceIntermediate(prm AnnounceIntermediatePrm) (res AnnounceIntermediateRes, err error) {
|
||||||
_, err = prm.cli.AnnounceIntermediateTrust(prm.ctx, prm.cliPrm, prm.opts...)
|
var cliRes *client.AnnounceIntermediateTrustRes
|
||||||
|
|
||||||
|
cliRes, err = prm.cli.AnnounceIntermediateTrust(prm.ctx, prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -11,9 +11,9 @@ require (
|
||||||
github.com/mr-tron/base58 v1.2.0
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/multiformats/go-multiaddr v0.4.0
|
github.com/multiformats/go-multiaddr v0.4.0
|
||||||
github.com/nspcc-dev/hrw v1.0.9
|
github.com/nspcc-dev/hrw v1.0.9
|
||||||
github.com/nspcc-dev/neo-go v0.97.3
|
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211123163659-b25c3775e847
|
||||||
github.com/nspcc-dev/neofs-api-go v1.30.0
|
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211118144033-580f6c5554ff
|
||||||
github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211110152919-10b78e74afbd
|
github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211123100340-d9317cbea191
|
||||||
github.com/nspcc-dev/tzhash v1.4.0
|
github.com/nspcc-dev/tzhash v1.4.0
|
||||||
github.com/panjf2000/ants/v2 v2.4.0
|
github.com/panjf2000/ants/v2 v2.4.0
|
||||||
github.com/paulmach/orb v0.2.2
|
github.com/paulmach/orb v0.2.2
|
||||||
|
|
BIN
go.sum
BIN
go.sum
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
rawclient "github.com/nspcc-dev/neofs-api-go/rpc/client"
|
rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/network"
|
"github.com/nspcc-dev/neofs-node/pkg/network"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup"
|
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
)
|
)
|
||||||
|
@ -42,12 +43,12 @@ func (x *SearchSGPrm) SetContainerID(id *cid.ID) {
|
||||||
|
|
||||||
// SearchSGRes groups resulting values of SearchSG operation.
|
// SearchSGRes groups resulting values of SearchSG operation.
|
||||||
type SearchSGRes struct {
|
type SearchSGRes struct {
|
||||||
cliRes []*object.ID
|
cliRes *client.ObjectSearchRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDList returns list of IDs of storage groups in container.
|
// IDList returns list of IDs of storage groups in container.
|
||||||
func (x SearchSGRes) IDList() []*object.ID {
|
func (x SearchSGRes) IDList() []*object.ID {
|
||||||
return x.cliRes
|
return x.cliRes.IDList()
|
||||||
}
|
}
|
||||||
|
|
||||||
var sgFilter = storagegroup.SearchQuery()
|
var sgFilter = storagegroup.SearchQuery()
|
||||||
|
@ -61,9 +62,13 @@ func (x Client) SearchSG(prm SearchSGPrm) (res SearchSGRes, err error) {
|
||||||
cliPrm.WithContainerID(prm.cnrID)
|
cliPrm.WithContainerID(prm.cnrID)
|
||||||
cliPrm.WithSearchFilters(sgFilter)
|
cliPrm.WithSearchFilters(sgFilter)
|
||||||
|
|
||||||
res.cliRes, err = x.c.SearchObject(prm.ctx, &cliPrm,
|
res.cliRes, err = x.c.SearchObjects(prm.ctx, &cliPrm,
|
||||||
client.WithKey(x.key),
|
client.WithKey(x.key),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -75,12 +80,12 @@ type GetObjectPrm struct {
|
||||||
|
|
||||||
// GetObjectRes groups resulting values of GetObject operation.
|
// GetObjectRes groups resulting values of GetObject operation.
|
||||||
type GetObjectRes struct {
|
type GetObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectGetRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object returns received object.
|
// Object returns received object.
|
||||||
func (x GetObjectRes) Object() *object.Object {
|
func (x GetObjectRes) Object() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObject reads the object by address.
|
// GetObject reads the object by address.
|
||||||
|
@ -94,6 +99,10 @@ func (x Client) GetObject(prm GetObjectPrm) (res GetObjectRes, err error) {
|
||||||
res.cliRes, err = x.c.GetObject(prm.ctx, &cliPrm,
|
res.cliRes, err = x.c.GetObject(prm.ctx, &cliPrm,
|
||||||
client.WithKey(x.key),
|
client.WithKey(x.key),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -119,12 +128,12 @@ func (x *HeadObjectPrm) SetTTL(ttl uint32) {
|
||||||
|
|
||||||
// HeadObjectRes groups resulting values of HeadObject operation.
|
// HeadObjectRes groups resulting values of HeadObject operation.
|
||||||
type HeadObjectRes struct {
|
type HeadObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectHeadRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns received object header.
|
// Header returns received object header.
|
||||||
func (x HeadObjectRes) Header() *object.Object {
|
func (x HeadObjectRes) Header() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeadObject reads short object header by address.
|
// HeadObject reads short object header by address.
|
||||||
|
@ -138,10 +147,14 @@ func (x Client) HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) {
|
||||||
cliPrm.WithRawFlag(prm.raw)
|
cliPrm.WithRawFlag(prm.raw)
|
||||||
cliPrm.WithMainFields()
|
cliPrm.WithMainFields()
|
||||||
|
|
||||||
res.cliRes, err = x.c.GetObjectHeader(prm.ctx, &cliPrm,
|
res.cliRes, err = x.c.HeadObject(prm.ctx, &cliPrm,
|
||||||
client.WithKey(x.key),
|
client.WithKey(x.key),
|
||||||
client.WithTTL(prm.ttl),
|
client.WithTTL(prm.ttl),
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -225,15 +238,22 @@ func (x Client) HashPayloadRange(prm HashPayloadRangePrm) (res HashPayloadRangeR
|
||||||
cliPrm.WithAddress(prm.objAddr)
|
cliPrm.WithAddress(prm.objAddr)
|
||||||
cliPrm.WithRangeList(prm.rng)
|
cliPrm.WithRangeList(prm.rng)
|
||||||
|
|
||||||
hs, err := x.c.ObjectPayloadRangeTZ(prm.ctx, &cliPrm,
|
cliRes, err := x.c.HashObjectPayloadRanges(prm.ctx, &cliPrm,
|
||||||
client.WithKey(x.key),
|
client.WithKey(x.key),
|
||||||
client.WithTTL(1),
|
client.WithTTL(1),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(cliRes.Status())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hs := cliRes.Hashes()
|
||||||
if ln := len(hs); ln != 1 {
|
if ln := len(hs); ln != 1 {
|
||||||
err = fmt.Errorf("wrong number of hashes %d", ln)
|
err = fmt.Errorf("wrong number of hashes %d", ln)
|
||||||
} else {
|
} else {
|
||||||
res.h = hs[0][:]
|
res.h = hs[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
226
pkg/network/cache/multi.go
vendored
226
pkg/network/cache/multi.go
vendored
|
@ -2,23 +2,18 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
rawclient "github.com/nspcc-dev/neofs-api-go/rpc/client"
|
rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/network"
|
"github.com/nspcc-dev/neofs-node/pkg/network"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type multiClient struct {
|
type multiClient struct {
|
||||||
|
@ -87,215 +82,184 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(client.Client)
|
||||||
return firstErr
|
return firstErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) PutObject(ctx context.Context, p *client.PutObjectParams, opts ...client.CallOption) (*object.ID, error) {
|
func (x *multiClient) PutObject(ctx context.Context, p *client.PutObjectParams, opts ...client.CallOption) (res *client.ObjectPutRes, err error) {
|
||||||
var res *object.ID
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.PutObject(ctx, p, opts...)
|
res, err = c.PutObject(ctx, p, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) GetBalance(ctx context.Context, id *owner.ID, opts ...client.CallOption) (*accounting.Decimal, error) {
|
func (x *multiClient) GetBalance(ctx context.Context, id *owner.ID, opts ...client.CallOption) (res *client.BalanceOfRes, err error) {
|
||||||
var res *accounting.Decimal
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.GetBalance(ctx, id, opts...)
|
res, err = c.GetBalance(ctx, id, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) PutContainer(ctx context.Context, cnr *container.Container, opts ...client.CallOption) (*cid.ID, error) {
|
func (x *multiClient) PutContainer(ctx context.Context, cnr *container.Container, opts ...client.CallOption) (res *client.ContainerPutRes, err error) {
|
||||||
var res *cid.ID
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.PutContainer(ctx, cnr, opts...)
|
res, err = c.PutContainer(ctx, cnr, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) GetContainer(ctx context.Context, id *cid.ID, opts ...client.CallOption) (*container.Container, error) {
|
func (x *multiClient) GetContainer(ctx context.Context, id *cid.ID, opts ...client.CallOption) (res *client.ContainerGetRes, err error) {
|
||||||
var res *container.Container
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.GetContainer(ctx, id, opts...)
|
res, err = c.GetContainer(ctx, id, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) ListContainers(ctx context.Context, id *owner.ID, opts ...client.CallOption) ([]*cid.ID, error) {
|
func (x *multiClient) ListContainers(ctx context.Context, id *owner.ID, opts ...client.CallOption) (res *client.ContainerListRes, err error) {
|
||||||
var res []*cid.ID
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.ListContainers(ctx, id, opts...)
|
res, err = c.ListContainers(ctx, id, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) DeleteContainer(ctx context.Context, id *cid.ID, opts ...client.CallOption) error {
|
func (x *multiClient) DeleteContainer(ctx context.Context, id *cid.ID, opts ...client.CallOption) (res *client.ContainerDeleteRes, err error) {
|
||||||
return x.iterateClients(ctx, func(c client.Client) error {
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
return c.DeleteContainer(ctx, id, opts...)
|
res, err = c.DeleteContainer(ctx, id, opts...)
|
||||||
})
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
func (x *multiClient) GetEACL(ctx context.Context, id *cid.ID, opts ...client.CallOption) (*client.EACLWithSignature, error) {
|
|
||||||
var res *client.EACLWithSignature
|
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.GetEACL(ctx, id, opts...)
|
|
||||||
return
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) SetEACL(ctx context.Context, t *eacl.Table, opts ...client.CallOption) error {
|
func (x *multiClient) EACL(ctx context.Context, id *cid.ID, opts ...client.CallOption) (res *client.EACLRes, err error) {
|
||||||
return x.iterateClients(ctx, func(c client.Client) error {
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
return c.SetEACL(ctx, t, opts...)
|
res, err = c.EACL(ctx, id, opts...)
|
||||||
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) AnnounceContainerUsedSpace(ctx context.Context, as []container.UsedSpaceAnnouncement, opts ...client.CallOption) error {
|
func (x *multiClient) SetEACL(ctx context.Context, t *eacl.Table, opts ...client.CallOption) (res *client.SetEACLRes, err error) {
|
||||||
return x.iterateClients(ctx, func(c client.Client) error {
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
return c.AnnounceContainerUsedSpace(ctx, as, opts...)
|
res, err = c.SetEACL(ctx, t, opts...)
|
||||||
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) EndpointInfo(ctx context.Context, opts ...client.CallOption) (*client.EndpointInfo, error) {
|
func (x *multiClient) AnnounceContainerUsedSpace(ctx context.Context, as []container.UsedSpaceAnnouncement, opts ...client.CallOption) (res *client.AnnounceSpaceRes, err error) {
|
||||||
var res *client.EndpointInfo
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
res, err = c.AnnounceContainerUsedSpace(ctx, as, opts...)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *multiClient) EndpointInfo(ctx context.Context, opts ...client.CallOption) (res *client.EndpointInfoRes, err error) {
|
||||||
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
res, err = c.EndpointInfo(ctx, opts...)
|
res, err = c.EndpointInfo(ctx, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) NetworkInfo(ctx context.Context, opts ...client.CallOption) (*netmap.NetworkInfo, error) {
|
func (x *multiClient) NetworkInfo(ctx context.Context, opts ...client.CallOption) (res *client.NetworkInfoRes, err error) {
|
||||||
var res *netmap.NetworkInfo
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.NetworkInfo(ctx, opts...)
|
res, err = c.NetworkInfo(ctx, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) DeleteObject(ctx context.Context, p *client.DeleteObjectParams, opts ...client.CallOption) error {
|
func (x *multiClient) DeleteObject(ctx context.Context, p *client.DeleteObjectParams, opts ...client.CallOption) (res *client.ObjectDeleteRes, err error) {
|
||||||
return x.iterateClients(ctx, func(c client.Client) error {
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
return c.DeleteObject(ctx, p, opts...)
|
res, err = c.DeleteObject(ctx, p, opts...)
|
||||||
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) GetObject(ctx context.Context, p *client.GetObjectParams, opts ...client.CallOption) (*object.Object, error) {
|
func (x *multiClient) GetObject(ctx context.Context, p *client.GetObjectParams, opts ...client.CallOption) (res *client.ObjectGetRes, err error) {
|
||||||
var res *object.Object
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.GetObject(ctx, p, opts...)
|
res, err = c.GetObject(ctx, p, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) GetObjectHeader(ctx context.Context, p *client.ObjectHeaderParams, opts ...client.CallOption) (*object.Object, error) {
|
func (x *multiClient) ObjectPayloadRangeData(ctx context.Context, p *client.RangeDataParams, opts ...client.CallOption) (res *client.ObjectRangeRes, err error) {
|
||||||
var res *object.Object
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.GetObjectHeader(ctx, p, opts...)
|
|
||||||
return
|
|
||||||
})
|
|
||||||
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *multiClient) ObjectPayloadRangeData(ctx context.Context, p *client.RangeDataParams, opts ...client.CallOption) ([]byte, error) {
|
|
||||||
var res []byte
|
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.ObjectPayloadRangeData(ctx, p, opts...)
|
res, err = c.ObjectPayloadRangeData(ctx, p, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) ObjectPayloadRangeSHA256(ctx context.Context, p *client.RangeChecksumParams, opts ...client.CallOption) ([][sha256.Size]byte, error) {
|
func (x *multiClient) HeadObject(ctx context.Context, p *client.ObjectHeaderParams, opts ...client.CallOption) (res *client.ObjectHeadRes, err error) {
|
||||||
var res [][sha256.Size]byte
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
res, err = c.HeadObject(ctx, p, opts...)
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
return err
|
||||||
res, err = c.ObjectPayloadRangeSHA256(ctx, p, opts...)
|
|
||||||
return
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) ObjectPayloadRangeTZ(ctx context.Context, p *client.RangeChecksumParams, opts ...client.CallOption) ([][client.TZSize]byte, error) {
|
func (x *multiClient) HashObjectPayloadRanges(ctx context.Context, p *client.RangeChecksumParams, opts ...client.CallOption) (res *client.ObjectRangeHashRes, err error) {
|
||||||
var res [][client.TZSize]byte
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
res, err = c.HashObjectPayloadRanges(ctx, p, opts...)
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
return err
|
||||||
res, err = c.ObjectPayloadRangeTZ(ctx, p, opts...)
|
|
||||||
return
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) SearchObject(ctx context.Context, p *client.SearchObjectParams, opts ...client.CallOption) ([]*object.ID, error) {
|
func (x *multiClient) SearchObjects(ctx context.Context, p *client.SearchObjectParams, opts ...client.CallOption) (res *client.ObjectSearchRes, err error) {
|
||||||
var res []*object.ID
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
res, err = c.SearchObjects(ctx, p, opts...)
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
return err
|
||||||
res, err = c.SearchObject(ctx, p, opts...)
|
|
||||||
return
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) CreateSession(ctx context.Context, exp uint64, opts ...client.CallOption) (*session.Token, error) {
|
func (x *multiClient) CreateSession(ctx context.Context, exp uint64, opts ...client.CallOption) (res *client.CreateSessionRes, err error) {
|
||||||
var res *session.Token
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.CreateSession(ctx, exp, opts...)
|
res, err = c.CreateSession(ctx, exp, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) AnnounceLocalTrust(ctx context.Context, p client.AnnounceLocalTrustPrm, opts ...client.CallOption) (*client.AnnounceLocalTrustRes, error) {
|
func (x *multiClient) AnnounceLocalTrust(ctx context.Context, p client.AnnounceLocalTrustPrm, opts ...client.CallOption) (res *client.AnnounceLocalTrustRes, err error) {
|
||||||
var res *client.AnnounceLocalTrustRes
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.AnnounceLocalTrust(ctx, p, opts...)
|
res, err = c.AnnounceLocalTrust(ctx, p, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) AnnounceIntermediateTrust(ctx context.Context, p client.AnnounceIntermediateTrustPrm, opts ...client.CallOption) (*client.AnnounceIntermediateTrustRes, error) {
|
func (x *multiClient) AnnounceIntermediateTrust(ctx context.Context, p client.AnnounceIntermediateTrustPrm, opts ...client.CallOption) (res *client.AnnounceIntermediateTrustRes, err error) {
|
||||||
var res *client.AnnounceIntermediateTrustRes
|
err = x.iterateClients(ctx, func(c client.Client) error {
|
||||||
|
|
||||||
err := x.iterateClients(ctx, func(c client.Client) (err error) {
|
|
||||||
res, err = c.AnnounceIntermediateTrust(ctx, p, opts...)
|
res, err = c.AnnounceIntermediateTrust(ctx, p, opts...)
|
||||||
return
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return res, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) Raw() *rawclient.Client {
|
func (x *multiClient) Raw() *rawclient.Client {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
objectGRPC "github.com/nspcc-dev/neofs-api-go/v2/object/grpc"
|
objectGRPC "github.com/nspcc-dev/neofs-api-go/v2/object/grpc"
|
||||||
objectSvc "github.com/nspcc-dev/neofs-node/pkg/services/object"
|
objectSvc "github.com/nspcc-dev/neofs-node/pkg/services/object"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/services/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server wraps NeoFS API Object service and
|
// Server wraps NeoFS API Object service and
|
||||||
|
@ -52,6 +53,15 @@ func (s *Server) Put(gStream objectGRPC.ObjectService_PutServer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := stream.Send(putReq); err != nil {
|
if err := stream.Send(putReq); err != nil {
|
||||||
|
if errors.Is(err, util.ErrAbortStream) {
|
||||||
|
resp, err := stream.CloseAndRecv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gStream.SendAndClose(resp.ToGRPCMessage().(*objectGRPC.PutResponse))
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@ func (s *signService) Balance(ctx context.Context, req *accounting.BalanceReques
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Balance(ctx, req.(*accounting.BalanceRequest))
|
return s.svc.Balance(ctx, req.(*accounting.BalanceRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(accounting.BalanceResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -26,6 +26,9 @@ func (s *signService) Put(ctx context.Context, req *container.PutRequest) (*cont
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Put(ctx, req.(*container.PutRequest))
|
return s.svc.Put(ctx, req.(*container.PutRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.PutResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -39,6 +42,9 @@ func (s *signService) Delete(ctx context.Context, req *container.DeleteRequest)
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Delete(ctx, req.(*container.DeleteRequest))
|
return s.svc.Delete(ctx, req.(*container.DeleteRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.DeleteResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -52,6 +58,9 @@ func (s *signService) Get(ctx context.Context, req *container.GetRequest) (*cont
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Get(ctx, req.(*container.GetRequest))
|
return s.svc.Get(ctx, req.(*container.GetRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.GetResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -65,6 +74,9 @@ func (s *signService) List(ctx context.Context, req *container.ListRequest) (*co
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.List(ctx, req.(*container.ListRequest))
|
return s.svc.List(ctx, req.(*container.ListRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.ListResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -78,6 +90,9 @@ func (s *signService) SetExtendedACL(ctx context.Context, req *container.SetExte
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.SetExtendedACL(ctx, req.(*container.SetExtendedACLRequest))
|
return s.svc.SetExtendedACL(ctx, req.(*container.SetExtendedACLRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.SetExtendedACLResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -91,6 +106,9 @@ func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExte
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.GetExtendedACL(ctx, req.(*container.GetExtendedACLRequest))
|
return s.svc.GetExtendedACL(ctx, req.(*container.GetExtendedACLRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.GetExtendedACLResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -104,6 +122,9 @@ func (s *signService) AnnounceUsedSpace(ctx context.Context, req *container.Anno
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.AnnounceUsedSpace(ctx, req.(*container.AnnounceUsedSpaceRequest))
|
return s.svc.AnnounceUsedSpace(ctx, req.(*container.AnnounceUsedSpaceRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(container.AnnounceUsedSpaceResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/grpc"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/grpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/message"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type requestWrapper struct {
|
type requestWrapper struct {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/grpc"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/grpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/message"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type requestWrapper struct {
|
type requestWrapper struct {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/common"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const serviceName = "ircontrol.ControlService"
|
const serviceName = "ircontrol.ControlService"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/util/proto"
|
"github.com/nspcc-dev/neofs-api-go/v2/util/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StableMarshal reads binary representation of health check request body
|
// StableMarshal reads binary representation of health check request body
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-api-go/rpc/common"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const serviceName = "control.ControlService"
|
const serviceName = "control.ControlService"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/util/proto"
|
"github.com/nspcc-dev/neofs-api-go/v2/util/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StableMarshal reads binary representation of health check request body
|
// StableMarshal reads binary representation of health check request body
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/util/proto"
|
"github.com/nspcc-dev/neofs-api-go/v2/util/proto"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ func (s *signService) LocalNodeInfo(
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.LocalNodeInfo(ctx, req.(*netmap.LocalNodeInfoRequest))
|
return s.svc.LocalNodeInfo(ctx, req.(*netmap.LocalNodeInfoRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(netmap.LocalNodeInfoResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -41,6 +44,9 @@ func (s *signService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRe
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.NetworkInfo(ctx, req.(*netmap.NetworkInfoRequest))
|
return s.svc.NetworkInfo(ctx, req.(*netmap.NetworkInfoRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(netmap.NetworkInfoResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -9,10 +9,10 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
rpcclient "github.com/nspcc-dev/neofs-api-go/rpc/client"
|
|
||||||
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
|
rpcclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/client"
|
"github.com/nspcc-dev/neofs-node/pkg/core/client"
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
session2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
session2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
|
@ -112,12 +113,12 @@ func (x *GetObjectPrm) SetAddress(addr *object.Address) {
|
||||||
|
|
||||||
// GetObjectRes groups resulting values of GetObject operation.
|
// GetObjectRes groups resulting values of GetObject operation.
|
||||||
type GetObjectRes struct {
|
type GetObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectGetRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object returns requested object.
|
// Object returns requested object.
|
||||||
func (x GetObjectRes) Object() *object.Object {
|
func (x GetObjectRes) Object() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObject reads the object by address.
|
// GetObject reads the object by address.
|
||||||
|
@ -130,6 +131,10 @@ func (x GetObjectRes) Object() *object.Object {
|
||||||
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
||||||
func GetObject(prm GetObjectPrm) (res GetObjectRes, err error) {
|
func GetObject(prm GetObjectPrm) (res GetObjectRes, err error) {
|
||||||
res.cliRes, err = prm.cli.GetObject(prm.ctx, &prm.cliPrm, prm.opts...)
|
res.cliRes, err = prm.cli.GetObject(prm.ctx, &prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: object.ErrAlreadyRemoved never returns
|
// FIXME: object.ErrAlreadyRemoved never returns
|
||||||
|
|
||||||
|
@ -159,12 +164,12 @@ func (x *HeadObjectPrm) SetAddress(addr *object.Address) {
|
||||||
|
|
||||||
// GetObjectRes groups resulting values of GetObject operation.
|
// GetObjectRes groups resulting values of GetObject operation.
|
||||||
type HeadObjectRes struct {
|
type HeadObjectRes struct {
|
||||||
cliRes *object.Object
|
cliRes *client.ObjectHeadRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns requested object header.
|
// Header returns requested object header.
|
||||||
func (x HeadObjectRes) Header() *object.Object {
|
func (x HeadObjectRes) Header() *object.Object {
|
||||||
return x.cliRes
|
return x.cliRes.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeadObject reads object header by address.
|
// HeadObject reads object header by address.
|
||||||
|
@ -176,7 +181,11 @@ func (x HeadObjectRes) Header() *object.Object {
|
||||||
// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual;
|
// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual;
|
||||||
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
||||||
func HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) {
|
func HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) {
|
||||||
res.cliRes, err = prm.cli.GetObjectHeader(prm.ctx, &prm.cliPrm, prm.opts...)
|
res.cliRes, err = prm.cli.HeadObject(prm.ctx, &prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: object.ErrAlreadyRemoved never returns
|
// FIXME: object.ErrAlreadyRemoved never returns
|
||||||
|
|
||||||
|
@ -213,12 +222,12 @@ func (x *PayloadRangePrm) SetRange(rng *object.Range) {
|
||||||
|
|
||||||
// PayloadRangeRes groups resulting values of GetObject operation.
|
// PayloadRangeRes groups resulting values of GetObject operation.
|
||||||
type PayloadRangeRes struct {
|
type PayloadRangeRes struct {
|
||||||
cliRes []byte
|
cliRes *client.ObjectRangeRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// PayloadRange returns data of the requested payload range.
|
// PayloadRange returns data of the requested payload range.
|
||||||
func (x PayloadRangeRes) PayloadRange() []byte {
|
func (x PayloadRangeRes) PayloadRange() []byte {
|
||||||
return x.cliRes
|
return x.cliRes.Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PayloadRange reads object payload range by address.
|
// PayloadRange reads object payload range by address.
|
||||||
|
@ -231,6 +240,10 @@ func (x PayloadRangeRes) PayloadRange() []byte {
|
||||||
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
// object.ErrAlreadyRemoved error if requested object is marked to be removed.
|
||||||
func PayloadRange(prm PayloadRangePrm) (res PayloadRangeRes, err error) {
|
func PayloadRange(prm PayloadRangePrm) (res PayloadRangeRes, err error) {
|
||||||
res.cliRes, err = prm.cli.ObjectPayloadRangeData(prm.ctx, &prm.cliPrm, prm.opts...)
|
res.cliRes, err = prm.cli.ObjectPayloadRangeData(prm.ctx, &prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: object.ErrAlreadyRemoved never returns
|
// FIXME: object.ErrAlreadyRemoved never returns
|
||||||
|
|
||||||
|
@ -253,12 +266,12 @@ func (x *PutObjectPrm) SetObject(obj *object.Object) {
|
||||||
|
|
||||||
// PutObjectRes groups resulting values of PutObject operation.
|
// PutObjectRes groups resulting values of PutObject operation.
|
||||||
type PutObjectRes struct {
|
type PutObjectRes struct {
|
||||||
cliRes *object.ID
|
cliRes *client.ObjectPutRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns identifier of the stored object.
|
// ID returns identifier of the stored object.
|
||||||
func (x PutObjectRes) ID() *object.ID {
|
func (x PutObjectRes) ID() *object.ID {
|
||||||
return x.cliRes
|
return x.cliRes.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObject saves the object in local storage of the remote node.
|
// PutObject saves the object in local storage of the remote node.
|
||||||
|
@ -270,6 +283,10 @@ func PutObject(prm PutObjectPrm) (res PutObjectRes, err error) {
|
||||||
res.cliRes, err = prm.cli.PutObject(prm.ctx, &prm.cliPrm,
|
res.cliRes, err = prm.cli.PutObject(prm.ctx, &prm.cliPrm,
|
||||||
append(prm.opts, client.WithTTL(1))...,
|
append(prm.opts, client.WithTTL(1))...,
|
||||||
)
|
)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -295,19 +312,23 @@ func (x *SearchObjectsPrm) SetFilters(fs object.SearchFilters) {
|
||||||
|
|
||||||
// SearchObjectsRes groups resulting values of SearchObjects operation.
|
// SearchObjectsRes groups resulting values of SearchObjects operation.
|
||||||
type SearchObjectsRes struct {
|
type SearchObjectsRes struct {
|
||||||
cliRes []*object.ID
|
cliRes *client.ObjectSearchRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDList returns identifiers of the matched objects.
|
// IDList returns identifiers of the matched objects.
|
||||||
func (x SearchObjectsRes) IDList() []*object.ID {
|
func (x SearchObjectsRes) IDList() []*object.ID {
|
||||||
return x.cliRes
|
return x.cliRes.IDList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchObjects selects objects from container which match the filters.
|
// SearchObjects selects objects from container which match the filters.
|
||||||
//
|
//
|
||||||
// Returns any error prevented the operation from completing correctly in error return.
|
// Returns any error prevented the operation from completing correctly in error return.
|
||||||
func SearchObjects(prm SearchObjectsPrm) (res SearchObjectsRes, err error) {
|
func SearchObjects(prm SearchObjectsPrm) (res SearchObjectsRes, err error) {
|
||||||
res.cliRes, err = prm.cli.SearchObject(prm.ctx, &prm.cliPrm, prm.opts...)
|
res.cliRes, err = prm.cli.SearchObjects(prm.ctx, &prm.cliPrm, prm.opts...)
|
||||||
|
if err == nil {
|
||||||
|
// pull out an error from status
|
||||||
|
err = apistatus.ErrFromStatus(res.cliRes.Status())
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
rpcclient "github.com/nspcc-dev/neofs-api-go/rpc/client"
|
|
||||||
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
|
rpcclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/client"
|
"github.com/nspcc-dev/neofs-node/pkg/core/client"
|
||||||
|
|
|
@ -21,6 +21,8 @@ type searchStreamSigner struct {
|
||||||
util.ServerStream
|
util.ServerStream
|
||||||
|
|
||||||
respWriter util.ResponseMessageWriter
|
respWriter util.ResponseMessageWriter
|
||||||
|
|
||||||
|
nonEmptyResp bool // set on first Send call
|
||||||
}
|
}
|
||||||
|
|
||||||
type getStreamSigner struct {
|
type getStreamSigner struct {
|
||||||
|
@ -52,19 +54,20 @@ func (s *getStreamSigner) Send(resp *object.GetResponse) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) Get(req *object.GetRequest, stream GetObjectStream) error {
|
func (s *SignService) Get(req *object.GetRequest, stream GetObjectStream) error {
|
||||||
respWriter, err := s.sigSvc.HandleServerStreamRequest(req,
|
return s.sigSvc.HandleServerStreamRequest(req,
|
||||||
func(resp util.ResponseMessage) error {
|
func(resp util.ResponseMessage) error {
|
||||||
return stream.Send(resp.(*object.GetResponse))
|
return stream.Send(resp.(*object.GetResponse))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.GetResponse)
|
||||||
|
},
|
||||||
|
func(respWriter util.ResponseMessageWriter) error {
|
||||||
|
return s.svc.Get(req, &getStreamSigner{
|
||||||
|
ServerStream: stream,
|
||||||
|
respWriter: respWriter,
|
||||||
|
})
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.svc.Get(req, &getStreamSigner{
|
|
||||||
ServerStream: stream,
|
|
||||||
respWriter: respWriter,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *putStreamSigner) Send(req *object.PutRequest) error {
|
func (s *putStreamSigner) Send(req *object.PutRequest) error {
|
||||||
|
@ -94,6 +97,9 @@ func (s *SignService) Put(ctx context.Context) (PutObjectStream, error) {
|
||||||
func() (util.ResponseMessage, error) {
|
func() (util.ResponseMessage, error) {
|
||||||
return stream.CloseAndRecv()
|
return stream.CloseAndRecv()
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.PutResponse)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -103,6 +109,9 @@ func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*objec
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Head(ctx, req.(*object.HeadRequest))
|
return s.svc.Head(ctx, req.(*object.HeadRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.HeadResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -112,23 +121,38 @@ func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*objec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *searchStreamSigner) Send(resp *object.SearchResponse) error {
|
func (s *searchStreamSigner) Send(resp *object.SearchResponse) error {
|
||||||
|
s.nonEmptyResp = true
|
||||||
return s.respWriter(resp)
|
return s.respWriter(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) Search(req *object.SearchRequest, stream SearchStream) error {
|
func (s *SignService) Search(req *object.SearchRequest, stream SearchStream) error {
|
||||||
respWriter, err := s.sigSvc.HandleServerStreamRequest(req,
|
return s.sigSvc.HandleServerStreamRequest(req,
|
||||||
func(resp util.ResponseMessage) error {
|
func(resp util.ResponseMessage) error {
|
||||||
return stream.Send(resp.(*object.SearchResponse))
|
return stream.Send(resp.(*object.SearchResponse))
|
||||||
},
|
},
|
||||||
)
|
func() util.ResponseMessage {
|
||||||
if err != nil {
|
return new(object.SearchResponse)
|
||||||
return err
|
},
|
||||||
}
|
func(respWriter util.ResponseMessageWriter) error {
|
||||||
|
stream := &searchStreamSigner{
|
||||||
|
ServerStream: stream,
|
||||||
|
respWriter: respWriter,
|
||||||
|
}
|
||||||
|
|
||||||
return s.svc.Search(req, &searchStreamSigner{
|
err := s.svc.Search(req, stream)
|
||||||
ServerStream: stream,
|
|
||||||
respWriter: respWriter,
|
if err == nil && !stream.nonEmptyResp {
|
||||||
})
|
// The higher component does not write any response in the case of an empty result (which is correct).
|
||||||
|
// With the introduction of status returns at least one answer must be signed and sent to the client.
|
||||||
|
// This approach is supported by clients who do not know how to work with statuses (one could make
|
||||||
|
// a switch according to the protocol version from the request, but the costs of sending an empty
|
||||||
|
// answer can be neglected due to the gradual refusal to use the "old" clients).
|
||||||
|
return stream.Send(new(object.SearchResponse))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) {
|
func (s *SignService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) {
|
||||||
|
@ -136,6 +160,9 @@ func (s *SignService) Delete(ctx context.Context, req *object.DeleteRequest) (*o
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Delete(ctx, req.(*object.DeleteRequest))
|
return s.svc.Delete(ctx, req.(*object.DeleteRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.DeleteResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -149,19 +176,20 @@ func (s *getRangeStreamSigner) Send(resp *object.GetRangeResponse) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error {
|
func (s *SignService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error {
|
||||||
respWriter, err := s.sigSvc.HandleServerStreamRequest(req,
|
return s.sigSvc.HandleServerStreamRequest(req,
|
||||||
func(resp util.ResponseMessage) error {
|
func(resp util.ResponseMessage) error {
|
||||||
return stream.Send(resp.(*object.GetRangeResponse))
|
return stream.Send(resp.(*object.GetRangeResponse))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.GetRangeResponse)
|
||||||
|
},
|
||||||
|
func(respWriter util.ResponseMessageWriter) error {
|
||||||
|
return s.svc.GetRange(req, &getRangeStreamSigner{
|
||||||
|
ServerStream: stream,
|
||||||
|
respWriter: respWriter,
|
||||||
|
})
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.svc.GetRange(req, &getRangeStreamSigner{
|
|
||||||
ServerStream: stream,
|
|
||||||
respWriter: respWriter,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) {
|
func (s *SignService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) {
|
||||||
|
@ -169,6 +197,9 @@ func (s *SignService) GetRangeHash(ctx context.Context, req *object.GetRangeHash
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.GetRangeHash(ctx, req.(*object.GetRangeHashRequest))
|
return s.svc.GetRangeHash(ctx, req.(*object.GetRangeHashRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(object.GetRangeHashResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -26,6 +26,9 @@ func (s *signService) AnnounceLocalTrust(ctx context.Context, req *reputation.An
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.AnnounceLocalTrust(ctx, req.(*reputation.AnnounceLocalTrustRequest))
|
return s.svc.AnnounceLocalTrust(ctx, req.(*reputation.AnnounceLocalTrustRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(reputation.AnnounceLocalTrustResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -39,6 +42,9 @@ func (s *signService) AnnounceIntermediateResult(ctx context.Context, req *reput
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.AnnounceIntermediateResult(ctx, req.(*reputation.AnnounceIntermediateResultRequest))
|
return s.svc.AnnounceIntermediateResult(ctx, req.(*reputation.AnnounceIntermediateResultRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(reputation.AnnounceIntermediateResultResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -26,6 +26,9 @@ func (s *signService) Create(ctx context.Context, req *session.CreateRequest) (*
|
||||||
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
func(ctx context.Context, req interface{}) (util.ResponseMessage, error) {
|
||||||
return s.svc.Create(ctx, req.(*session.CreateRequest))
|
return s.svc.Create(ctx, req.(*session.CreateRequest))
|
||||||
},
|
},
|
||||||
|
func() util.ResponseMessage {
|
||||||
|
return new(session.CreateResponse)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -3,12 +3,18 @@ package util
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RequestMessage interface {
|
||||||
|
GetMetaHeader() *session.RequestMetaHeader
|
||||||
|
}
|
||||||
|
|
||||||
// ResponseMessage is an interface of NeoFS response message.
|
// ResponseMessage is an interface of NeoFS response message.
|
||||||
type ResponseMessage interface {
|
type ResponseMessage interface {
|
||||||
GetMetaHeader() *session.ResponseMetaHeader
|
GetMetaHeader() *session.ResponseMetaHeader
|
||||||
|
@ -27,11 +33,9 @@ type ServerStreamHandler func(context.Context, interface{}) (ResponseMessageRead
|
||||||
|
|
||||||
type ResponseMessageReader func() (ResponseMessage, error)
|
type ResponseMessageReader func() (ResponseMessage, error)
|
||||||
|
|
||||||
type ResponseMessageStreamer struct {
|
var ErrAbortStream = errors.New("abort message stream")
|
||||||
key *ecdsa.PrivateKey
|
|
||||||
|
|
||||||
recv ResponseMessageReader
|
type ResponseConstructor func() ResponseMessage
|
||||||
}
|
|
||||||
|
|
||||||
type RequestMessageWriter func(interface{}) error
|
type RequestMessageWriter func(interface{}) error
|
||||||
|
|
||||||
|
@ -43,6 +47,12 @@ type RequestMessageStreamer struct {
|
||||||
send RequestMessageWriter
|
send RequestMessageWriter
|
||||||
|
|
||||||
close ClientStreamCloser
|
close ClientStreamCloser
|
||||||
|
|
||||||
|
respCons ResponseConstructor
|
||||||
|
|
||||||
|
statusSupported bool
|
||||||
|
|
||||||
|
sendErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUnarySignService(key *ecdsa.PrivateKey) *SignService {
|
func NewUnarySignService(key *ecdsa.PrivateKey) *SignService {
|
||||||
|
@ -52,79 +62,192 @@ func NewUnarySignService(key *ecdsa.PrivateKey) *SignService {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RequestMessageStreamer) Send(req interface{}) error {
|
func (s *RequestMessageStreamer) Send(req interface{}) error {
|
||||||
|
// req argument should be strengthen with type RequestMessage
|
||||||
|
s.statusSupported = isStatusSupported(req.(RequestMessage)) // panic is OK here for now
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
// verify request signatures
|
// verify request signatures
|
||||||
if err := signature.VerifyServiceMessage(req); err != nil {
|
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||||
return fmt.Errorf("could not verify request: %w", err)
|
err = fmt.Errorf("could not verify request: %w", err)
|
||||||
|
} else {
|
||||||
|
err = s.send(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.send(req)
|
if err != nil {
|
||||||
|
if !s.statusSupported {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sendErr = err
|
||||||
|
|
||||||
|
return ErrAbortStream
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RequestMessageStreamer) CloseAndRecv() (ResponseMessage, error) {
|
func (s *RequestMessageStreamer) CloseAndRecv() (ResponseMessage, error) {
|
||||||
resp, err := s.close()
|
var (
|
||||||
if err != nil {
|
resp ResponseMessage
|
||||||
return nil, fmt.Errorf("could not close stream and receive response: %w", err)
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if s.sendErr != nil {
|
||||||
|
err = s.sendErr
|
||||||
|
} else {
|
||||||
|
resp, err = s.close()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("could not close stream and receive response: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := signature.SignServiceMessage(s.key, resp); err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not sign response: %w", err)
|
if !s.statusSupported {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var st apistatus.ServerInternal // specific API status should be set according to error
|
||||||
|
|
||||||
|
apistatus.WriteInternalServerErr(&st, err)
|
||||||
|
|
||||||
|
resp = s.respCons()
|
||||||
|
|
||||||
|
setStatusV2(resp, st)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = signResponse(s.key, resp, s.statusSupported); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignService) CreateRequestStreamer(sender RequestMessageWriter, closer ClientStreamCloser) *RequestMessageStreamer {
|
func (s *SignService) CreateRequestStreamer(sender RequestMessageWriter, closer ClientStreamCloser, blankResp ResponseConstructor) *RequestMessageStreamer {
|
||||||
return &RequestMessageStreamer{
|
return &RequestMessageStreamer{
|
||||||
key: s.key,
|
key: s.key,
|
||||||
send: sender,
|
send: sender,
|
||||||
close: closer,
|
close: closer,
|
||||||
|
|
||||||
|
respCons: blankResp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ResponseMessageStreamer) Recv() (ResponseMessage, error) {
|
func (s *SignService) HandleServerStreamRequest(
|
||||||
m, err := s.recv()
|
req interface{},
|
||||||
if err != nil {
|
respWriter ResponseMessageWriter,
|
||||||
return nil, fmt.Errorf("could not receive response message for signing: %w", err)
|
blankResp ResponseConstructor,
|
||||||
}
|
respWriterCaller func(ResponseMessageWriter) error,
|
||||||
|
) error {
|
||||||
|
// handle protocol versions <=2.10 (API statuses was introduced in 2.11 only)
|
||||||
|
|
||||||
if err := signature.SignServiceMessage(s.key, m); err != nil {
|
// req argument should be strengthen with type RequestMessage
|
||||||
return nil, fmt.Errorf("could not sign response message: %w", err)
|
statusSupported := isStatusSupported(req.(RequestMessage)) // panic is OK here for now
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
var err error
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignService) HandleServerStreamRequest(req interface{}, respWriter ResponseMessageWriter) (ResponseMessageWriter, error) {
|
|
||||||
// verify request signatures
|
// verify request signatures
|
||||||
if err := signature.VerifyServiceMessage(req); err != nil {
|
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||||
return nil, fmt.Errorf("could not verify request: %w", err)
|
err = fmt.Errorf("could not verify request: %w", err)
|
||||||
|
} else {
|
||||||
|
err = respWriterCaller(func(resp ResponseMessage) error {
|
||||||
|
if err := signResponse(s.key, resp, statusSupported); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return respWriter(resp)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(resp ResponseMessage) error {
|
if err != nil {
|
||||||
if err := signature.SignServiceMessage(s.key, resp); err != nil {
|
if !statusSupported {
|
||||||
return fmt.Errorf("could not sign response message: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return respWriter(resp)
|
var st apistatus.ServerInternal // specific API status should be set according to error
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignService) HandleUnaryRequest(ctx context.Context, req interface{}, handler UnaryHandler) (ResponseMessage, error) {
|
apistatus.WriteInternalServerErr(&st, err)
|
||||||
// verify request signatures
|
|
||||||
if err := signature.VerifyServiceMessage(req); err != nil {
|
resp := blankResp()
|
||||||
return nil, fmt.Errorf("could not verify request: %w", err)
|
|
||||||
|
setStatusV2(resp, st)
|
||||||
|
|
||||||
|
_ = signResponse(s.key, resp, false) // panics or returns nil with false arg
|
||||||
|
|
||||||
|
return respWriter(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignService) HandleUnaryRequest(ctx context.Context, req interface{}, handler UnaryHandler, blankResp ResponseConstructor) (ResponseMessage, error) {
|
||||||
|
// handle protocol versions <=2.10 (API statuses was introduced in 2.11 only)
|
||||||
|
|
||||||
|
// req argument should be strengthen with type RequestMessage
|
||||||
|
statusSupported := isStatusSupported(req.(RequestMessage)) // panic is OK here for now
|
||||||
|
|
||||||
|
var (
|
||||||
|
resp ResponseMessage
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
// verify request signatures
|
||||||
|
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||||
|
err = fmt.Errorf("could not verify request: %w", err)
|
||||||
|
} else {
|
||||||
|
// process request
|
||||||
|
resp, err = handler(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// process request
|
|
||||||
resp, err := handler(ctx, req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not handle request: %w", err)
|
if !statusSupported {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var st apistatus.ServerInternal // specific API status should be set according to error
|
||||||
|
|
||||||
|
apistatus.WriteInternalServerErr(&st, err)
|
||||||
|
|
||||||
|
resp = blankResp()
|
||||||
|
|
||||||
|
setStatusV2(resp, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign the response
|
// sign the response
|
||||||
if err := signature.SignServiceMessage(s.key, resp); err != nil {
|
if err = signResponse(s.key, resp, statusSupported); err != nil {
|
||||||
return nil, fmt.Errorf("could not sign response: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStatusSupported(req RequestMessage) bool {
|
||||||
|
version := req.GetMetaHeader().GetVersion()
|
||||||
|
|
||||||
|
mjr := version.GetMajor()
|
||||||
|
|
||||||
|
return mjr > 2 || mjr == 2 && version.GetMinor() >= 11
|
||||||
|
}
|
||||||
|
|
||||||
|
func setStatusV2(resp ResponseMessage, st apistatus.Status) {
|
||||||
|
session.SetStatus(resp, apistatus.ToStatusV2(st))
|
||||||
|
}
|
||||||
|
|
||||||
|
// signs response with private key via signature.SignServiceMessage.
|
||||||
|
// The signature error affects the result depending on the protocol version:
|
||||||
|
// * if status return is supported, panics since we cannot return the failed status, because it will not be signed;
|
||||||
|
// * otherwise, returns error in order to transport it directly.
|
||||||
|
func signResponse(key *ecdsa.PrivateKey, resp interface{}, statusSupported bool) error {
|
||||||
|
err := signature.SignServiceMessage(key, resp)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("could not sign response: %w", err)
|
||||||
|
|
||||||
|
if statusSupported {
|
||||||
|
// We can't pass this error as status code since response will be unsigned.
|
||||||
|
// Isn't expected in practice, so panic is ok here.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue