forked from TrueCloudLab/frostfs-sdk-go
commit
cfdd870755
32 changed files with 589 additions and 821 deletions
|
@ -42,7 +42,6 @@ Contains client for working with NeoFS.
|
||||||
```go
|
```go
|
||||||
var prmInit client.PrmInit
|
var prmInit client.PrmInit
|
||||||
prmInit.SetDefaultPrivateKey(key) // private key for request signing
|
prmInit.SetDefaultPrivateKey(key) // private key for request signing
|
||||||
prmInit.ResolveNeoFSFailures() // enable erroneous status parsing
|
|
||||||
|
|
||||||
var c client.Client
|
var c client.Client
|
||||||
c.Init(prmInit)
|
c.Init(prmInit)
|
||||||
|
@ -77,8 +76,7 @@ if needed and perform any desired action. In the case above we may want to repor
|
||||||
these details to the user as well as retry an operation, possibly with different parameters.
|
these details to the user as well as retry an operation, possibly with different parameters.
|
||||||
Status wire-format is extendable and each node can report any set of details it wants.
|
Status wire-format is extendable and each node can report any set of details it wants.
|
||||||
The set of reserved status codes can be found in
|
The set of reserved status codes can be found in
|
||||||
[NeoFS API](https://github.com/nspcc-dev/neofs-api/blob/master/status/types.proto). There is also
|
[NeoFS API](https://github.com/nspcc-dev/neofs-api/blob/master/status/types.proto).
|
||||||
a `client.PrmInit.ResolveNeoFSFailures()` to seamlessly convert erroneous statuses into Go error type.
|
|
||||||
|
|
||||||
### policy
|
### policy
|
||||||
Contains helpers allowing conversion of placing policy from/to JSON representation
|
Contains helpers allowing conversion of placing policy from/to JSON representation
|
||||||
|
|
|
@ -28,8 +28,6 @@ func (x *PrmBalanceGet) SetAccount(id user.ID) {
|
||||||
|
|
||||||
// ResBalanceGet groups resulting values of BalanceGet operation.
|
// ResBalanceGet groups resulting values of BalanceGet operation.
|
||||||
type ResBalanceGet struct {
|
type ResBalanceGet struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
amount accounting.Decimal
|
amount accounting.Decimal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,17 +38,11 @@ func (x ResBalanceGet) Amount() accounting.Decimal {
|
||||||
|
|
||||||
// BalanceGet requests current balance of the NeoFS account.
|
// BalanceGet requests current balance of the NeoFS account.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`,
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmBalanceGet docs).
|
// Immediately panics if parameters are set incorrectly (see PrmBalanceGet docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) {
|
func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) {
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -81,7 +73,6 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.Balance(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.Balance(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,6 @@ func (c *Client) Close() error {
|
||||||
//
|
//
|
||||||
// See also Init.
|
// See also Init.
|
||||||
type PrmInit struct {
|
type PrmInit struct {
|
||||||
resolveNeoFSErrors bool
|
|
||||||
|
|
||||||
signer neofscrypto.Signer
|
signer neofscrypto.Signer
|
||||||
|
|
||||||
cbRespInfo func(ResponseMetaInfo) error
|
cbRespInfo func(ResponseMetaInfo) error
|
||||||
|
@ -162,14 +160,6 @@ func (x *PrmInit) SetDefaultSigner(signer neofscrypto.Signer) {
|
||||||
x.signer = signer
|
x.signer = signer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveNeoFSFailures makes the Client to resolve failure statuses of the
|
|
||||||
// NeoFS protocol into Go built-in errors. These errors are returned from
|
|
||||||
// each protocol operation. By default, statuses aren't resolved and written
|
|
||||||
// to the resulting structure (see corresponding Res* docs).
|
|
||||||
func (x *PrmInit) ResolveNeoFSFailures() {
|
|
||||||
x.resolveNeoFSErrors = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetResponseInfoCallback makes the Client to pass ResponseMetaInfo from each
|
// SetResponseInfoCallback makes the Client to pass ResponseMetaInfo from each
|
||||||
// NeoFS server response to f. Nil (default) means ignore response meta info.
|
// NeoFS server response to f. Nil (default) means ignore response meta info.
|
||||||
func (x *PrmInit) SetResponseInfoCallback(f func(ResponseMetaInfo) error) {
|
func (x *PrmInit) SetResponseInfoCallback(f func(ResponseMetaInfo) error) {
|
||||||
|
|
|
@ -19,11 +19,6 @@ func init() {
|
||||||
statusErr.SetMessage("test status error")
|
statusErr.SetMessage("test status error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertStatusErr(tb testing.TB, res interface{ Status() apistatus.Status }) {
|
|
||||||
require.IsType(tb, &statusErr, res.Status())
|
|
||||||
require.Equal(tb, statusErr.Message(), res.Status().(*apistatus.ServerInternal).Message())
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClient(signer neofscrypto.Signer, server neoFSAPIServer) *Client {
|
func newClient(signer neofscrypto.Signer, server neoFSAPIServer) *Client {
|
||||||
var prm PrmInit
|
var prm PrmInit
|
||||||
prm.SetDefaultSigner(signer)
|
prm.SetDefaultSigner(signer)
|
||||||
|
|
|
@ -11,28 +11,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/version"
|
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// common interface of resulting structures with API status.
|
|
||||||
type resCommon interface {
|
|
||||||
setStatus(apistatus.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// structure is embedded to all resulting types in order to inherit status-related methods.
|
|
||||||
type statusRes struct {
|
|
||||||
st apistatus.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
// setStatus implements resCommon interface method.
|
|
||||||
func (x *statusRes) setStatus(st apistatus.Status) {
|
|
||||||
x.st = st
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status returns server's status return.
|
|
||||||
//
|
|
||||||
// Use apistatus package functionality to handle the status.
|
|
||||||
func (x statusRes) Status() apistatus.Status {
|
|
||||||
return x.st
|
|
||||||
}
|
|
||||||
|
|
||||||
// groups meta parameters shared between all Client operations.
|
// groups meta parameters shared between all Client operations.
|
||||||
type prmCommonMeta struct {
|
type prmCommonMeta struct {
|
||||||
// NeoFS request X-Headers
|
// NeoFS request X-Headers
|
||||||
|
@ -97,9 +75,6 @@ type contextCall struct {
|
||||||
// callback prior to processing the response by the client
|
// callback prior to processing the response by the client
|
||||||
callbackResp func(ResponseMetaInfo) error
|
callbackResp func(ResponseMetaInfo) error
|
||||||
|
|
||||||
// if set, protocol errors will be expanded into a final error
|
|
||||||
resolveAPIFailures bool
|
|
||||||
|
|
||||||
// NeoFS network magic
|
// NeoFS network magic
|
||||||
netMagic uint64
|
netMagic uint64
|
||||||
|
|
||||||
|
@ -109,9 +84,6 @@ type contextCall struct {
|
||||||
// ==================================================
|
// ==================================================
|
||||||
// custom call parameters
|
// custom call parameters
|
||||||
|
|
||||||
// structure of the call result
|
|
||||||
statusRes resCommon
|
|
||||||
|
|
||||||
// request to be signed with a signer and sent
|
// request to be signed with a signer and sent
|
||||||
req request
|
req request
|
||||||
|
|
||||||
|
@ -235,20 +207,13 @@ func (x *contextCall) processResponse() bool {
|
||||||
// get result status
|
// get result status
|
||||||
st := apistatus.FromStatusV2(x.resp.GetMetaHeader().GetStatus())
|
st := apistatus.FromStatusV2(x.resp.GetMetaHeader().GetStatus())
|
||||||
|
|
||||||
// unwrap unsuccessful status and return it
|
|
||||||
// as error if client has been configured so
|
|
||||||
successfulStatus := apistatus.IsSuccessful(st)
|
successfulStatus := apistatus.IsSuccessful(st)
|
||||||
|
x.err = apistatus.ErrFromStatus(st)
|
||||||
if x.resolveAPIFailures {
|
|
||||||
x.err = apistatus.ErrFromStatus(st)
|
|
||||||
} else {
|
|
||||||
x.statusRes.setStatus(st)
|
|
||||||
}
|
|
||||||
|
|
||||||
return successfulStatus
|
return successfulStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// processResponse verifies response signature and converts status to an error if needed.
|
// processResponse verifies response signature.
|
||||||
func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
|
func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
|
||||||
err := verifyServiceMessage(resp)
|
err := verifyServiceMessage(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -256,14 +221,11 @@ func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
|
st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
|
||||||
if c.prm.resolveNeoFSErrors {
|
return st, apistatus.ErrFromStatus(st)
|
||||||
return st, apistatus.ErrFromStatus(st)
|
|
||||||
}
|
|
||||||
return st, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads response (if rResp is set) and processes it. Result means success.
|
// reads response (if rResp is set) and processes it. Result means success.
|
||||||
// If failed, contextCall.err (or statusRes if resolveAPIFailures is set) contains the reason.
|
// If failed, contextCall.err contains the reason.
|
||||||
func (x *contextCall) readResponse() bool {
|
func (x *contextCall) readResponse() bool {
|
||||||
if x.rResp != nil {
|
if x.rResp != nil {
|
||||||
x.err = x.rResp()
|
x.err = x.rResp()
|
||||||
|
@ -329,7 +291,6 @@ func (x *contextCall) processCall() bool {
|
||||||
// initializes static cross-call parameters inherited from client.
|
// initializes static cross-call parameters inherited from client.
|
||||||
func (c *Client) initCallContext(ctx *contextCall) {
|
func (c *Client) initCallContext(ctx *contextCall) {
|
||||||
ctx.signer = c.prm.signer
|
ctx.signer = c.prm.signer
|
||||||
ctx.resolveAPIFailures = c.prm.resolveNeoFSErrors
|
|
||||||
ctx.callbackResp = c.prm.cbRespInfo
|
ctx.callbackResp = c.prm.cbRespInfo
|
||||||
ctx.netMagic = c.prm.netMagic
|
ctx.netMagic = c.prm.netMagic
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,6 @@ func (x *PrmContainerPut) WithinSession(s session.Container) {
|
||||||
|
|
||||||
// ResContainerPut groups resulting values of ContainerPut operation.
|
// ResContainerPut groups resulting values of ContainerPut operation.
|
||||||
type ResContainerPut struct {
|
type ResContainerPut struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
id cid.ID
|
id cid.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,11 +76,8 @@ func (c *Client) defaultSigner() neofscrypto.Signer {
|
||||||
|
|
||||||
// ContainerPut sends request to save container in NeoFS.
|
// ContainerPut sends request to save container in NeoFS.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -91,9 +86,6 @@ func (c *Client) defaultSigner() neofscrypto.Signer {
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerPut docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerPut docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) {
|
func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) {
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
|
@ -154,7 +146,6 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.PutContainer(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.PutContainer(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -200,8 +191,6 @@ func (x *PrmContainerGet) SetContainer(id cid.ID) {
|
||||||
|
|
||||||
// ResContainerGet groups resulting values of ContainerGet operation.
|
// ResContainerGet groups resulting values of ContainerGet operation.
|
||||||
type ResContainerGet struct {
|
type ResContainerGet struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
cnr container.Container
|
cnr container.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,18 +203,11 @@ func (x ResContainerGet) Container() container.Container {
|
||||||
|
|
||||||
// ContainerGet reads NeoFS container by ID.
|
// ContainerGet reads NeoFS container by ID.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerGet docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerGet docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
|
||||||
// - *apistatus.ContainerNotFound.
|
|
||||||
func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) {
|
func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) {
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -256,7 +238,6 @@ func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResCon
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.GetContainer(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.GetContainer(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -300,8 +281,6 @@ func (x *PrmContainerList) SetAccount(id user.ID) {
|
||||||
|
|
||||||
// ResContainerList groups resulting values of ContainerList operation.
|
// ResContainerList groups resulting values of ContainerList operation.
|
||||||
type ResContainerList struct {
|
type ResContainerList struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
ids []cid.ID
|
ids []cid.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,17 +293,11 @@ func (x ResContainerList) Containers() []cid.ID {
|
||||||
|
|
||||||
// ContainerList requests identifiers of the account-owned containers.
|
// ContainerList requests identifiers of the account-owned containers.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerList docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerList docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) {
|
func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) {
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
|
@ -356,7 +329,6 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.ListContainers(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.ListContainers(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -420,18 +392,10 @@ func (x *PrmContainerDelete) WithinSession(tok session.Container) {
|
||||||
x.tokSet = true
|
x.tokSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResContainerDelete groups resulting values of ContainerDelete operation.
|
|
||||||
type ResContainerDelete struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerDelete sends request to remove the NeoFS container.
|
// ContainerDelete sends request to remove the NeoFS container.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -441,12 +405,8 @@ type ResContainerDelete struct {
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerDelete docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerDelete docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. Server status return is returned in ResContainerDelete.
|
|
||||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||||
//
|
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) error {
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*ResContainerDelete, error) {
|
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -471,7 +431,7 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
|
||||||
|
|
||||||
err := sig.Calculate(signer, data)
|
err := sig.Calculate(signer, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
return fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sigv2 refs.Signature
|
var sigv2 refs.Signature
|
||||||
|
@ -503,23 +463,21 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
|
||||||
// init call context
|
// init call context
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cc contextCall
|
cc contextCall
|
||||||
res ResContainerDelete
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.DeleteContainer(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.DeleteContainer(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
if !cc.processCall() {
|
if !cc.processCall() {
|
||||||
return nil, cc.err
|
return cc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrmContainerEACL groups parameters of ContainerEACL operation.
|
// PrmContainerEACL groups parameters of ContainerEACL operation.
|
||||||
|
@ -539,8 +497,6 @@ func (x *PrmContainerEACL) SetContainer(id cid.ID) {
|
||||||
|
|
||||||
// ResContainerEACL groups resulting values of ContainerEACL operation.
|
// ResContainerEACL groups resulting values of ContainerEACL operation.
|
||||||
type ResContainerEACL struct {
|
type ResContainerEACL struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
table eacl.Table
|
table eacl.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,19 +507,11 @@ func (x ResContainerEACL) Table() eacl.Table {
|
||||||
|
|
||||||
// ContainerEACL reads eACL table of the NeoFS container.
|
// ContainerEACL reads eACL table of the NeoFS container.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerEACL docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerEACL docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
|
||||||
// - *apistatus.ContainerNotFound;
|
|
||||||
// - *apistatus.EACLNotFound.
|
|
||||||
func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) {
|
func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) {
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
|
@ -595,7 +543,6 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.GetEACL(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.GetEACL(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -662,18 +609,10 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
|
||||||
x.sessionSet = true
|
x.sessionSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResContainerSetEACL groups resulting values of ContainerSetEACL operation.
|
|
||||||
type ResContainerSetEACL struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerSetEACL sends request to update eACL table of the NeoFS container.
|
// ContainerSetEACL sends request to update eACL table of the NeoFS container.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -682,10 +621,7 @@ type ResContainerSetEACL struct {
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
|
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) (*ResContainerSetEACL, error) {
|
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -710,7 +646,7 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
|
||||||
|
|
||||||
err := sig.Calculate(signer, eaclV2.StableMarshal(nil))
|
err := sig.Calculate(signer, eaclV2.StableMarshal(nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
return fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sigv2 refs.Signature
|
var sigv2 refs.Signature
|
||||||
|
@ -742,23 +678,21 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
|
||||||
// init call context
|
// init call context
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cc contextCall
|
cc contextCall
|
||||||
res ResContainerSetEACL
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.SetEACL(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.SetEACL(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
if !cc.processCall() {
|
if !cc.processCall() {
|
||||||
return nil, cc.err
|
return cc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrmAnnounceSpace groups parameters of ContainerAnnounceUsedSpace operation.
|
// PrmAnnounceSpace groups parameters of ContainerAnnounceUsedSpace operation.
|
||||||
|
@ -776,18 +710,10 @@ func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) {
|
||||||
x.announcements = vs
|
x.announcements = vs
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResAnnounceSpace groups resulting values of ContainerAnnounceUsedSpace operation.
|
|
||||||
type ResAnnounceSpace struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerAnnounceUsedSpace sends request to announce volume of the space used for the container objects.
|
// ContainerAnnounceUsedSpace sends request to announce volume of the space used for the container objects.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -796,10 +722,7 @@ type ResAnnounceSpace struct {
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceSpace docs).
|
// Immediately panics if parameters are set incorrectly (see PrmAnnounceSpace docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) error {
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) (*ResAnnounceSpace, error) {
|
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -826,24 +749,22 @@ func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounce
|
||||||
// init call context
|
// init call context
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cc contextCall
|
cc contextCall
|
||||||
res ResAnnounceSpace
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.AnnounceUsedSpace(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.AnnounceUsedSpace(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
if !cc.processCall() {
|
if !cc.processCall() {
|
||||||
return nil, cc.err
|
return cc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncContainerWithNetwork requests network configuration using passed client
|
// SyncContainerWithNetwork requests network configuration using passed client
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
package client_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestErrors(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
errs []error
|
|
||||||
errVariable error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
errs: []error{
|
|
||||||
apistatus.ContainerNotFound{},
|
|
||||||
new(apistatus.ContainerNotFound),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrContainerNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errs: []error{
|
|
||||||
apistatus.EACLNotFound{},
|
|
||||||
new(apistatus.EACLNotFound),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrEACLNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errs: []error{
|
|
||||||
apistatus.ObjectNotFound{},
|
|
||||||
new(apistatus.ObjectNotFound),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrObjectNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errs: []error{
|
|
||||||
apistatus.ObjectAlreadyRemoved{},
|
|
||||||
new(apistatus.ObjectAlreadyRemoved),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrObjectAlreadyRemoved,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errs: []error{
|
|
||||||
apistatus.SessionTokenExpired{},
|
|
||||||
new(apistatus.SessionTokenExpired),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrSessionTokenExpired,
|
|
||||||
}, {
|
|
||||||
errs: []error{
|
|
||||||
apistatus.SessionTokenNotFound{},
|
|
||||||
new(apistatus.SessionTokenNotFound),
|
|
||||||
},
|
|
||||||
errVariable: apistatus.ErrSessionTokenNotFound,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
require.NotEmpty(t, tc.errs)
|
|
||||||
require.NotNil(t, tc.errVariable)
|
|
||||||
|
|
||||||
for i := range tc.errs {
|
|
||||||
require.ErrorIs(t, tc.errs[i], tc.errVariable)
|
|
||||||
|
|
||||||
wrapped := fmt.Errorf("some message %w", tc.errs[i])
|
|
||||||
require.ErrorIs(t, wrapped, tc.errVariable)
|
|
||||||
|
|
||||||
wrappedTwice := fmt.Errorf("another message %w", wrapped)
|
|
||||||
require.ErrorIs(t, wrappedTwice, tc.errVariable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,7 +36,6 @@ func ExampleClient_ContainerPut() {
|
||||||
// prepare client
|
// prepare client
|
||||||
var prmInit client.PrmInit
|
var prmInit client.PrmInit
|
||||||
prmInit.SetDefaultSigner(signer) // private signer for request signing
|
prmInit.SetDefaultSigner(signer) // private signer for request signing
|
||||||
prmInit.ResolveNeoFSFailures() // enable erroneous status parsing
|
|
||||||
|
|
||||||
var c client.Client
|
var c client.Client
|
||||||
c.Init(prmInit)
|
c.Init(prmInit)
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/version"
|
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||||
)
|
)
|
||||||
|
@ -20,8 +19,6 @@ type PrmEndpointInfo struct {
|
||||||
|
|
||||||
// ResEndpointInfo group resulting values of EndpointInfo operation.
|
// ResEndpointInfo group resulting values of EndpointInfo operation.
|
||||||
type ResEndpointInfo struct {
|
type ResEndpointInfo struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
version version.Version
|
version version.Version
|
||||||
|
|
||||||
ni netmap.NodeInfo
|
ni netmap.NodeInfo
|
||||||
|
@ -41,19 +38,14 @@ func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo {
|
||||||
//
|
//
|
||||||
// Method can be used as a health check to see if node is alive and responds to requests.
|
// Method can be used as a health check to see if node is alive and responds to requests.
|
||||||
//
|
//
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmEndpointInfo docs).
|
// Immediately panics if parameters are set incorrectly (see PrmEndpointInfo docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo.
|
// Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo.
|
||||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) {
|
func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) {
|
||||||
// check context
|
// check context
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
|
@ -73,7 +65,6 @@ func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEnd
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.LocalNodeInfo(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.LocalNodeInfo(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -126,8 +117,6 @@ type PrmNetworkInfo struct {
|
||||||
|
|
||||||
// ResNetworkInfo groups resulting values of NetworkInfo operation.
|
// ResNetworkInfo groups resulting values of NetworkInfo operation.
|
||||||
type ResNetworkInfo struct {
|
type ResNetworkInfo struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
info netmap.NetworkInfo
|
info netmap.NetworkInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,19 +127,14 @@ func (x ResNetworkInfo) Info() netmap.NetworkInfo {
|
||||||
|
|
||||||
// NetworkInfo requests information about the NeoFS network of which the remote server is a part.
|
// NetworkInfo requests information about the NeoFS network of which the remote server is a part.
|
||||||
//
|
//
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmNetworkInfo docs).
|
// Immediately panics if parameters are set incorrectly (see PrmNetworkInfo docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo.
|
// Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo.
|
||||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) {
|
func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) {
|
||||||
// check context
|
// check context
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
|
@ -170,7 +154,6 @@ func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetwo
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.NetworkInfo(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.NetworkInfo(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
@ -206,8 +189,6 @@ type PrmNetMapSnapshot struct {
|
||||||
|
|
||||||
// ResNetMapSnapshot groups resulting values of NetMapSnapshot operation.
|
// ResNetMapSnapshot groups resulting values of NetMapSnapshot operation.
|
||||||
type ResNetMapSnapshot struct {
|
type ResNetMapSnapshot struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
netMap netmap.NetMap
|
netMap netmap.NetMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,18 +199,13 @@ func (x ResNetMapSnapshot) NetMap() netmap.NetMap {
|
||||||
|
|
||||||
// NetMapSnapshot requests current network view of the remote server.
|
// NetMapSnapshot requests current network view of the remote server.
|
||||||
//
|
//
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Context is required and MUST NOT be nil. It is used for network communication.
|
// Context is required and MUST NOT be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot.
|
// Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot.
|
||||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) {
|
func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) {
|
||||||
// check context
|
// check context
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
|
@ -258,15 +234,11 @@ func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResN
|
||||||
}
|
}
|
||||||
|
|
||||||
var res ResNetMapSnapshot
|
var res ResNetMapSnapshot
|
||||||
res.st, err = c.processResponse(resp)
|
_, err = c.processResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apistatus.IsSuccessful(res.st) {
|
|
||||||
return &res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const fieldNetMap = "network map"
|
const fieldNetMap = "network map"
|
||||||
|
|
||||||
netMapV2 := resp.GetBody().NetMap()
|
netMapV2 := resp.GetBody().NetMap()
|
||||||
|
|
|
@ -102,10 +102,10 @@ func TestClient_NetMapSnapshot(t *testing.T) {
|
||||||
|
|
||||||
srv.signResponse = true
|
srv.signResponse = true
|
||||||
|
|
||||||
// status failure
|
// failure error
|
||||||
res, err = c.NetMapSnapshot(ctx, prm)
|
_, err = c.NetMapSnapshot(ctx, prm)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
assertStatusErr(t, res)
|
require.ErrorIs(t, err, apistatus.ErrServerInternal)
|
||||||
|
|
||||||
srv.statusOK = true
|
srv.statusOK = true
|
||||||
|
|
||||||
|
@ -145,6 +145,5 @@ func TestClient_NetMapSnapshot(t *testing.T) {
|
||||||
|
|
||||||
res, err = c.NetMapSnapshot(ctx, prm)
|
res, err = c.NetMapSnapshot(ctx, prm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, apistatus.IsSuccessful(res.Status()))
|
|
||||||
require.Equal(t, netMap, res.NetMap())
|
require.Equal(t, netMap, res.NetMap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
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"
|
||||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
@ -95,8 +94,6 @@ func (x *PrmObjectDelete) WithXHeaders(hs ...string) {
|
||||||
|
|
||||||
// ResObjectDelete groups resulting values of ObjectDelete operation.
|
// ResObjectDelete groups resulting values of ObjectDelete operation.
|
||||||
type ResObjectDelete struct {
|
type ResObjectDelete struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
tomb oid.ID
|
tomb oid.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,19 +112,17 @@ func (x ResObjectDelete) Tombstone() oid.ID {
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
||||||
// Any client's internal or transport errors are returned as `error`,
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmObjectDelete docs).
|
// Immediately panics if parameters are set incorrectly (see PrmObjectDelete docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Return statuses:
|
// Return errors:
|
||||||
// - global (see Client docs)
|
// - global (see Client docs)
|
||||||
// - *apistatus.ContainerNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.ObjectLocked;
|
// - [apistatus.ErrObjectLocked];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -162,15 +157,11 @@ func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObj
|
||||||
}
|
}
|
||||||
|
|
||||||
var res ResObjectDelete
|
var res ResObjectDelete
|
||||||
res.st, err = c.processResponse(resp)
|
_, err = c.processResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apistatus.IsSuccessful(res.st) {
|
|
||||||
return &res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const fieldTombstone = "tombstone"
|
const fieldTombstone = "tombstone"
|
||||||
|
|
||||||
idTombV2 := resp.GetBody().GetTombstone().GetObjectID()
|
idTombV2 := resp.GetBody().GetTombstone().GetObjectID()
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
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"
|
||||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
|
@ -100,11 +99,6 @@ type PrmObjectGet struct {
|
||||||
signer neofscrypto.Signer
|
signer neofscrypto.Signer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResObjectGet groups the final result values of ObjectGetInit operation.
|
|
||||||
type ResObjectGet struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReader is designed to read one object from NeoFS system.
|
// ObjectReader is designed to read one object from NeoFS system.
|
||||||
//
|
//
|
||||||
// Must be initialized using Client.ObjectGetInit, any other
|
// Must be initialized using Client.ObjectGetInit, any other
|
||||||
|
@ -117,7 +111,6 @@ type ObjectReader struct {
|
||||||
Read(resp *v2object.GetResponse) error
|
Read(resp *v2object.GetResponse) error
|
||||||
}
|
}
|
||||||
|
|
||||||
res ResObjectGet
|
|
||||||
err error
|
err error
|
||||||
|
|
||||||
tailPayload []byte
|
tailPayload []byte
|
||||||
|
@ -140,8 +133,8 @@ func (x *ObjectReader) ReadHeader(dst *object.Object) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
x.res.st, x.err = x.client.processResponse(&resp)
|
_, x.err = x.client.processResponse(&resp)
|
||||||
if x.err != nil || !apistatus.IsSuccessful(x.res.st) {
|
if x.err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +186,8 @@ func (x *ObjectReader) readChunk(buf []byte) (int, bool) {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
x.res.st, x.err = x.client.processResponse(&resp)
|
_, x.err = x.client.processResponse(&resp)
|
||||||
if x.err != nil || !apistatus.IsSuccessful(x.res.st) {
|
if x.err != nil {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,44 +226,40 @@ func (x *ObjectReader) ReadChunk(buf []byte) (int, bool) {
|
||||||
return x.readChunk(buf)
|
return x.readChunk(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ObjectReader) close(ignoreEOF bool) (*ResObjectGet, error) {
|
func (x *ObjectReader) close(ignoreEOF bool) error {
|
||||||
defer x.cancelCtxStream()
|
defer x.cancelCtxStream()
|
||||||
|
|
||||||
if x.err != nil {
|
if x.err != nil {
|
||||||
if !errors.Is(x.err, io.EOF) {
|
if !errors.Is(x.err, io.EOF) {
|
||||||
return nil, x.err
|
return x.err
|
||||||
} else if !ignoreEOF {
|
} else if !ignoreEOF {
|
||||||
if x.remainingPayloadLen > 0 {
|
if x.remainingPayloadLen > 0 {
|
||||||
return nil, io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &x.res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close ends reading the object and returns the result of the operation
|
// Close ends reading the object and returns the result of the operation
|
||||||
// along with the final results. Must be called after using the ObjectReader.
|
// along with the final results. Must be called after using the ObjectReader.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
|
||||||
// Any client's internal or transport errors are returned as Go built-in error.
|
// Any client's internal or transport errors are returned as Go built-in error.
|
||||||
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
||||||
// codes are returned as error.
|
// codes are returned as error.
|
||||||
//
|
//
|
||||||
// Return errors:
|
// Return errors:
|
||||||
//
|
|
||||||
// *object.SplitInfoError (returned on virtual objects with PrmObjectGet.MakeRaw).
|
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
// - global (see Client docs);
|
||||||
// - *apistatus.ContainerNotFound;
|
// - *[object.SplitInfoError] (returned on virtual objects with PrmObjectGet.MakeRaw).
|
||||||
// - *apistatus.ObjectNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectNotFound];
|
||||||
// - *apistatus.ObjectAlreadyRemoved;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrObjectAlreadyRemoved];
|
||||||
func (x *ObjectReader) Close() (*ResObjectGet, error) {
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
|
func (x *ObjectReader) Close() error {
|
||||||
return x.close(true)
|
return x.close(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +270,11 @@ func (x *ObjectReader) Read(p []byte) (int, error) {
|
||||||
x.remainingPayloadLen -= n
|
x.remainingPayloadLen -= n
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
res, err := x.close(false)
|
if err := x.close(false); err != nil {
|
||||||
if err != nil {
|
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, apistatus.ErrFromStatus(res.Status())
|
return n, x.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.remainingPayloadLen < 0 {
|
if x.remainingPayloadLen < 0 {
|
||||||
|
@ -367,8 +355,6 @@ func (x *PrmObjectHead) UseSigner(signer neofscrypto.Signer) {
|
||||||
|
|
||||||
// ResObjectHead groups resulting values of ObjectHead operation.
|
// ResObjectHead groups resulting values of ObjectHead operation.
|
||||||
type ResObjectHead struct {
|
type ResObjectHead struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
// requested object (response doesn't carry the ID)
|
// requested object (response doesn't carry the ID)
|
||||||
idObj oid.ID
|
idObj oid.ID
|
||||||
|
|
||||||
|
@ -399,24 +385,19 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
||||||
// Any client's internal or transport errors are returned as `error`,
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmObjectHead docs).
|
// Immediately panics if parameters are set incorrectly (see PrmObjectHead docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
//
|
||||||
// Return errors:
|
// Return errors:
|
||||||
//
|
|
||||||
// *object.SplitInfoError (returned on virtual objects with PrmObjectHead.MakeRaw).
|
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
// - global (see Client docs);
|
||||||
// - *apistatus.ContainerNotFound;
|
// - *[object.SplitInfoError] (returned on virtual objects with PrmObjectHead.MakeRaw).
|
||||||
// - *apistatus.ObjectNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectNotFound];
|
||||||
// - *apistatus.ObjectAlreadyRemoved;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrObjectAlreadyRemoved];
|
||||||
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
|
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -452,15 +433,11 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH
|
||||||
}
|
}
|
||||||
|
|
||||||
var res ResObjectHead
|
var res ResObjectHead
|
||||||
res.st, err = c.processResponse(resp)
|
_, err = c.processResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apistatus.IsSuccessful(res.st) {
|
|
||||||
return &res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = res.idObj.ReadFromV2(*prm.addr.GetObjectID())
|
_ = res.idObj.ReadFromV2(*prm.addr.GetObjectID())
|
||||||
|
|
||||||
switch v := resp.GetBody().GetHeaderPart().(type) {
|
switch v := resp.GetBody().GetHeaderPart().(type) {
|
||||||
|
@ -508,11 +485,6 @@ func (x *PrmObjectRange) UseSigner(signer neofscrypto.Signer) {
|
||||||
x.signer = signer
|
x.signer = signer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResObjectRange groups the final result values of ObjectRange operation.
|
|
||||||
type ResObjectRange struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectRangeReader is designed to read payload range of one object
|
// ObjectRangeReader is designed to read payload range of one object
|
||||||
// from NeoFS system.
|
// from NeoFS system.
|
||||||
//
|
//
|
||||||
|
@ -523,7 +495,6 @@ type ObjectRangeReader struct {
|
||||||
|
|
||||||
client *Client
|
client *Client
|
||||||
|
|
||||||
res ResObjectRange
|
|
||||||
err error
|
err error
|
||||||
|
|
||||||
stream interface {
|
stream interface {
|
||||||
|
@ -558,8 +529,8 @@ func (x *ObjectRangeReader) readChunk(buf []byte) (int, bool) {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
x.res.st, x.err = x.client.processResponse(&resp)
|
_, x.err = x.client.processResponse(&resp)
|
||||||
if x.err != nil || !apistatus.IsSuccessful(x.res.st) {
|
if x.err != nil {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,45 +573,41 @@ func (x *ObjectRangeReader) ReadChunk(buf []byte) (int, bool) {
|
||||||
return x.readChunk(buf)
|
return x.readChunk(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ObjectRangeReader) close(ignoreEOF bool) (*ResObjectRange, error) {
|
func (x *ObjectRangeReader) close(ignoreEOF bool) error {
|
||||||
defer x.cancelCtxStream()
|
defer x.cancelCtxStream()
|
||||||
|
|
||||||
if x.err != nil {
|
if x.err != nil {
|
||||||
if !errors.Is(x.err, io.EOF) {
|
if !errors.Is(x.err, io.EOF) {
|
||||||
return nil, x.err
|
return x.err
|
||||||
} else if !ignoreEOF {
|
} else if !ignoreEOF {
|
||||||
if x.remainingPayloadLen > 0 {
|
if x.remainingPayloadLen > 0 {
|
||||||
return nil, io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &x.res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close ends reading the payload range and returns the result of the operation
|
// Close ends reading the payload range and returns the result of the operation
|
||||||
// along with the final results. Must be called after using the ObjectRangeReader.
|
// along with the final results. Must be called after using the ObjectRangeReader.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
|
||||||
// Any client's internal or transport errors are returned as Go built-in error.
|
// Any client's internal or transport errors are returned as Go built-in error.
|
||||||
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
||||||
// codes are returned as error.
|
// codes are returned as error.
|
||||||
//
|
//
|
||||||
// Return errors:
|
// Return errors:
|
||||||
//
|
|
||||||
// *object.SplitInfoError (returned on virtual objects with PrmObjectRange.MakeRaw).
|
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
// - global (see Client docs);
|
||||||
// - *apistatus.ContainerNotFound;
|
// - *[object.SplitInfoError] (returned on virtual objects with PrmObjectRange.MakeRaw).
|
||||||
// - *apistatus.ObjectNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectNotFound];
|
||||||
// - *apistatus.ObjectAlreadyRemoved;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.ObjectOutOfRange;
|
// - [apistatus.ErrObjectAlreadyRemoved];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrObjectOutOfRange];
|
||||||
func (x *ObjectRangeReader) Close() (*ResObjectRange, error) {
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
|
func (x *ObjectRangeReader) Close() error {
|
||||||
return x.close(true)
|
return x.close(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,12 +618,12 @@ func (x *ObjectRangeReader) Read(p []byte) (int, error) {
|
||||||
x.remainingPayloadLen -= n
|
x.remainingPayloadLen -= n
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
res, err := x.close(false)
|
err := x.close(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, apistatus.ErrFromStatus(res.Status())
|
return n, x.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.remainingPayloadLen < 0 {
|
if x.remainingPayloadLen < 0 {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
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"
|
||||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
@ -135,8 +134,6 @@ func (x *PrmObjectHash) WithXHeaders(hs ...string) {
|
||||||
|
|
||||||
// ResObjectHash groups resulting values of ObjectHash operation.
|
// ResObjectHash groups resulting values of ObjectHash operation.
|
||||||
type ResObjectHash struct {
|
type ResObjectHash struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
checksums [][]byte
|
checksums [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,20 +150,10 @@ func (x ResObjectHash) Checksums() [][]byte {
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
||||||
// Any client's internal or transport errors are returned as `error`,
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
|
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs);
|
|
||||||
// - *apistatus.ContainerNotFound;
|
|
||||||
// - *apistatus.ObjectNotFound;
|
|
||||||
// - *apistatus.ObjectAccessDenied;
|
|
||||||
// - *apistatus.ObjectOutOfRange;
|
|
||||||
// - *apistatus.SessionTokenExpired.
|
|
||||||
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
|
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -206,15 +193,11 @@ func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectH
|
||||||
}
|
}
|
||||||
|
|
||||||
var res ResObjectHash
|
var res ResObjectHash
|
||||||
res.st, err = c.processResponse(resp)
|
_, err = c.processResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apistatus.IsSuccessful(res.st) {
|
|
||||||
return &res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
res.checksums = resp.GetBody().GetHashList()
|
res.checksums = resp.GetBody().GetHashList()
|
||||||
if len(res.checksums) == 0 {
|
if len(res.checksums) == 0 {
|
||||||
return nil, newErrMissingResponseField("hash list")
|
return nil, newErrMissingResponseField("hash list")
|
||||||
|
|
|
@ -36,8 +36,6 @@ func (x *PrmObjectPutInit) SetCopiesNumber(copiesNumber uint32) {
|
||||||
|
|
||||||
// ResObjectPut groups the final result values of ObjectPutInit operation.
|
// ResObjectPut groups the final result values of ObjectPutInit operation.
|
||||||
type ResObjectPut struct {
|
type ResObjectPut struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
obj oid.ID
|
obj oid.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,14 +184,14 @@ func (x *ObjectWriter) WritePayloadChunk(chunk []byte) bool {
|
||||||
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
||||||
// codes are returned as error.
|
// codes are returned as error.
|
||||||
//
|
//
|
||||||
// Return statuses:
|
// Return errors:
|
||||||
// - global (see Client docs);
|
// - global (see Client docs);
|
||||||
// - *apistatus.ContainerNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.ObjectLocked;
|
// - [apistatus.ErrObjectLocked];
|
||||||
// - *apistatus.LockNonRegularObject;
|
// - [apistatus.ErrLockNonRegularObject];
|
||||||
// - *apistatus.SessionTokenNotFound;
|
// - [apistatus.ErrSessionTokenNotFound];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
func (x *ObjectWriter) Close() (*ResObjectPut, error) {
|
func (x *ObjectWriter) Close() (*ResObjectPut, error) {
|
||||||
defer x.cancelCtxStream()
|
defer x.cancelCtxStream()
|
||||||
|
|
||||||
|
@ -208,15 +206,11 @@ func (x *ObjectWriter) Close() (*ResObjectPut, error) {
|
||||||
return nil, x.err
|
return nil, x.err
|
||||||
}
|
}
|
||||||
|
|
||||||
x.res.st, x.err = x.client.processResponse(&x.respV2)
|
_, x.err = x.client.processResponse(&x.respV2)
|
||||||
if x.err != nil {
|
if x.err != nil {
|
||||||
return nil, x.err
|
return nil, x.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apistatus.IsSuccessful(x.res.st) {
|
|
||||||
return &x.res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const fieldID = "ID"
|
const fieldID = "ID"
|
||||||
|
|
||||||
idV2 := x.respV2.GetBody().GetObjectID()
|
idV2 := x.respV2.GetBody().GetObjectID()
|
||||||
|
@ -291,7 +285,7 @@ func (x *objectWriter) InitDataStream(header object.Object) (io.Writer, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, apistatus.ErrFromStatus(res.Status())
|
return nil, apistatus.ErrFromStatus(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
type payloadWriter struct {
|
type payloadWriter struct {
|
||||||
|
@ -312,7 +306,7 @@ func (x *payloadWriter) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return apistatus.ErrFromStatus(res.Status())
|
return apistatus.ErrFromStatus(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateObject creates new NeoFS object with given payload data and stores it
|
// CreateObject creates new NeoFS object with given payload data and stores it
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
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"
|
||||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
|
@ -88,11 +87,6 @@ func (x *PrmObjectSearch) SetFilters(filters object.SearchFilters) {
|
||||||
x.filters = filters
|
x.filters = filters
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResObjectSearch groups the final result values of ObjectSearch operation.
|
|
||||||
type ResObjectSearch struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectListReader is designed to read list of object identifiers from NeoFS system.
|
// ObjectListReader is designed to read list of object identifiers from NeoFS system.
|
||||||
//
|
//
|
||||||
// Must be initialized using Client.ObjectSearch, any other usage is unsafe.
|
// Must be initialized using Client.ObjectSearch, any other usage is unsafe.
|
||||||
|
@ -100,7 +94,6 @@ type ObjectListReader struct {
|
||||||
client *Client
|
client *Client
|
||||||
cancelCtxStream context.CancelFunc
|
cancelCtxStream context.CancelFunc
|
||||||
err error
|
err error
|
||||||
res ResObjectSearch
|
|
||||||
stream interface {
|
stream interface {
|
||||||
Read(resp *v2object.SearchResponse) error
|
Read(resp *v2object.SearchResponse) error
|
||||||
}
|
}
|
||||||
|
@ -132,8 +125,8 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
x.res.st, x.err = x.client.processResponse(&resp)
|
_, x.err = x.client.processResponse(&resp)
|
||||||
if x.err != nil || !apistatus.IsSuccessful(x.res.st) {
|
if x.err != nil {
|
||||||
return read, false
|
return read, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,11 +169,7 @@ func (x *ObjectListReader) Iterate(f func(oid.ID) bool) error {
|
||||||
// so false means nothing was read.
|
// so false means nothing was read.
|
||||||
_, ok := x.Read(buf)
|
_, ok := x.Read(buf)
|
||||||
if !ok {
|
if !ok {
|
||||||
res, err := x.Close()
|
return x.Close()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return apistatus.ErrFromStatus(res.Status())
|
|
||||||
}
|
}
|
||||||
if f(buf[0]) {
|
if f(buf[0]) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -191,24 +180,23 @@ func (x *ObjectListReader) Iterate(f func(oid.ID) bool) error {
|
||||||
// Close ends reading list of the matched objects and returns the result of the operation
|
// Close ends reading list of the matched objects and returns the result of the operation
|
||||||
// along with the final results. Must be called after using the ObjectListReader.
|
// along with the final results. Must be called after using the ObjectListReader.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
|
||||||
// Any client's internal or transport errors are returned as Go built-in error.
|
// Any client's internal or transport errors are returned as Go built-in error.
|
||||||
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
// If Client is tuned to resolve NeoFS API statuses, then NeoFS failures
|
||||||
// codes are returned as error.
|
// codes are returned as error.
|
||||||
//
|
//
|
||||||
// Return statuses:
|
// Return errors:
|
||||||
// - global (see Client docs);
|
// - global (see Client docs);
|
||||||
// - *apistatus.ContainerNotFound;
|
// - [apistatus.ErrContainerNotFound];
|
||||||
// - *apistatus.ObjectAccessDenied;
|
// - [apistatus.ErrObjectAccessDenied];
|
||||||
// - *apistatus.SessionTokenExpired.
|
// - [apistatus.ErrSessionTokenExpired].
|
||||||
func (x *ObjectListReader) Close() (*ResObjectSearch, error) {
|
func (x *ObjectListReader) Close() error {
|
||||||
defer x.cancelCtxStream()
|
defer x.cancelCtxStream()
|
||||||
|
|
||||||
if x.err != nil && !errors.Is(x.err, io.EOF) {
|
if x.err != nil && !errors.Is(x.err, io.EOF) {
|
||||||
return nil, x.err
|
return x.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &x.res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectSearchInit initiates object selection through a remote server using NeoFS API protocol.
|
// ObjectSearchInit initiates object selection through a remote server using NeoFS API protocol.
|
||||||
|
|
|
@ -32,25 +32,14 @@ func (x *PrmAnnounceLocalTrust) SetValues(trusts []reputation.Trust) {
|
||||||
x.trusts = trusts
|
x.trusts = trusts
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResAnnounceLocalTrust groups results of AnnounceLocalTrust operation.
|
|
||||||
type ResAnnounceLocalTrust struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceLocalTrust sends client's trust values to the NeoFS network participants.
|
// AnnounceLocalTrust sends client's trust values to the NeoFS network participants.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
|
// Immediately panics if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTrust) error {
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTrust) (*ResAnnounceLocalTrust, error) {
|
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -81,24 +70,22 @@ func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTru
|
||||||
// init call context
|
// init call context
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cc contextCall
|
cc contextCall
|
||||||
res ResAnnounceLocalTrust
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.AnnounceLocalTrust(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.AnnounceLocalTrust(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
if !cc.processCall() {
|
if !cc.processCall() {
|
||||||
return nil, cc.err
|
return cc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrmAnnounceIntermediateTrust groups parameters of AnnounceIntermediateTrust operation.
|
// PrmAnnounceIntermediateTrust groups parameters of AnnounceIntermediateTrust operation.
|
||||||
|
@ -132,26 +119,15 @@ func (x *PrmAnnounceIntermediateTrust) SetCurrentValue(trust reputation.PeerToPe
|
||||||
x.trustSet = true
|
x.trustSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResAnnounceIntermediateTrust groups results of AnnounceIntermediateTrust operation.
|
|
||||||
type ResAnnounceIntermediateTrust struct {
|
|
||||||
statusRes
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceIntermediateTrust sends global trust values calculated for the specified NeoFS network participants
|
// AnnounceIntermediateTrust sends global trust values calculated for the specified NeoFS network participants
|
||||||
// at some stage of client's calculation algorithm.
|
// at some stage of client's calculation algorithm.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
|
// Immediately panics if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceIntermediateTrust) error {
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceIntermediateTrust) (*ResAnnounceIntermediateTrust, error) {
|
|
||||||
// check parameters
|
// check parameters
|
||||||
switch {
|
switch {
|
||||||
case ctx == nil:
|
case ctx == nil:
|
||||||
|
@ -179,22 +155,20 @@ func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceI
|
||||||
// init call context
|
// init call context
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cc contextCall
|
cc contextCall
|
||||||
res ResAnnounceIntermediateTrust
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.initCallContext(&cc)
|
c.initCallContext(&cc)
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return rpcapi.AnnounceIntermediateResult(&c.c, &req, client.WithContext(ctx))
|
return rpcapi.AnnounceIntermediateResult(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// process call
|
// process call
|
||||||
if !cc.processCall() {
|
if !cc.processCall() {
|
||||||
return nil, cc.err
|
return cc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,6 @@ func (x *PrmSessionCreate) UseSigner(signer neofscrypto.Signer) {
|
||||||
|
|
||||||
// ResSessionCreate groups resulting values of SessionCreate operation.
|
// ResSessionCreate groups resulting values of SessionCreate operation.
|
||||||
type ResSessionCreate struct {
|
type ResSessionCreate struct {
|
||||||
statusRes
|
|
||||||
|
|
||||||
id []byte
|
id []byte
|
||||||
|
|
||||||
sessionKey []byte
|
sessionKey []byte
|
||||||
|
@ -63,17 +61,11 @@ func (x ResSessionCreate) PublicKey() []byte {
|
||||||
// The session lifetime coincides with the server lifetime. Results can be written
|
// The session lifetime coincides with the server lifetime. Results can be written
|
||||||
// to session token which can be later attached to the requests.
|
// to session token which can be later attached to the requests.
|
||||||
//
|
//
|
||||||
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||||
// Any client's internal or transport errors are returned as `error`.
|
// see [apistatus] package for NeoFS-specific error types.
|
||||||
// If PrmInit.ResolveNeoFSFailures has been called, unsuccessful
|
|
||||||
// NeoFS status codes are returned as `error`, otherwise, are included
|
|
||||||
// in the returned result structure.
|
|
||||||
//
|
//
|
||||||
// Immediately panics if parameters are set incorrectly (see PrmSessionCreate docs).
|
// Immediately panics if parameters are set incorrectly (see PrmSessionCreate docs).
|
||||||
// Context is required and must not be nil. It is used for network communication.
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
//
|
|
||||||
// Return statuses:
|
|
||||||
// - global (see Client docs).
|
|
||||||
func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
|
func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
|
||||||
// check context
|
// check context
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
|
@ -113,7 +105,6 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS
|
||||||
|
|
||||||
cc.meta = prm.prmCommonMeta
|
cc.meta = prm.prmCommonMeta
|
||||||
cc.req = &req
|
cc.req = &req
|
||||||
cc.statusRes = &res
|
|
||||||
cc.call = func() (responseV2, error) {
|
cc.call = func() (responseV2, error) {
|
||||||
return c.server.createSession(&c.c, &req, client.WithContext(ctx))
|
return c.server.createSession(&c.c, &req, client.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ func TestClient_SessionCreate(t *testing.T) {
|
||||||
|
|
||||||
var prmInit PrmInit
|
var prmInit PrmInit
|
||||||
prmInit.SetDefaultSigner(signer)
|
prmInit.SetDefaultSigner(signer)
|
||||||
prmInit.ResolveNeoFSFailures()
|
|
||||||
|
|
||||||
var c Client
|
var c Client
|
||||||
c.Init(prmInit)
|
c.Init(prmInit)
|
||||||
|
|
|
@ -2,10 +2,30 @@ package apistatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Error describes common error which is a grouping type for any [apistatus] errors. Any [apistatus] error may be checked
|
||||||
|
// explicitly via it's type of just check the group via errors.Is(err, [apistatus.Error]).
|
||||||
|
var Error = errors.New("api error")
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrServerInternal is an instance of ServerInternal error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrServerInternal ServerInternal
|
||||||
|
// ErrWrongMagicNumber is an instance of WrongMagicNumber error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrWrongMagicNumber WrongMagicNumber
|
||||||
|
// ErrSignatureVerification is an instance of SignatureVerification error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrSignatureVerification SignatureVerification
|
||||||
|
// ErrNodeUnderMaintenance is an instance of NodeUnderMaintenance error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrNodeUnderMaintenance NodeUnderMaintenance
|
||||||
|
)
|
||||||
|
|
||||||
// ServerInternal describes failure statuses related to internal server errors.
|
// ServerInternal describes failure statuses related to internal server errors.
|
||||||
// Instances provide [Status], [StatusV2] and error interfaces.
|
// Instances provide [Status], [StatusV2] and error interfaces.
|
||||||
//
|
//
|
||||||
|
@ -21,6 +41,16 @@ func (x ServerInternal) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x ServerInternal) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case ServerInternal, *ServerInternal:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *ServerInternal) fromStatusV2(st *status.Status) {
|
func (x *ServerInternal) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -69,6 +99,16 @@ func (x WrongMagicNumber) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x WrongMagicNumber) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case WrongMagicNumber, *WrongMagicNumber:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *WrongMagicNumber) fromStatusV2(st *status.Status) {
|
func (x *WrongMagicNumber) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -144,6 +184,16 @@ func (x SignatureVerification) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x SignatureVerification) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case SignatureVerification, *SignatureVerification:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *SignatureVerification) fromStatusV2(st *status.Status) {
|
func (x *SignatureVerification) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -203,6 +253,16 @@ func (x NodeUnderMaintenance) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x NodeUnderMaintenance) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case NodeUnderMaintenance, *NodeUnderMaintenance:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) {
|
func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package apistatus
|
package apistatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||||
)
|
)
|
||||||
|
@ -38,7 +40,7 @@ func (x ContainerNotFound) Error() string {
|
||||||
func (x ContainerNotFound) Is(target error) bool {
|
func (x ContainerNotFound) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case ContainerNotFound, *ContainerNotFound:
|
case ContainerNotFound, *ContainerNotFound:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,7 @@ func (x EACLNotFound) Error() string {
|
||||||
func (x EACLNotFound) Is(target error) bool {
|
func (x EACLNotFound) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case EACLNotFound, *EACLNotFound:
|
case EACLNotFound, *EACLNotFound:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
93
client/status/errors_test.go
Normal file
93
client/status/errors_test.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package apistatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrors(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
errs []error
|
||||||
|
errVariable error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
errs: []error{ServerInternal{}, new(ServerInternal)},
|
||||||
|
errVariable: ErrServerInternal,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{WrongMagicNumber{}, new(WrongMagicNumber)},
|
||||||
|
errVariable: ErrWrongMagicNumber,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{SignatureVerification{}, new(SignatureVerification)},
|
||||||
|
errVariable: ErrSignatureVerification,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{NodeUnderMaintenance{}, new(NodeUnderMaintenance)},
|
||||||
|
errVariable: ErrNodeUnderMaintenance,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
errs: []error{ObjectLocked{}, new(ObjectLocked)},
|
||||||
|
errVariable: ErrObjectLocked,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{LockNonRegularObject{}, new(LockNonRegularObject)},
|
||||||
|
errVariable: ErrLockNonRegularObject,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{ObjectAccessDenied{}, new(ObjectAccessDenied)},
|
||||||
|
errVariable: ErrObjectAccessDenied,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{ObjectNotFound{}, new(ObjectNotFound)},
|
||||||
|
errVariable: ErrObjectNotFound,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{ObjectAlreadyRemoved{}, new(ObjectAlreadyRemoved)},
|
||||||
|
errVariable: ErrObjectAlreadyRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{ObjectOutOfRange{}, new(ObjectOutOfRange)},
|
||||||
|
errVariable: ErrObjectOutOfRange,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
errs: []error{ContainerNotFound{}, new(ContainerNotFound)},
|
||||||
|
errVariable: ErrContainerNotFound,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{EACLNotFound{}, new(EACLNotFound)},
|
||||||
|
errVariable: ErrEACLNotFound,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
errs: []error{SessionTokenExpired{}, new(SessionTokenExpired)},
|
||||||
|
errVariable: ErrSessionTokenExpired,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errs: []error{SessionTokenNotFound{}, new(SessionTokenNotFound)},
|
||||||
|
errVariable: ErrSessionTokenNotFound,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
errs: []error{UnrecognizedStatusV2{}, new(UnrecognizedStatusV2)},
|
||||||
|
errVariable: ErrUnrecognizedStatusV2,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
require.NotEmpty(t, tc.errs)
|
||||||
|
require.NotNil(t, tc.errVariable)
|
||||||
|
|
||||||
|
for i := range tc.errs {
|
||||||
|
require.ErrorIs(t, tc.errs[i], tc.errVariable)
|
||||||
|
|
||||||
|
wrapped := fmt.Errorf("some message %w", tc.errs[i])
|
||||||
|
require.ErrorIs(t, wrapped, tc.errVariable)
|
||||||
|
|
||||||
|
wrappedTwice := fmt.Errorf("another message %w", wrapped)
|
||||||
|
require.ErrorIs(t, wrappedTwice, tc.errVariable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,31 @@
|
||||||
package apistatus
|
package apistatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// ErrObjectLocked is an instance of ObjectLocked error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrObjectLocked ObjectLocked
|
||||||
// ErrObjectAlreadyRemoved is an instance of ObjectAlreadyRemoved error status. It's expected to be used for [errors.Is]
|
// ErrObjectAlreadyRemoved is an instance of ObjectAlreadyRemoved error status. It's expected to be used for [errors.Is]
|
||||||
// and MUST NOT be changed.
|
// and MUST NOT be changed.
|
||||||
ErrObjectAlreadyRemoved ObjectAlreadyRemoved
|
ErrObjectAlreadyRemoved ObjectAlreadyRemoved
|
||||||
|
// ErrLockNonRegularObject is an instance of LockNonRegularObject error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrLockNonRegularObject LockNonRegularObject
|
||||||
|
// ErrObjectAccessDenied is an instance of ObjectAccessDenied error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrObjectAccessDenied ObjectAccessDenied
|
||||||
// ErrObjectNotFound is an instance of ObjectNotFound error status. It's expected to be used for [errors.Is]
|
// ErrObjectNotFound is an instance of ObjectNotFound error status. It's expected to be used for [errors.Is]
|
||||||
// and MUST NOT be changed.
|
// and MUST NOT be changed.
|
||||||
ErrObjectNotFound ObjectNotFound
|
ErrObjectNotFound ObjectNotFound
|
||||||
|
// ErrObjectOutOfRange is an instance of ObjectOutOfRange error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
ErrObjectOutOfRange ObjectOutOfRange
|
||||||
)
|
)
|
||||||
|
|
||||||
// ObjectLocked describes status of the failure because of the locked object.
|
// ObjectLocked describes status of the failure because of the locked object.
|
||||||
|
@ -34,6 +48,16 @@ func (x ObjectLocked) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x ObjectLocked) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case ObjectLocked, *ObjectLocked:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *ObjectLocked) fromStatusV2(st *status.Status) {
|
func (x *ObjectLocked) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -71,6 +95,16 @@ func (x LockNonRegularObject) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x LockNonRegularObject) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case LockNonRegularObject, *LockNonRegularObject:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *LockNonRegularObject) fromStatusV2(st *status.Status) {
|
func (x *LockNonRegularObject) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -108,6 +142,16 @@ func (x ObjectAccessDenied) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x ObjectAccessDenied) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case ObjectAccessDenied, *ObjectAccessDenied:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *ObjectAccessDenied) fromStatusV2(st *status.Status) {
|
func (x *ObjectAccessDenied) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
@ -160,7 +204,7 @@ func (x ObjectNotFound) Error() string {
|
||||||
func (x ObjectNotFound) Is(target error) bool {
|
func (x ObjectNotFound) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case ObjectNotFound, *ObjectNotFound:
|
case ObjectNotFound, *ObjectNotFound:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -207,7 +251,7 @@ func (x ObjectAlreadyRemoved) Error() string {
|
||||||
func (x ObjectAlreadyRemoved) Is(target error) bool {
|
func (x ObjectAlreadyRemoved) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case ObjectAlreadyRemoved, *ObjectAlreadyRemoved:
|
case ObjectAlreadyRemoved, *ObjectAlreadyRemoved:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -251,6 +295,16 @@ func (x ObjectOutOfRange) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x ObjectOutOfRange) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return errors.Is(Error, target)
|
||||||
|
case ObjectOutOfRange, *ObjectOutOfRange:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *ObjectOutOfRange) fromStatusV2(st *status.Status) {
|
func (x *ObjectOutOfRange) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package apistatus
|
package apistatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"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/status"
|
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||||
)
|
)
|
||||||
|
@ -38,7 +40,7 @@ func (x SessionTokenNotFound) Error() string {
|
||||||
func (x SessionTokenNotFound) Is(target error) bool {
|
func (x SessionTokenNotFound) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case SessionTokenNotFound, *SessionTokenNotFound:
|
case SessionTokenNotFound, *SessionTokenNotFound:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -85,7 +87,7 @@ func (x SessionTokenExpired) Error() string {
|
||||||
func (x SessionTokenExpired) Is(target error) bool {
|
func (x SessionTokenExpired) Is(target error) bool {
|
||||||
switch target.(type) {
|
switch target.(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return errors.Is(Error, target)
|
||||||
case SessionTokenExpired, *SessionTokenExpired:
|
case SessionTokenExpired, *SessionTokenExpired:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestErrors(t *testing.T) {
|
||||||
|
|
||||||
res := apistatus.ErrFromStatus(st)
|
res := apistatus.ErrFromStatus(st)
|
||||||
|
|
||||||
require.Equal(t, err, res)
|
require.ErrorIs(t, res, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("non-error source", func(t *testing.T) {
|
t.Run("non-error source", func(t *testing.T) {
|
||||||
|
|
|
@ -4,15 +4,31 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type unrecognizedStatusV2 struct {
|
// ErrUnrecognizedStatusV2 is an instance of UnrecognizedStatusV2 error status. It's expected to be used for [errors.Is]
|
||||||
|
// and MUST NOT be changed.
|
||||||
|
var ErrUnrecognizedStatusV2 UnrecognizedStatusV2
|
||||||
|
|
||||||
|
// UnrecognizedStatusV2 describes status of the uncertain failure.
|
||||||
|
// Instances provide [Status], [StatusV2] and error interfaces.
|
||||||
|
type UnrecognizedStatusV2 struct {
|
||||||
v2 status.Status
|
v2 status.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x unrecognizedStatusV2) Error() string {
|
func (x UnrecognizedStatusV2) Error() string {
|
||||||
return errMessageStatusV2("unrecognized", x.v2.Message())
|
return errMessageStatusV2("unrecognized", x.v2.Message())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is implements interface for correct checking current error type with [errors.Is].
|
||||||
|
func (x UnrecognizedStatusV2) Is(target error) bool {
|
||||||
|
switch target.(type) {
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
case UnrecognizedStatusV2, *UnrecognizedStatusV2:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implements local interface defined in FromStatusV2 func.
|
// implements local interface defined in FromStatusV2 func.
|
||||||
func (x *unrecognizedStatusV2) fromStatusV2(st *status.Status) {
|
func (x *UnrecognizedStatusV2) fromStatusV2(st *status.Status) {
|
||||||
x.v2 = *st
|
x.v2 = *st
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,16 +28,29 @@ type StatusV2 interface {
|
||||||
// Note: notice if the return type is a pointer.
|
// Note: notice if the return type is a pointer.
|
||||||
//
|
//
|
||||||
// Successes:
|
// Successes:
|
||||||
// - status.OK: *SuccessDefaultV2 (this also includes nil argument).
|
// - [status.OK]: *[SuccessDefaultV2] (this also includes nil argument).
|
||||||
//
|
//
|
||||||
// Common failures:
|
// Common failures:
|
||||||
// - status.Internal: *ServerInternal;
|
// - [status.Internal]: *[ServerInternal];
|
||||||
// - status.SignatureVerificationFail: *SignatureVerification.
|
// - [status.SignatureVerificationFail]: *[SignatureVerification].
|
||||||
|
// - [status.WrongMagicNumber]: *[WrongMagicNumber].
|
||||||
|
// - [status.NodeUnderMaintenance]: *[NodeUnderMaintenance].
|
||||||
//
|
//
|
||||||
// Object failures:
|
// Object failures:
|
||||||
// - object.StatusLocked: *ObjectLocked;
|
// - [object.StatusLocked]: *[ObjectLocked];
|
||||||
// - object.StatusLockNonRegularObject: *LockNonRegularObject.
|
// - [object.StatusLockNonRegularObject]: *[LockNonRegularObject].
|
||||||
// - object.StatusAccessDenied: *ObjectAccessDenied.
|
// - [object.StatusAccessDenied]: *[ObjectAccessDenied].
|
||||||
|
// - [object.StatusNotFound]: *[ObjectNotFound].
|
||||||
|
// - [object.StatusAlreadyRemoved]: *[ObjectAlreadyRemoved].
|
||||||
|
// - [object.StatusOutOfRange]: *[ObjectOutOfRange].
|
||||||
|
//
|
||||||
|
// Container failures:
|
||||||
|
// - [container.StatusNotFound]: *[ContainerNotFound];
|
||||||
|
// - [container.StatusEACLNotFound]: *[EACLNotFound];
|
||||||
|
//
|
||||||
|
// Session failures:
|
||||||
|
// - [session.StatusTokenNotFound]: *[SessionTokenNotFound];
|
||||||
|
// - [session.StatusTokenExpired]: *[SessionTokenExpired];
|
||||||
func FromStatusV2(st *status.Status) Status {
|
func FromStatusV2(st *status.Status) Status {
|
||||||
var decoder interface {
|
var decoder interface {
|
||||||
fromStatusV2(*status.Status)
|
fromStatusV2(*status.Status)
|
||||||
|
@ -95,7 +108,7 @@ func FromStatusV2(st *status.Status) Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
if decoder == nil {
|
if decoder == nil {
|
||||||
decoder = new(unrecognizedStatusV2)
|
decoder = new(UnrecognizedStatusV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder.fromStatusV2(st)
|
decoder.fromStatusV2(st)
|
||||||
|
|
|
@ -8,166 +8,15 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToStatusV2(t *testing.T) {
|
|
||||||
type statusConstructor func() apistatus.Status
|
|
||||||
|
|
||||||
for _, testItem := range [...]struct {
|
|
||||||
status any // Status or statusConstructor
|
|
||||||
codeV2 uint64
|
|
||||||
messageV2 string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
status: errors.New("some error"),
|
|
||||||
codeV2: 1024,
|
|
||||||
messageV2: "some error",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 1,
|
|
||||||
codeV2: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: "text",
|
|
||||||
codeV2: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: true,
|
|
||||||
codeV2: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: true,
|
|
||||||
codeV2: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: nil,
|
|
||||||
codeV2: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
var st apistatus.ServerInternal
|
|
||||||
|
|
||||||
st.SetMessage("internal error message")
|
|
||||||
|
|
||||||
return st
|
|
||||||
}),
|
|
||||||
codeV2: 1024,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
var st apistatus.WrongMagicNumber
|
|
||||||
|
|
||||||
st.WriteCorrectMagic(322)
|
|
||||||
|
|
||||||
return st
|
|
||||||
}),
|
|
||||||
codeV2: 1025,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.ObjectLocked)
|
|
||||||
}),
|
|
||||||
codeV2: 2050,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.LockNonRegularObject)
|
|
||||||
}),
|
|
||||||
codeV2: 2051,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
var st apistatus.ObjectAccessDenied
|
|
||||||
|
|
||||||
st.WriteReason("any reason")
|
|
||||||
|
|
||||||
return st
|
|
||||||
}),
|
|
||||||
codeV2: 2048,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.ObjectNotFound)
|
|
||||||
}),
|
|
||||||
codeV2: 2049,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.ObjectAlreadyRemoved)
|
|
||||||
}),
|
|
||||||
codeV2: 2052,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.ObjectOutOfRange)
|
|
||||||
}),
|
|
||||||
codeV2: 2053,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.ContainerNotFound)
|
|
||||||
}),
|
|
||||||
codeV2: 3072,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.EACLNotFound)
|
|
||||||
}),
|
|
||||||
codeV2: 3073,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.SessionTokenNotFound)
|
|
||||||
}),
|
|
||||||
codeV2: 4096,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.SessionTokenExpired)
|
|
||||||
}),
|
|
||||||
codeV2: 4097,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
|
||||||
return new(apistatus.NodeUnderMaintenance)
|
|
||||||
}),
|
|
||||||
codeV2: 1027,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
var st apistatus.Status
|
|
||||||
|
|
||||||
if cons, ok := testItem.status.(statusConstructor); ok {
|
|
||||||
st = cons()
|
|
||||||
} else {
|
|
||||||
st = testItem.status
|
|
||||||
}
|
|
||||||
|
|
||||||
stv2 := apistatus.ToStatusV2(st)
|
|
||||||
|
|
||||||
// must generate the same status.Status message
|
|
||||||
require.EqualValues(t, testItem.codeV2, stv2.Code())
|
|
||||||
if len(testItem.messageV2) > 0 {
|
|
||||||
require.Equal(t, testItem.messageV2, stv2.Message())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := st.(apistatus.StatusV2)
|
|
||||||
if ok {
|
|
||||||
// restore and convert again
|
|
||||||
restored := apistatus.FromStatusV2(stv2)
|
|
||||||
|
|
||||||
res := apistatus.ToStatusV2(restored)
|
|
||||||
|
|
||||||
// must generate the same status.Status message
|
|
||||||
require.Equal(t, stv2, res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromStatusV2(t *testing.T) {
|
func TestFromStatusV2(t *testing.T) {
|
||||||
type statusConstructor func() apistatus.Status
|
type statusConstructor func() apistatus.Status
|
||||||
|
|
||||||
for _, testItem := range [...]struct {
|
for _, testItem := range [...]struct {
|
||||||
status any // Status or statusConstructor
|
status any // Status or statusConstructor
|
||||||
codeV2 uint64
|
codeV2 uint64
|
||||||
messageV2 string
|
messageV2 string
|
||||||
|
compatibleErrs []error
|
||||||
|
checkAsErr func(error) bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
status: errors.New("some error"),
|
status: errors.New("some error"),
|
||||||
|
@ -183,7 +32,7 @@ func TestFromStatusV2(t *testing.T) {
|
||||||
codeV2: 0,
|
codeV2: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: true,
|
status: false,
|
||||||
codeV2: 0,
|
codeV2: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -196,93 +45,155 @@ func TestFromStatusV2(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
var st apistatus.ServerInternal
|
st := new(apistatus.ServerInternal)
|
||||||
|
|
||||||
st.SetMessage("internal error message")
|
st.SetMessage("internal error message")
|
||||||
|
|
||||||
return st
|
return st
|
||||||
}),
|
}),
|
||||||
codeV2: 1024,
|
codeV2: 1024,
|
||||||
|
compatibleErrs: []error{apistatus.ErrServerInternal, apistatus.ServerInternal{}, &apistatus.ServerInternal{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ServerInternal
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
var st apistatus.WrongMagicNumber
|
st := new(apistatus.WrongMagicNumber)
|
||||||
|
|
||||||
st.WriteCorrectMagic(322)
|
st.WriteCorrectMagic(322)
|
||||||
|
|
||||||
return st
|
return st
|
||||||
}),
|
}),
|
||||||
codeV2: 1025,
|
codeV2: 1025,
|
||||||
|
compatibleErrs: []error{apistatus.ErrWrongMagicNumber, apistatus.WrongMagicNumber{}, &apistatus.WrongMagicNumber{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.WrongMagicNumber
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.ObjectLocked)
|
return new(apistatus.ObjectLocked)
|
||||||
}),
|
}),
|
||||||
codeV2: 2050,
|
codeV2: 2050,
|
||||||
|
compatibleErrs: []error{apistatus.ErrObjectLocked, apistatus.ObjectLocked{}, &apistatus.ObjectLocked{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ObjectLocked
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.LockNonRegularObject)
|
return new(apistatus.LockNonRegularObject)
|
||||||
}),
|
}),
|
||||||
codeV2: 2051,
|
codeV2: 2051,
|
||||||
|
compatibleErrs: []error{apistatus.ErrLockNonRegularObject, apistatus.LockNonRegularObject{}, &apistatus.LockNonRegularObject{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.LockNonRegularObject
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
var st apistatus.ObjectAccessDenied
|
st := new(apistatus.ObjectAccessDenied)
|
||||||
|
|
||||||
st.WriteReason("any reason")
|
st.WriteReason("any reason")
|
||||||
|
|
||||||
return st
|
return st
|
||||||
}),
|
}),
|
||||||
codeV2: 2048,
|
codeV2: 2048,
|
||||||
|
compatibleErrs: []error{apistatus.ErrObjectAccessDenied, apistatus.ObjectAccessDenied{}, &apistatus.ObjectAccessDenied{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ObjectAccessDenied
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.ObjectNotFound)
|
return new(apistatus.ObjectNotFound)
|
||||||
}),
|
}),
|
||||||
codeV2: 2049,
|
codeV2: 2049,
|
||||||
|
compatibleErrs: []error{apistatus.ErrObjectNotFound, apistatus.ObjectNotFound{}, &apistatus.ObjectNotFound{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ObjectNotFound
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.ObjectAlreadyRemoved)
|
return new(apistatus.ObjectAlreadyRemoved)
|
||||||
}),
|
}),
|
||||||
codeV2: 2052,
|
codeV2: 2052,
|
||||||
|
compatibleErrs: []error{apistatus.ErrObjectAlreadyRemoved, apistatus.ObjectAlreadyRemoved{}, &apistatus.ObjectAlreadyRemoved{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ObjectAlreadyRemoved
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: statusConstructor(func() apistatus.Status {
|
status: statusConstructor(func() apistatus.Status {
|
||||||
return new(apistatus.ObjectOutOfRange)
|
return new(apistatus.ObjectOutOfRange)
|
||||||
}),
|
}),
|
||||||
codeV2: 2053,
|
codeV2: 2053,
|
||||||
|
compatibleErrs: []error{apistatus.ErrObjectOutOfRange, apistatus.ObjectOutOfRange{}, &apistatus.ObjectOutOfRange{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ObjectOutOfRange
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.ContainerNotFound)
|
return new(apistatus.ContainerNotFound)
|
||||||
}),
|
}),
|
||||||
codeV2: 3072,
|
codeV2: 3072,
|
||||||
|
compatibleErrs: []error{apistatus.ErrContainerNotFound, apistatus.ContainerNotFound{}, &apistatus.ContainerNotFound{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.ContainerNotFound
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.EACLNotFound)
|
return new(apistatus.EACLNotFound)
|
||||||
}),
|
}),
|
||||||
codeV2: 3073,
|
codeV2: 3073,
|
||||||
|
compatibleErrs: []error{apistatus.ErrEACLNotFound, apistatus.EACLNotFound{}, &apistatus.EACLNotFound{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.EACLNotFound
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.SessionTokenNotFound)
|
return new(apistatus.SessionTokenNotFound)
|
||||||
}),
|
}),
|
||||||
codeV2: 4096,
|
codeV2: 4096,
|
||||||
|
compatibleErrs: []error{apistatus.ErrSessionTokenNotFound, apistatus.SessionTokenNotFound{}, &apistatus.SessionTokenNotFound{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.SessionTokenNotFound
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.SessionTokenExpired)
|
return new(apistatus.SessionTokenExpired)
|
||||||
}),
|
}),
|
||||||
codeV2: 4097,
|
codeV2: 4097,
|
||||||
|
compatibleErrs: []error{apistatus.ErrSessionTokenExpired, apistatus.SessionTokenExpired{}, &apistatus.SessionTokenExpired{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.SessionTokenExpired
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: (statusConstructor)(func() apistatus.Status {
|
status: (statusConstructor)(func() apistatus.Status {
|
||||||
return new(apistatus.NodeUnderMaintenance)
|
return new(apistatus.NodeUnderMaintenance)
|
||||||
}),
|
}),
|
||||||
codeV2: 1027,
|
codeV2: 1027,
|
||||||
|
compatibleErrs: []error{apistatus.ErrNodeUnderMaintenance, apistatus.NodeUnderMaintenance{}, &apistatus.NodeUnderMaintenance{}, apistatus.Error},
|
||||||
|
checkAsErr: func(err error) bool {
|
||||||
|
var target *apistatus.NodeUnderMaintenance
|
||||||
|
return errors.As(err, &target)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
var st apistatus.Status
|
var st apistatus.Status
|
||||||
|
@ -311,5 +222,17 @@ func TestFromStatusV2(t *testing.T) {
|
||||||
// must generate the same status.Status message
|
// must generate the same status.Status message
|
||||||
require.Equal(t, stv2, res)
|
require.Equal(t, stv2, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randomError := errors.New("garbage")
|
||||||
|
errFromStatus := apistatus.ErrFromStatus(st)
|
||||||
|
|
||||||
|
for _, err := range testItem.compatibleErrs {
|
||||||
|
require.ErrorIs(t, errFromStatus, err)
|
||||||
|
require.NotErrorIs(t, randomError, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if testItem.checkAsErr != nil {
|
||||||
|
require.True(t, testItem.checkAsErr(errFromStatus))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,10 @@ FILTER City EQ SPB AND SSD EQ true OR City EQ SPB AND Rating GE 5 AS SPBSSD`,
|
||||||
var p PlacementPolicy
|
var p PlacementPolicy
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
|
||||||
require.NoError(t, p.DecodeString(testCase))
|
require.NoError(t, p.DecodeString(testCase))
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
require.NoError(t, p.WriteStringTo(&b))
|
require.NoError(t, p.WriteStringTo(&b))
|
||||||
|
|
||||||
require.Equal(t, testCase, b.String())
|
require.Equal(t, testCase, b.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,9 @@ func (m *mockClient) endpointInfo(context.Context, prmEndpointInfo) (netmap.Node
|
||||||
var ni netmap.NodeInfo
|
var ni netmap.NodeInfo
|
||||||
|
|
||||||
if m.errorOnEndpointInfo {
|
if m.errorOnEndpointInfo {
|
||||||
return ni, m.handleError(nil, errors.New("error"))
|
err := errors.New("endpoint info")
|
||||||
|
m.updateErrorRate(err)
|
||||||
|
return ni, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ni.SetNetworkEndpoints(m.addr)
|
ni.SetNetworkEndpoints(m.addr)
|
||||||
|
@ -118,7 +120,9 @@ func (m *mockClient) networkInfo(context.Context, prmNetworkInfo) (netmap.Networ
|
||||||
var ni netmap.NetworkInfo
|
var ni netmap.NetworkInfo
|
||||||
|
|
||||||
if m.errorOnNetworkInfo {
|
if m.errorOnNetworkInfo {
|
||||||
return ni, m.handleError(nil, errors.New("error"))
|
err := errors.New("network info")
|
||||||
|
m.updateErrorRate(err)
|
||||||
|
return ni, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ni, nil
|
return ni, nil
|
||||||
|
@ -139,8 +143,9 @@ func (m *mockClient) objectGet(context.Context, PrmObjectGet) (ResGetObject, err
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
status := apistatus.ErrFromStatus(m.stOnGetObject)
|
err := apistatus.ErrFromStatus(m.stOnGetObject)
|
||||||
return res, m.handleError(status, nil)
|
m.updateErrorRate(err)
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockClient) objectHead(context.Context, PrmObjectHead) (object.Object, error) {
|
func (m *mockClient) objectHead(context.Context, PrmObjectHead) (object.Object, error) {
|
||||||
|
@ -157,7 +162,9 @@ func (m *mockClient) objectSearch(context.Context, PrmObjectSearch) (ResObjectSe
|
||||||
|
|
||||||
func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (resCreateSession, error) {
|
func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (resCreateSession, error) {
|
||||||
if m.errorOnCreateSession {
|
if m.errorOnCreateSession {
|
||||||
return resCreateSession{}, m.handleError(nil, errors.New("error"))
|
err := errors.New("create session")
|
||||||
|
m.updateErrorRate(err)
|
||||||
|
return resCreateSession{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tok := newToken(m.signer)
|
tok := newToken(m.signer)
|
||||||
|
|
177
pool/pool.go
177
pool/pool.go
|
@ -374,11 +374,8 @@ func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (acco
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.BalanceGet(ctx, cliPrm)
|
res, err := cl.BalanceGet(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodBalanceGet)
|
c.incRequests(time.Since(start), methodBalanceGet)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return accounting.Decimal{}, fmt.Errorf("balance get on client: %w", err)
|
return accounting.Decimal{}, fmt.Errorf("balance get on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,11 +393,8 @@ func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerPut(ctx, prm.prmClient)
|
res, err := cl.ContainerPut(ctx, prm.prmClient)
|
||||||
c.incRequests(time.Since(start), methodContainerPut)
|
c.incRequests(time.Since(start), methodContainerPut)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return cid.ID{}, fmt.Errorf("container put on client: %w", err)
|
return cid.ID{}, fmt.Errorf("container put on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +405,8 @@ func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (
|
||||||
idCnr := res.ID()
|
idCnr := res.ID()
|
||||||
|
|
||||||
err = waitForContainerPresence(ctx, c, idCnr, &prm.waitParams)
|
err = waitForContainerPresence(ctx, c, idCnr, &prm.waitParams)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return cid.ID{}, fmt.Errorf("wait container presence on client: %w", err)
|
return cid.ID{}, fmt.Errorf("wait container presence on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,11 +426,8 @@ func (c *clientWrapper) containerGet(ctx context.Context, prm PrmContainerGet) (
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerGet(ctx, cliPrm)
|
res, err := cl.ContainerGet(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodContainerGet)
|
c.incRequests(time.Since(start), methodContainerGet)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return container.Container{}, fmt.Errorf("container get on client: %w", err)
|
return container.Container{}, fmt.Errorf("container get on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,11 +447,8 @@ func (c *clientWrapper) containerList(ctx context.Context, prm PrmContainerList)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerList(ctx, cliPrm)
|
res, err := cl.ContainerList(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodContainerList)
|
c.incRequests(time.Since(start), methodContainerList)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return nil, fmt.Errorf("container list on client: %w", err)
|
return nil, fmt.Errorf("container list on client: %w", err)
|
||||||
}
|
}
|
||||||
return res.Containers(), nil
|
return res.Containers(), nil
|
||||||
|
@ -480,13 +469,10 @@ func (c *clientWrapper) containerDelete(ctx context.Context, prm PrmContainerDel
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerDelete(ctx, cliPrm)
|
err = cl.ContainerDelete(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodContainerDelete)
|
c.incRequests(time.Since(start), methodContainerDelete)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return fmt.Errorf("container delete on client: %w", err)
|
return fmt.Errorf("container delete on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,11 +496,8 @@ func (c *clientWrapper) containerEACL(ctx context.Context, prm PrmContainerEACL)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerEACL(ctx, cliPrm)
|
res, err := cl.ContainerEACL(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodContainerEACL)
|
c.incRequests(time.Since(start), methodContainerEACL)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return eacl.Table{}, fmt.Errorf("get eacl on client: %w", err)
|
return eacl.Table{}, fmt.Errorf("get eacl on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,13 +520,10 @@ func (c *clientWrapper) containerSetEACL(ctx context.Context, prm PrmContainerSe
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ContainerSetEACL(ctx, cliPrm)
|
err = cl.ContainerSetEACL(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodContainerSetEACL)
|
c.incRequests(time.Since(start), methodContainerSetEACL)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return fmt.Errorf("set eacl on client: %w", err)
|
return fmt.Errorf("set eacl on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +537,8 @@ func (c *clientWrapper) containerSetEACL(ctx context.Context, prm PrmContainerSe
|
||||||
}
|
}
|
||||||
|
|
||||||
err = waitForEACLPresence(ctx, c, cIDp, &prm.table, &prm.waitParams)
|
err = waitForEACLPresence(ctx, c, cIDp, &prm.table, &prm.waitParams)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("wait eacl presence on client: %w", err)
|
return fmt.Errorf("wait eacl presence on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,11 +555,8 @@ func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (ne
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{})
|
res, err := cl.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{})
|
||||||
c.incRequests(time.Since(start), methodEndpointInfo)
|
c.incRequests(time.Since(start), methodEndpointInfo)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return netmap.NodeInfo{}, fmt.Errorf("endpoint info on client: %w", err)
|
return netmap.NodeInfo{}, fmt.Errorf("endpoint info on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,11 +573,8 @@ func (c *clientWrapper) networkInfo(ctx context.Context, _ prmNetworkInfo) (netm
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.NetworkInfo(ctx, sdkClient.PrmNetworkInfo{})
|
res, err := cl.NetworkInfo(ctx, sdkClient.PrmNetworkInfo{})
|
||||||
c.incRequests(time.Since(start), methodNetworkInfo)
|
c.incRequests(time.Since(start), methodNetworkInfo)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return netmap.NetworkInfo{}, fmt.Errorf("network info on client: %w", err)
|
return netmap.NetworkInfo{}, fmt.Errorf("network info on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +603,8 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (oid.ID
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
wObj, err := cl.ObjectPutInit(ctx, cliPrm)
|
wObj, err := cl.ObjectPutInit(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodObjectPut)
|
c.incRequests(time.Since(start), methodObjectPut)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return oid.ID{}, fmt.Errorf("init writing on API client: %w", err)
|
return oid.ID{}, fmt.Errorf("init writing on API client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,17 +648,15 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (oid.ID
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return oid.ID{}, fmt.Errorf("read payload: %w", c.handleError(nil, err))
|
c.updateErrorRate(err)
|
||||||
|
return oid.ID{}, fmt.Errorf("read payload: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := wObj.Close()
|
res, err := wObj.Close()
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil { // here err already carries both status and client errors
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil { // here err already carries both status and client errors
|
|
||||||
return oid.ID{}, fmt.Errorf("client failure: %w", err)
|
return oid.ID{}, fmt.Errorf("client failure: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,13 +686,10 @@ func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) e
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ObjectDelete(ctx, cliPrm)
|
_, err = cl.ObjectDelete(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodObjectDelete)
|
c.incRequests(time.Since(start), methodObjectDelete)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return fmt.Errorf("delete object on client: %w", err)
|
return fmt.Errorf("delete object on client: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -749,7 +720,8 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (ResGet
|
||||||
var res ResGetObject
|
var res ResGetObject
|
||||||
|
|
||||||
rObj, err := cl.ObjectGetInit(ctx, cliPrm)
|
rObj, err := cl.ObjectGetInit(ctx, cliPrm)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return ResGetObject{}, fmt.Errorf("init object reading on client: %w", err)
|
return ResGetObject{}, fmt.Errorf("init object reading on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,12 +729,8 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (ResGet
|
||||||
successReadHeader := rObj.ReadHeader(&res.Header)
|
successReadHeader := rObj.ReadHeader(&res.Header)
|
||||||
c.incRequests(time.Since(start), methodObjectGet)
|
c.incRequests(time.Since(start), methodObjectGet)
|
||||||
if !successReadHeader {
|
if !successReadHeader {
|
||||||
rObjRes, err := rObj.Close()
|
err = rObj.Close()
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if rObjRes != nil {
|
|
||||||
st = rObjRes.Status()
|
|
||||||
}
|
|
||||||
err = c.handleError(st, err)
|
|
||||||
return res, fmt.Errorf("read header: %w", err)
|
return res, fmt.Errorf("read header: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,11 +774,8 @@ func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (obje
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ObjectHead(ctx, cliPrm)
|
res, err := cl.ObjectHead(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodObjectHead)
|
c.incRequests(time.Since(start), methodObjectHead)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return obj, fmt.Errorf("read object header via client: %w", err)
|
return obj, fmt.Errorf("read object header via client: %w", err)
|
||||||
}
|
}
|
||||||
if !res.ReadHeader(&obj) {
|
if !res.ReadHeader(&obj) {
|
||||||
|
@ -846,7 +811,8 @@ func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (Re
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.ObjectRangeInit(ctx, cliPrm)
|
res, err := cl.ObjectRangeInit(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodObjectRange)
|
c.incRequests(time.Since(start), methodObjectRange)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return ResObjectRange{}, fmt.Errorf("init payload range reading on client: %w", err)
|
return ResObjectRange{}, fmt.Errorf("init payload range reading on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,7 +849,8 @@ func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) (
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := cl.ObjectSearchInit(ctx, cliPrm)
|
res, err := cl.ObjectSearchInit(ctx, cliPrm)
|
||||||
if err = c.handleError(nil, err); err != nil {
|
c.updateErrorRate(err)
|
||||||
|
if err != nil {
|
||||||
return ResObjectSearch{}, fmt.Errorf("init object searching on client: %w", err)
|
return ResObjectSearch{}, fmt.Errorf("init object searching on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,11 +871,8 @@ func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
res, err := cl.SessionCreate(ctx, cliPrm)
|
res, err := cl.SessionCreate(ctx, cliPrm)
|
||||||
c.incRequests(time.Since(start), methodSessionCreate)
|
c.incRequests(time.Since(start), methodSessionCreate)
|
||||||
var st apistatus.Status
|
c.updateErrorRate(err)
|
||||||
if res != nil {
|
if err != nil {
|
||||||
st = res.Status()
|
|
||||||
}
|
|
||||||
if err = c.handleError(st, err); err != nil {
|
|
||||||
return resCreateSession{}, fmt.Errorf("session creation on client: %w", err)
|
return resCreateSession{}, fmt.Errorf("session creation on client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,29 +942,32 @@ func (c *clientWrapper) incRequests(elapsed time.Duration, method MethodIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientStatusMonitor) handleError(st apistatus.Status, err error) error {
|
func (c *clientStatusMonitor) updateErrorRate(err error) {
|
||||||
if err != nil {
|
if err == nil {
|
||||||
// non-status logic error that could be returned
|
return
|
||||||
// from the SDK client; should not be considered
|
|
||||||
// as a connection error
|
|
||||||
var siErr *object.SplitInfoError
|
|
||||||
if !errors.As(err, &siErr) {
|
|
||||||
c.incErrorRate()
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = apistatus.ErrFromStatus(st)
|
// count only this API errors
|
||||||
switch err.(type) {
|
if errors.Is(err, apistatus.ErrServerInternal) ||
|
||||||
case apistatus.ServerInternal, *apistatus.ServerInternal,
|
errors.Is(err, apistatus.ErrWrongMagicNumber) ||
|
||||||
apistatus.WrongMagicNumber, *apistatus.WrongMagicNumber,
|
errors.Is(err, apistatus.ErrSignatureVerification) ||
|
||||||
apistatus.SignatureVerification, *apistatus.SignatureVerification,
|
errors.Is(err, apistatus.ErrNodeUnderMaintenance) {
|
||||||
apistatus.NodeUnderMaintenance, *apistatus.NodeUnderMaintenance:
|
c.incErrorRate()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't count another API errors
|
||||||
|
if errors.Is(err, apistatus.Error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-status logic error that could be returned
|
||||||
|
// from the SDK client; should not be considered
|
||||||
|
// as a connection error
|
||||||
|
var siErr *object.SplitInfoError
|
||||||
|
if !errors.As(err, &siErr) {
|
||||||
c.incErrorRate()
|
c.incErrorRate()
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientBuilder is a type alias of client constructors which open connection
|
// clientBuilder is a type alias of client constructors which open connection
|
||||||
|
@ -2133,8 +2100,7 @@ func (x *objectReadCloser) Read(p []byte) (int, error) {
|
||||||
|
|
||||||
// Close implements io.Closer of the object payload.
|
// Close implements io.Closer of the object payload.
|
||||||
func (x *objectReadCloser) Close() error {
|
func (x *objectReadCloser) Close() error {
|
||||||
_, err := x.reader.Close()
|
return x.reader.Close()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResGetObject is designed to provide object header nad read one object payload from NeoFS system.
|
// ResGetObject is designed to provide object header nad read one object payload from NeoFS system.
|
||||||
|
@ -2212,8 +2178,7 @@ func (x *ResObjectRange) Read(p []byte) (int, error) {
|
||||||
// Close ends reading the payload range and returns the result of the operation
|
// Close ends reading the payload range and returns the result of the operation
|
||||||
// along with the final results. Must be called after using the ResObjectRange.
|
// along with the final results. Must be called after using the ResObjectRange.
|
||||||
func (x *ResObjectRange) Close() error {
|
func (x *ResObjectRange) Close() error {
|
||||||
_, err := x.payload.Close()
|
return x.payload.Close()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectRange initiates reading an object's payload range through a remote
|
// ObjectRange initiates reading an object's payload range through a remote
|
||||||
|
@ -2251,7 +2216,7 @@ type ResObjectSearch struct {
|
||||||
func (x *ResObjectSearch) Read(buf []oid.ID) (int, error) {
|
func (x *ResObjectSearch) Read(buf []oid.ID) (int, error) {
|
||||||
n, ok := x.r.Read(buf)
|
n, ok := x.r.Read(buf)
|
||||||
if !ok {
|
if !ok {
|
||||||
_, err := x.r.Close()
|
err := x.r.Close()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return n, io.EOF
|
return n, io.EOF
|
||||||
}
|
}
|
||||||
|
@ -2273,7 +2238,7 @@ func (x *ResObjectSearch) Iterate(f func(oid.ID) bool) error {
|
||||||
// Close ends reading list of the matched objects and returns the result of the operation
|
// Close ends reading list of the matched objects and returns the result of the operation
|
||||||
// along with the final results. Must be called after using the ResObjectSearch.
|
// along with the final results. Must be called after using the ResObjectSearch.
|
||||||
func (x *ResObjectSearch) Close() {
|
func (x *ResObjectSearch) Close() {
|
||||||
_, _ = x.r.Close()
|
_ = x.r.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchObjects initiates object selection through a remote server using NeoFS API protocol.
|
// SearchObjects initiates object selection through a remote server using NeoFS API protocol.
|
||||||
|
|
|
@ -521,79 +521,68 @@ func TestHandleError(t *testing.T) {
|
||||||
monitor := newClientStatusMonitor("", 10)
|
monitor := newClientStatusMonitor("", 10)
|
||||||
|
|
||||||
for i, tc := range []struct {
|
for i, tc := range []struct {
|
||||||
status apistatus.Status
|
|
||||||
err error
|
err error
|
||||||
expectedError bool
|
expectedError bool
|
||||||
countError bool
|
countError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
status: nil,
|
|
||||||
err: nil,
|
err: nil,
|
||||||
expectedError: false,
|
expectedError: false,
|
||||||
countError: false,
|
countError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.SuccessDefaultV2{},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
expectedError: false,
|
expectedError: false,
|
||||||
countError: false,
|
countError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.SuccessDefaultV2{},
|
|
||||||
err: errors.New("error"),
|
err: errors.New("error"),
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: nil,
|
|
||||||
err: errors.New("error"),
|
err: errors.New("error"),
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.ObjectNotFound{},
|
err: apistatus.ObjectNotFound{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: false,
|
countError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.ServerInternal{},
|
err: apistatus.ServerInternal{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.WrongMagicNumber{},
|
err: apistatus.WrongMagicNumber{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.SignatureVerification{},
|
err: apistatus.SignatureVerification{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: &apistatus.SignatureVerification{},
|
err: apistatus.SignatureVerification{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: apistatus.NodeUnderMaintenance{},
|
err: apistatus.NodeUnderMaintenance{},
|
||||||
err: nil,
|
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
countError: true,
|
countError: true,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
errCount := monitor.currentErrorRate()
|
errCount := monitor.currentErrorRate()
|
||||||
err := monitor.handleError(tc.status, tc.err)
|
monitor.updateErrorRate(tc.err)
|
||||||
if tc.expectedError {
|
if tc.expectedError {
|
||||||
require.Error(t, err)
|
require.Error(t, tc.err)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, tc.err)
|
||||||
}
|
}
|
||||||
if tc.countError {
|
if tc.countError {
|
||||||
errCount++
|
errCount++
|
||||||
|
|
|
@ -183,12 +183,16 @@ func TestStorageGroup_SetMembers_DoubleSetting(t *testing.T) {
|
||||||
var sg storagegroup.StorageGroup
|
var sg storagegroup.StorageGroup
|
||||||
|
|
||||||
mm := []oid.ID{oidtest.ID(), oidtest.ID(), oidtest.ID()} // cap is 3 at least
|
mm := []oid.ID{oidtest.ID(), oidtest.ID(), oidtest.ID()} // cap is 3 at least
|
||||||
sg.SetMembers(mm)
|
require.NotPanics(t, func() {
|
||||||
|
sg.SetMembers(mm)
|
||||||
|
})
|
||||||
|
|
||||||
// the previous cap is more that a new length;
|
require.NotPanics(t, func() {
|
||||||
// slicing should not lead to `out of range`
|
// the previous cap is more that a new length;
|
||||||
// and apply update correctly
|
// slicing should not lead to `out of range`
|
||||||
sg.SetMembers(mm[:1])
|
// and apply update correctly
|
||||||
|
sg.SetMembers(mm[:1])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStorageGroupFromObject(t *testing.T) {
|
func TestStorageGroupFromObject(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue