forked from TrueCloudLab/frostfs-sdk-go
commit
7002b3b0df
22 changed files with 210 additions and 140 deletions
|
@ -41,14 +41,14 @@ func (x ResBalanceGet) Amount() accounting.Decimal {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmBalanceGet docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingAccount]
|
||||
func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) {
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.accountSet:
|
||||
panic("account not set")
|
||||
return nil, ErrMissingAccount
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
|
|
@ -74,15 +74,19 @@ func (c *Client) Init(prm PrmInit) {
|
|||
// One-time method call during application start-up stage (after Init ) is expected.
|
||||
// Calling multiple times leads to undefined behavior.
|
||||
//
|
||||
// Return client errors:
|
||||
// - [ErrMissingServer]
|
||||
// - [ErrNonPositiveTimeout]
|
||||
//
|
||||
// See also Init / Close.
|
||||
func (c *Client) Dial(prm PrmDial) error {
|
||||
if prm.endpoint == "" {
|
||||
panic("server address is unset or empty")
|
||||
return ErrMissingServer
|
||||
}
|
||||
|
||||
if prm.timeoutDialSet {
|
||||
if prm.timeoutDial <= 0 {
|
||||
panic("non-positive timeout")
|
||||
return ErrNonPositiveTimeout
|
||||
}
|
||||
} else {
|
||||
prm.timeoutDial = 5 * time.Second
|
||||
|
@ -90,7 +94,7 @@ func (c *Client) Dial(prm PrmDial) error {
|
|||
|
||||
if prm.streamTimeoutSet {
|
||||
if prm.streamTimeout <= 0 {
|
||||
panic("non-positive timeout")
|
||||
return ErrNonPositiveTimeout
|
||||
}
|
||||
} else {
|
||||
prm.streamTimeout = 10 * time.Second
|
||||
|
|
|
@ -47,14 +47,6 @@ func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
|
|||
h.SetXHeaders(hs)
|
||||
}
|
||||
|
||||
// panic messages.
|
||||
const (
|
||||
panicMsgMissingContext = "missing context"
|
||||
panicMsgMissingContainer = "missing container"
|
||||
panicMsgMissingObject = "missing object"
|
||||
panicMsgOwnerExtract = "extract owner failed"
|
||||
)
|
||||
|
||||
// groups all the details required to send a single request and process a response to it.
|
||||
type contextCall struct {
|
||||
// ==================================================
|
||||
|
|
|
@ -84,15 +84,15 @@ func (c *Client) defaultSigner() neofscrypto.Signer {
|
|||
//
|
||||
// Success can be verified by reading by identifier (see ResContainerPut.ID).
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerPut docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.cnrSet:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
}
|
||||
|
||||
// TODO: check private signer is set before forming the request
|
||||
|
@ -206,14 +206,14 @@ func (x ResContainerGet) Container() container.Container {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerGet docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) {
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.idSet:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 refs.ContainerID
|
||||
|
@ -296,15 +296,15 @@ func (x ResContainerList) Containers() []cid.ID {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerList docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingAccount]
|
||||
func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.ownerSet:
|
||||
panic("account not set")
|
||||
return nil, ErrMissingAccount
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
@ -402,17 +402,17 @@ func (x *PrmContainerDelete) WithinSession(tok session.Container) {
|
|||
//
|
||||
// Success can be verified by reading by identifier (see GetContainer).
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerDelete docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
//
|
||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) error {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.idSet:
|
||||
panic(panicMsgMissingContainer)
|
||||
return ErrMissingContainer
|
||||
}
|
||||
|
||||
// sign container ID
|
||||
|
@ -510,15 +510,15 @@ func (x ResContainerEACL) Table() eacl.Table {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerEACL docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.idSet:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 refs.ContainerID
|
||||
|
@ -619,20 +619,21 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
|
|||
//
|
||||
// Success can be verified by reading by identifier (see EACL).
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
|
||||
// Return errors:
|
||||
// - [ErrMissingEACL]
|
||||
// - [ErrMissingEACLContainer]
|
||||
//
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.tableSet:
|
||||
panic("eACL table not set")
|
||||
return ErrMissingEACL
|
||||
}
|
||||
|
||||
_, isCIDSet := prm.table.CID()
|
||||
if !isCIDSet {
|
||||
panic("missing container in eACL table")
|
||||
return ErrMissingEACLContainer
|
||||
}
|
||||
|
||||
// sign the eACL table
|
||||
|
@ -720,15 +721,15 @@ func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) {
|
|||
//
|
||||
// At this moment success can not be checked.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceSpace docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingAnnouncements]
|
||||
func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) error {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case len(prm.announcements) == 0:
|
||||
panic("missing announcements")
|
||||
return ErrMissingAnnouncements
|
||||
}
|
||||
|
||||
// convert list of SDK announcement structures into NeoFS-API v2 list
|
||||
|
|
|
@ -1,33 +1,72 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingResponseField missingResponseFieldErr
|
||||
// ErrMissingServer is returned when server endpoint is empty in parameters.
|
||||
ErrMissingServer = errors.New("server address is unset or empty")
|
||||
// ErrNonPositiveTimeout is returned when any timeout is below zero in parameters.
|
||||
ErrNonPositiveTimeout = errors.New("non-positive timeout")
|
||||
|
||||
// ErrMissingContainer is returned when container is not provided.
|
||||
ErrMissingContainer = errors.New("missing container")
|
||||
// ErrMissingObject is returned when object is not provided.
|
||||
ErrMissingObject = errors.New("missing object")
|
||||
// ErrMissingAccount is returned when account/owner is not provided.
|
||||
ErrMissingAccount = errors.New("missing account")
|
||||
// ErrMissingEACL is returned when eACL table is not provided.
|
||||
ErrMissingEACL = errors.New("missing eACL table")
|
||||
// ErrMissingEACLContainer is returned when container info is not provided in eACL table.
|
||||
ErrMissingEACLContainer = errors.New("missing container in eACL table")
|
||||
// ErrMissingAnnouncements is returned when announcements are not provided.
|
||||
ErrMissingAnnouncements = errors.New("missing announcements")
|
||||
// ErrZeroRangeLength is returned when range parameter has zero length.
|
||||
ErrZeroRangeLength = errors.New("zero range length")
|
||||
// ErrMissingRanges is returned when empty ranges list is provided.
|
||||
ErrMissingRanges = errors.New("missing ranges")
|
||||
// ErrZeroEpoch is returned when zero epoch is provided.
|
||||
ErrZeroEpoch = errors.New("zero epoch")
|
||||
// ErrMissingTrusts is returned when empty slice of trusts is provided.
|
||||
ErrMissingTrusts = errors.New("missing trusts")
|
||||
// ErrMissingTrust is returned when empty trust is not provided.
|
||||
ErrMissingTrust = errors.New("missing trust")
|
||||
|
||||
// ErrUnexpectedReadCall is returned when we already got all data but truing to get more.
|
||||
ErrUnexpectedReadCall = errors.New("unexpected call to `Read`")
|
||||
|
||||
// ErrSign is returned when unable to sign service message.
|
||||
ErrSign SignError
|
||||
|
||||
// ErrMissingResponseField is returned when required field is not exists in NeoFS api response.
|
||||
ErrMissingResponseField MissingResponseFieldErr
|
||||
)
|
||||
|
||||
type missingResponseFieldErr struct {
|
||||
// MissingResponseFieldErr contains field name which should be in NeoFS API response.
|
||||
type MissingResponseFieldErr struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (e missingResponseFieldErr) Error() string {
|
||||
// Error implements the error interface.
|
||||
func (e MissingResponseFieldErr) Error() string {
|
||||
return fmt.Sprintf("missing %s field in the response", e.name)
|
||||
}
|
||||
|
||||
func (e missingResponseFieldErr) Is(target error) bool {
|
||||
// Is implements interface for correct checking current error type with [errors.Is].
|
||||
func (e MissingResponseFieldErr) Is(target error) bool {
|
||||
switch target.(type) {
|
||||
default:
|
||||
return false
|
||||
case missingResponseFieldErr, *missingResponseFieldErr:
|
||||
case MissingResponseFieldErr, *MissingResponseFieldErr:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// returns error describing missing field with the given name.
|
||||
func newErrMissingResponseField(name string) error {
|
||||
return missingResponseFieldErr{name: name}
|
||||
return MissingResponseFieldErr{name: name}
|
||||
}
|
||||
|
||||
// returns error describing invalid field (according to the NeoFS protocol)
|
||||
|
@ -35,3 +74,33 @@ func newErrMissingResponseField(name string) error {
|
|||
func newErrInvalidResponseField(name string, err error) error {
|
||||
return fmt.Errorf("invalid %s field in the response: %w", name, err)
|
||||
}
|
||||
|
||||
// SignError wraps another error with reason why sign process was failed.
|
||||
type SignError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// NewSignError is a constructor for [SignError].
|
||||
func NewSignError(err error) SignError {
|
||||
return SignError{err: err}
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e SignError) Error() string {
|
||||
return fmt.Sprintf("sign: %v", e.err)
|
||||
}
|
||||
|
||||
// Unwrap implements the error interface.
|
||||
func (e SignError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// Is implements interface for correct checking current error type with [errors.Is].
|
||||
func (e SignError) Is(target error) bool {
|
||||
switch target.(type) {
|
||||
default:
|
||||
return false
|
||||
case SignError, *SignError:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
17
client/errors_test.go
Normal file
17
client/errors_test.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package client_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_SignError(t *testing.T) {
|
||||
someErr := errors.New("some error")
|
||||
signErr := client.NewSignError(someErr)
|
||||
|
||||
require.ErrorIs(t, signErr, someErr)
|
||||
require.ErrorIs(t, signErr, client.ErrSign)
|
||||
}
|
|
@ -41,17 +41,11 @@ func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo {
|
|||
// Any client's internal or transport errors are returned as `error`,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmEndpointInfo docs).
|
||||
// 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.
|
||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||
func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) {
|
||||
// check context
|
||||
if ctx == nil {
|
||||
panic(panicMsgMissingContext)
|
||||
}
|
||||
|
||||
// form request
|
||||
var req v2netmap.LocalNodeInfoRequest
|
||||
|
||||
|
@ -130,17 +124,11 @@ func (x ResNetworkInfo) Info() netmap.NetworkInfo {
|
|||
// Any client's internal or transport errors are returned as `error`,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmNetworkInfo docs).
|
||||
// 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.
|
||||
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
|
||||
func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) {
|
||||
// check context
|
||||
if ctx == nil {
|
||||
panic(panicMsgMissingContext)
|
||||
}
|
||||
|
||||
// form request
|
||||
var req v2netmap.NetworkInfoRequest
|
||||
|
||||
|
@ -207,11 +195,6 @@ func (x ResNetMapSnapshot) NetMap() netmap.NetMap {
|
|||
// 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.).
|
||||
func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) {
|
||||
// check context
|
||||
if ctx == nil {
|
||||
panic(panicMsgMissingContext)
|
||||
}
|
||||
|
||||
// form request body
|
||||
var body v2netmap.SnapshotRequestBody
|
||||
|
||||
|
|
|
@ -82,12 +82,6 @@ func TestClient_NetMapSnapshot(t *testing.T) {
|
|||
c := newClient(signer, &srv)
|
||||
ctx := context.Background()
|
||||
|
||||
// missing context
|
||||
require.PanicsWithValue(t, panicMsgMissingContext, func() {
|
||||
//nolint:staticcheck
|
||||
_, _ = c.NetMapSnapshot(nil, prm)
|
||||
})
|
||||
|
||||
// request signature
|
||||
srv.errTransport = errors.New("any error")
|
||||
|
||||
|
|
|
@ -114,23 +114,22 @@ func (x ResObjectDelete) Tombstone() oid.ID {
|
|||
// Any client's internal or transport errors are returned as `error`,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectDelete docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - global (see Client docs)
|
||||
// - [ErrMissingContainer];
|
||||
// - [ErrMissingObject];
|
||||
// - [apistatus.ErrContainerNotFound];
|
||||
// - [apistatus.ErrObjectAccessDenied];
|
||||
// - [apistatus.ErrObjectLocked];
|
||||
// - [apistatus.ErrSessionTokenExpired].
|
||||
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
panic(panicMsgMissingObject)
|
||||
return nil, ErrMissingObject
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
|
|
@ -289,17 +289,18 @@ func (x *ObjectReader) Read(p []byte) (int, error) {
|
|||
// The call only opens the transmission channel, explicit fetching is done using the ObjectReader.
|
||||
// Exactly one return value is non-nil. Resulting reader must be finally closed.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectGet docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
// - [ErrMissingObject]
|
||||
func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectReader, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
panic(panicMsgMissingObject)
|
||||
return nil, ErrMissingObject
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
@ -387,11 +388,12 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
|||
// Any client's internal or transport errors are returned as `error`,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectHead docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - global (see Client docs);
|
||||
// - [ErrMissingContainer];
|
||||
// - [ErrMissingObject];
|
||||
// - *[object.SplitInfoError] (returned on virtual objects with PrmObjectHead.MakeRaw).
|
||||
// - [apistatus.ErrContainerNotFound];
|
||||
// - [apistatus.ErrObjectNotFound];
|
||||
|
@ -400,12 +402,10 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
|||
// - [apistatus.ErrSessionTokenExpired].
|
||||
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
panic(panicMsgMissingObject)
|
||||
return nil, ErrMissingObject
|
||||
}
|
||||
|
||||
var body v2object.HeadRequestBody
|
||||
|
@ -639,19 +639,21 @@ func (x *ObjectRangeReader) Read(p []byte) (int, error) {
|
|||
// The call only opens the transmission channel, explicit fetching is done using the ObjectRangeReader.
|
||||
// Exactly one return value is non-nil. Resulting reader must be finally closed.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectRange docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
// - [ErrMissingObject]
|
||||
// - [ErrZeroRangeLength]
|
||||
func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*ObjectRangeReader, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
panic(panicMsgMissingObject)
|
||||
return nil, ErrMissingObject
|
||||
case prm.rng.GetLength() == 0:
|
||||
panic("zero range length")
|
||||
return nil, ErrZeroRangeLength
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
|
|
@ -152,18 +152,20 @@ func (x ResObjectHash) Checksums() [][]byte {
|
|||
// Any client's internal or transport errors are returned as `error`,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
// - [ErrMissingObject]
|
||||
// - [ErrMissingRanges]
|
||||
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
panic(panicMsgMissingObject)
|
||||
return nil, ErrMissingObject
|
||||
case len(prm.body.GetRanges()) == 0:
|
||||
panic("missing ranges")
|
||||
return nil, ErrMissingRanges
|
||||
}
|
||||
|
||||
prm.body.SetAddress(&prm.addr)
|
||||
|
|
|
@ -233,11 +233,6 @@ func (x *ObjectWriter) Close() (*ResObjectPut, error) {
|
|||
//
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
func (c *Client) ObjectPutInit(ctx context.Context, prm PrmObjectPutInit) (*ObjectWriter, error) {
|
||||
// check parameters
|
||||
if ctx == nil {
|
||||
panic(panicMsgMissingContext)
|
||||
}
|
||||
|
||||
var w ObjectWriter
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
|
|
@ -205,15 +205,15 @@ func (x *ObjectListReader) Close() error {
|
|||
// is done using the ObjectListReader. Exactly one return value is non-nil.
|
||||
// Resulting reader must be finally closed.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmObjectSearch docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrMissingContainer]
|
||||
func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*ObjectListReader, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case !prm.cnrSet:
|
||||
panic(panicMsgMissingContainer)
|
||||
return nil, ErrMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 v2refs.ContainerID
|
||||
|
|
|
@ -2,7 +2,6 @@ package client
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
|
@ -136,7 +135,7 @@ func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error {
|
|||
if s.endError != nil {
|
||||
return s.endError
|
||||
}
|
||||
panic("unexpected call to `Read`")
|
||||
return ErrUnexpectedReadCall
|
||||
}
|
||||
|
||||
var body v2object.SearchResponseBody
|
||||
|
@ -152,7 +151,7 @@ func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error {
|
|||
|
||||
err := signServiceMessage(s.signer, resp)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error: %w", err))
|
||||
return err
|
||||
}
|
||||
|
||||
s.n++
|
||||
|
|
|
@ -37,17 +37,18 @@ func (x *PrmAnnounceLocalTrust) SetValues(trusts []reputation.Trust) {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrZeroEpoch]
|
||||
// - [ErrMissingTrusts]
|
||||
func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTrust) error {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.epoch == 0:
|
||||
panic("zero epoch")
|
||||
return ErrZeroEpoch
|
||||
case len(prm.trusts) == 0:
|
||||
panic("missing trusts")
|
||||
return ErrMissingTrusts
|
||||
}
|
||||
|
||||
// form request body
|
||||
|
@ -125,17 +126,18 @@ func (x *PrmAnnounceIntermediateTrust) SetCurrentValue(trust reputation.PeerToPe
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
//
|
||||
// Return errors:
|
||||
// - [ErrZeroEpoch]
|
||||
// - [ErrMissingTrust]
|
||||
func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceIntermediateTrust) error {
|
||||
// check parameters
|
||||
switch {
|
||||
case ctx == nil:
|
||||
panic(panicMsgMissingContext)
|
||||
case prm.epoch == 0:
|
||||
panic("zero epoch")
|
||||
return ErrZeroEpoch
|
||||
case !prm.trustSet:
|
||||
panic("current trust value not set")
|
||||
return ErrMissingTrust
|
||||
}
|
||||
|
||||
var trust v2reputation.PeerToPeerTrust
|
||||
|
|
|
@ -2,6 +2,7 @@ package client
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||
|
@ -64,17 +65,11 @@ func (x ResSessionCreate) PublicKey() []byte {
|
|||
// Any errors (local or remote, including returned status codes) are returned as Go errors,
|
||||
// see [apistatus] package for NeoFS-specific error types.
|
||||
//
|
||||
// Immediately panics if parameters are set incorrectly (see PrmSessionCreate docs).
|
||||
// Context is required and must not be nil. It is used for network communication.
|
||||
func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
|
||||
// check context
|
||||
if ctx == nil {
|
||||
panic(panicMsgMissingContext)
|
||||
}
|
||||
|
||||
var ownerID user.ID
|
||||
if err := user.IDFromSigner(&ownerID, prm.signer); err != nil {
|
||||
panic(panicMsgOwnerExtract)
|
||||
return nil, fmt.Errorf("IDFromSigner: %w", err)
|
||||
}
|
||||
|
||||
var ownerIDV2 refs.OwnerID
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestClient_SessionCreate(t *testing.T) {
|
|||
|
||||
result, err := c.SessionCreate(ctx, prmSessionCreate)
|
||||
require.Nil(t, result)
|
||||
require.ErrorIs(t, err, errMissingResponseField)
|
||||
require.ErrorIs(t, err, ErrMissingResponseField)
|
||||
require.Equal(t, "missing session id field in the response", err.Error())
|
||||
})
|
||||
|
||||
|
@ -67,7 +67,7 @@ func TestClient_SessionCreate(t *testing.T) {
|
|||
|
||||
result, err := c.SessionCreate(ctx, prmSessionCreate)
|
||||
require.Nil(t, result)
|
||||
require.ErrorIs(t, err, errMissingResponseField)
|
||||
require.ErrorIs(t, err, ErrMissingResponseField)
|
||||
require.Equal(t, "missing session key field in the response", err.Error())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -132,6 +132,8 @@ func (s stableMarshalerWrapper) SignedDataSize() int {
|
|||
}
|
||||
|
||||
// signServiceMessage signing request or response messages which can be sent or received from neofs endpoint.
|
||||
// Return errors:
|
||||
// - [ErrSign]
|
||||
func signServiceMessage(signer neofscrypto.Signer, msg interface{}) error {
|
||||
var (
|
||||
body, meta, verifyOrigin stableMarshaler
|
||||
|
@ -165,24 +167,24 @@ func signServiceMessage(signer neofscrypto.Signer, msg interface{}) error {
|
|||
verifyOrigin = h
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||
return NewSignError(fmt.Errorf("unsupported session message %T", v))
|
||||
}
|
||||
|
||||
if verifyOrigin == nil {
|
||||
// sign session message body
|
||||
if err := signServiceMessagePart(signer, body, verifyHdr.SetBodySignature); err != nil {
|
||||
return fmt.Errorf("could not sign body: %w", err)
|
||||
return NewSignError(fmt.Errorf("body: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// sign meta header
|
||||
if err := signServiceMessagePart(signer, meta, verifyHdr.SetMetaSignature); err != nil {
|
||||
return fmt.Errorf("could not sign meta header: %w", err)
|
||||
return NewSignError(fmt.Errorf("meta header: %w", err))
|
||||
}
|
||||
|
||||
// sign verification header origin
|
||||
if err := signServiceMessagePart(signer, verifyOrigin, verifyHdr.SetOriginSignature); err != nil {
|
||||
return fmt.Errorf("could not sign origin of verification header: %w", err)
|
||||
return NewSignError(fmt.Errorf("origin of verification header: %w", err))
|
||||
}
|
||||
|
||||
// wrap origin verification header
|
||||
|
@ -240,7 +242,7 @@ func verifyServiceMessage(msg interface{}) error {
|
|||
ResponseVerificationHeader: v.GetVerificationHeader(),
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||
return fmt.Errorf("unsupported session message %T", v)
|
||||
}
|
||||
|
||||
body := serviceMessageBody(msg)
|
||||
|
|
|
@ -19,6 +19,11 @@ import (
|
|||
"github.com/nspcc-dev/tzhash/tz"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidAttributeAmount indicates wrong number of arguments. Amount of arguments MUST be even number.
|
||||
ErrInvalidAttributeAmount = errors.New("attributes must be even number of strings")
|
||||
)
|
||||
|
||||
// ObjectWriter represents a virtual object recorder.
|
||||
type ObjectWriter interface {
|
||||
// InitDataStream initializes and returns a stream of writable data associated
|
||||
|
@ -133,15 +138,16 @@ func (x *Slicer) childPayloadSizeLimit() uint64 {
|
|||
//
|
||||
// See New for details.
|
||||
func (x *Slicer) Slice(data io.Reader, attributes ...string) (oid.ID, error) {
|
||||
var rootID oid.ID
|
||||
|
||||
if len(attributes)%2 != 0 {
|
||||
panic("attributes must be even number of strings")
|
||||
return rootID, ErrInvalidAttributeAmount
|
||||
}
|
||||
|
||||
if x.opts.objectPayloadLimit == 0 {
|
||||
x.opts.objectPayloadLimit = 1 << 20
|
||||
}
|
||||
|
||||
var rootID oid.ID
|
||||
var rootHeader object.Object
|
||||
var offset uint64
|
||||
var isSplit bool
|
||||
|
|
|
@ -155,7 +155,7 @@ func (x commonData) signedData(w contextWriter) []byte {
|
|||
|
||||
func (x *commonData) sign(signer neofscrypto.Signer, w contextWriter) error {
|
||||
if err := user.IDFromSigner(&x.issuer, signer); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("IDFromSigner: %w", err)
|
||||
}
|
||||
|
||||
x.issuerSet = true
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||
)
|
||||
|
||||
// ErrOwnerExtract is returned when failed to extract account info from key.
|
||||
var ErrOwnerExtract = errors.New("decode owner failed")
|
||||
|
||||
// IDFromKey forms the ID using script hash calculated for the given key.
|
||||
func IDFromKey(id *ID, key []byte) error {
|
||||
var pk keys.PublicKey
|
||||
if err := pk.DecodeBytes(key); err != nil {
|
||||
return fmt.Errorf("IDFromKey %v", err)
|
||||
return fmt.Errorf("%w: %v", ErrOwnerExtract, err)
|
||||
}
|
||||
|
||||
id.SetScriptHash(pk.GetScriptHash())
|
||||
|
|
|
@ -20,4 +20,8 @@ func TestIDFromKey(t *testing.T) {
|
|||
require.NoError(t, user.IDFromKey(&id, rawPub))
|
||||
|
||||
require.Equal(t, "NNLi44dJNXtDNSBkofB48aTVYtb1zZrNEs", id.EncodeToString())
|
||||
|
||||
err := user.IDFromKey(&id, []byte{1})
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, user.ErrOwnerExtract)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue