4e31b4f231
In previous implementation `client` package provided access to nested response fields as pointers to them. This caused clients to handle nil cases even when the field presence in the response is required. Avoid returning pointers to required fields in response getters. This also reduces reference counter load and allows fields to be decoded directly without additional assignment. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
820 lines
21 KiB
Go
820 lines
21 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
v2container "github.com/nspcc-dev/neofs-api-go/v2/container"
|
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
|
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
|
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
|
"github.com/nspcc-dev/neofs-sdk-go/user"
|
|
)
|
|
|
|
// PrmContainerPut groups parameters of ContainerPut operation.
|
|
type PrmContainerPut struct {
|
|
prmCommonMeta
|
|
|
|
cnrSet bool
|
|
cnr container.Container
|
|
|
|
sessionSet bool
|
|
session session.Container
|
|
}
|
|
|
|
// SetContainer sets structured information about new NeoFS container.
|
|
// Required parameter.
|
|
func (x *PrmContainerPut) SetContainer(cnr container.Container) {
|
|
x.cnr = cnr
|
|
x.cnrSet = true
|
|
}
|
|
|
|
// WithinSession specifies session within which container should be saved.
|
|
//
|
|
// Creator of the session acquires the authorship of the request. This affects
|
|
// the execution of an operation (e.g. access control).
|
|
//
|
|
// Session is optional, if set the following requirements apply:
|
|
// - session operation MUST be session.VerbContainerPut (ForVerb)
|
|
// - token MUST be signed using private key of the owner of the container to be saved
|
|
func (x *PrmContainerPut) WithinSession(s session.Container) {
|
|
x.session = s
|
|
x.sessionSet = true
|
|
}
|
|
|
|
// ResContainerPut groups resulting values of ContainerPut operation.
|
|
type ResContainerPut struct {
|
|
statusRes
|
|
|
|
id cid.ID
|
|
}
|
|
|
|
// ID returns identifier of the container declared to be stored in the system.
|
|
// Used as a link to information about the container (in particular, you can
|
|
// asynchronously check if the save was successful).
|
|
func (x ResContainerPut) ID() cid.ID {
|
|
return x.id
|
|
}
|
|
|
|
// 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 client's internal or transport errors are returned as `error`.
|
|
// 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.
|
|
// The required time is also not predictable.
|
|
//
|
|
// 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 statuses:
|
|
// - global (see Client docs).
|
|
func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.cnrSet:
|
|
panic(panicMsgMissingContainer)
|
|
}
|
|
|
|
// TODO: check private key is set before forming the request
|
|
// sign container
|
|
var cnr v2container.Container
|
|
prm.cnr.WriteToV2(&cnr)
|
|
|
|
var sig neofscrypto.Signature
|
|
|
|
err := container.CalculateSignature(&sig, prm.cnr, c.prm.key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("calculate container signature: %w", err)
|
|
}
|
|
|
|
var sigv2 refs.Signature
|
|
|
|
sig.WriteToV2(&sigv2)
|
|
|
|
// form request body
|
|
reqBody := new(v2container.PutRequestBody)
|
|
reqBody.SetContainer(&cnr)
|
|
reqBody.SetSignature(&sigv2)
|
|
|
|
// form meta header
|
|
var meta v2session.RequestMetaHeader
|
|
prm.prmCommonMeta.writeToMetaHeader(&meta)
|
|
|
|
if prm.sessionSet {
|
|
var tokv2 v2session.Token
|
|
prm.session.WriteToV2(&tokv2)
|
|
|
|
meta.SetSessionToken(&tokv2)
|
|
}
|
|
|
|
// form request
|
|
var req v2container.PutRequest
|
|
|
|
req.SetBody(reqBody)
|
|
req.SetMetaHeader(&meta)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerPut
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.PutContainer(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
cc.result = func(r responseV2) {
|
|
resp := r.(*v2container.PutResponse)
|
|
|
|
const fieldCnrID = "container ID"
|
|
|
|
cidV2 := resp.GetBody().GetContainerID()
|
|
if cidV2 == nil {
|
|
cc.err = newErrMissingResponseField(fieldCnrID)
|
|
return
|
|
}
|
|
|
|
cc.err = res.id.ReadFromV2(*cidV2)
|
|
if cc.err != nil {
|
|
cc.err = newErrInvalidResponseField(fieldCnrID, cc.err)
|
|
}
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmContainerGet groups parameters of ContainerGet operation.
|
|
type PrmContainerGet struct {
|
|
prmCommonMeta
|
|
|
|
idSet bool
|
|
id cid.ID
|
|
}
|
|
|
|
// SetContainer sets identifier of the container to be read.
|
|
// Required parameter.
|
|
func (x *PrmContainerGet) SetContainer(id cid.ID) {
|
|
x.id = id
|
|
x.idSet = true
|
|
}
|
|
|
|
// ResContainerGet groups resulting values of ContainerGet operation.
|
|
type ResContainerGet struct {
|
|
statusRes
|
|
|
|
cnr container.Container
|
|
}
|
|
|
|
// Container returns structured information about the requested container.
|
|
//
|
|
// Client doesn't retain value so modification is safe.
|
|
func (x ResContainerGet) Container() container.Container {
|
|
return x.cnr
|
|
}
|
|
|
|
// ContainerGet reads NeoFS container by ID.
|
|
//
|
|
// 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`.
|
|
// 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).
|
|
// 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) {
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.idSet:
|
|
panic(panicMsgMissingContainer)
|
|
}
|
|
|
|
var cidV2 refs.ContainerID
|
|
prm.id.WriteToV2(&cidV2)
|
|
|
|
// form request body
|
|
reqBody := new(v2container.GetRequestBody)
|
|
reqBody.SetContainerID(&cidV2)
|
|
|
|
// form request
|
|
var req v2container.GetRequest
|
|
|
|
req.SetBody(reqBody)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerGet
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.meta = prm.prmCommonMeta
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.GetContainer(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
cc.result = func(r responseV2) {
|
|
resp := r.(*v2container.GetResponse)
|
|
|
|
cnrV2 := resp.GetBody().GetContainer()
|
|
if cnrV2 == nil {
|
|
cc.err = errors.New("missing container in response")
|
|
return
|
|
}
|
|
|
|
cc.err = res.cnr.ReadFromV2(*cnrV2)
|
|
if cc.err != nil {
|
|
cc.err = fmt.Errorf("invalid container in response: %w", cc.err)
|
|
}
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmContainerList groups parameters of ContainerList operation.
|
|
type PrmContainerList struct {
|
|
prmCommonMeta
|
|
|
|
ownerSet bool
|
|
ownerID user.ID
|
|
}
|
|
|
|
// SetAccount sets identifier of the NeoFS account to list the containers.
|
|
// Required parameter.
|
|
func (x *PrmContainerList) SetAccount(id user.ID) {
|
|
x.ownerID = id
|
|
x.ownerSet = true
|
|
}
|
|
|
|
// ResContainerList groups resulting values of ContainerList operation.
|
|
type ResContainerList struct {
|
|
statusRes
|
|
|
|
ids []cid.ID
|
|
}
|
|
|
|
// Containers returns list of identifiers of the account-owned containers.
|
|
//
|
|
// Client doesn't retain value so modification is safe.
|
|
func (x ResContainerList) Containers() []cid.ID {
|
|
return x.ids
|
|
}
|
|
|
|
// 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 client's internal or transport errors are returned as `error`.
|
|
// 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).
|
|
// 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) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.ownerSet:
|
|
panic("account not set")
|
|
}
|
|
|
|
// form request body
|
|
var ownerV2 refs.OwnerID
|
|
prm.ownerID.WriteToV2(&ownerV2)
|
|
|
|
reqBody := new(v2container.ListRequestBody)
|
|
reqBody.SetOwnerID(&ownerV2)
|
|
|
|
// form request
|
|
var req v2container.ListRequest
|
|
|
|
req.SetBody(reqBody)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerList
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.meta = prm.prmCommonMeta
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.ListContainers(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
cc.result = func(r responseV2) {
|
|
resp := r.(*v2container.ListResponse)
|
|
|
|
res.ids = make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
|
|
|
|
for i, cidV2 := range resp.GetBody().GetContainerIDs() {
|
|
cc.err = res.ids[i].ReadFromV2(cidV2)
|
|
if cc.err != nil {
|
|
cc.err = fmt.Errorf("invalid ID in the response: %w", cc.err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmContainerDelete groups parameters of ContainerDelete operation.
|
|
type PrmContainerDelete struct {
|
|
prmCommonMeta
|
|
|
|
idSet bool
|
|
id cid.ID
|
|
|
|
tokSet bool
|
|
tok session.Container
|
|
}
|
|
|
|
// SetContainer sets identifier of the NeoFS container to be removed.
|
|
// Required parameter.
|
|
func (x *PrmContainerDelete) SetContainer(id cid.ID) {
|
|
x.id = id
|
|
x.idSet = true
|
|
}
|
|
|
|
// WithinSession specifies session within which container should be removed.
|
|
//
|
|
// Creator of the session acquires the authorship of the request.
|
|
// This may affect the execution of an operation (e.g. access control).
|
|
//
|
|
// Must be signed.
|
|
func (x *PrmContainerDelete) WithinSession(tok session.Container) {
|
|
x.tok = tok
|
|
x.tokSet = true
|
|
}
|
|
|
|
// ResContainerDelete groups resulting values of ContainerDelete operation.
|
|
type ResContainerDelete struct {
|
|
statusRes
|
|
}
|
|
|
|
// 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 client's internal or transport errors are returned as `error`.
|
|
// 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.
|
|
// The required time is also not predictable.
|
|
//
|
|
// 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.
|
|
//
|
|
// 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.).
|
|
//
|
|
// Return statuses:
|
|
// - global (see Client docs).
|
|
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*ResContainerDelete, error) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.idSet:
|
|
panic(panicMsgMissingContainer)
|
|
}
|
|
|
|
// sign container ID
|
|
var cidV2 refs.ContainerID
|
|
prm.id.WriteToV2(&cidV2)
|
|
|
|
// container contract expects signature of container ID value
|
|
// don't get confused with stable marshaled protobuf container.ID structure
|
|
data := cidV2.GetValue()
|
|
|
|
var sig neofscrypto.Signature
|
|
|
|
err := sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("calculate signature: %w", err)
|
|
}
|
|
|
|
var sigv2 refs.Signature
|
|
|
|
sig.WriteToV2(&sigv2)
|
|
|
|
// form request body
|
|
reqBody := new(v2container.DeleteRequestBody)
|
|
reqBody.SetContainerID(&cidV2)
|
|
reqBody.SetSignature(&sigv2)
|
|
|
|
// form meta header
|
|
var meta v2session.RequestMetaHeader
|
|
prm.prmCommonMeta.writeToMetaHeader(&meta)
|
|
|
|
if prm.tokSet {
|
|
var tokv2 v2session.Token
|
|
prm.tok.WriteToV2(&tokv2)
|
|
|
|
meta.SetSessionToken(&tokv2)
|
|
}
|
|
|
|
// form request
|
|
var req v2container.DeleteRequest
|
|
|
|
req.SetBody(reqBody)
|
|
req.SetMetaHeader(&meta)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerDelete
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.DeleteContainer(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmContainerEACL groups parameters of ContainerEACL operation.
|
|
type PrmContainerEACL struct {
|
|
prmCommonMeta
|
|
|
|
idSet bool
|
|
id cid.ID
|
|
}
|
|
|
|
// SetContainer sets identifier of the NeoFS container to read the eACL table.
|
|
// Required parameter.
|
|
func (x *PrmContainerEACL) SetContainer(id cid.ID) {
|
|
x.id = id
|
|
x.idSet = true
|
|
}
|
|
|
|
// ResContainerEACL groups resulting values of ContainerEACL operation.
|
|
type ResContainerEACL struct {
|
|
statusRes
|
|
|
|
table eacl.Table
|
|
}
|
|
|
|
// Table returns eACL table of the requested container.
|
|
func (x ResContainerEACL) Table() eacl.Table {
|
|
return x.table
|
|
}
|
|
|
|
// 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 client's internal or transport errors are returned as `error`.
|
|
// 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).
|
|
// 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) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.idSet:
|
|
panic(panicMsgMissingContainer)
|
|
}
|
|
|
|
var cidV2 refs.ContainerID
|
|
prm.id.WriteToV2(&cidV2)
|
|
|
|
// form request body
|
|
reqBody := new(v2container.GetExtendedACLRequestBody)
|
|
reqBody.SetContainerID(&cidV2)
|
|
|
|
// form request
|
|
var req v2container.GetExtendedACLRequest
|
|
|
|
req.SetBody(reqBody)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerEACL
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.meta = prm.prmCommonMeta
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.GetEACL(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
cc.result = func(r responseV2) {
|
|
resp := r.(*v2container.GetExtendedACLResponse)
|
|
|
|
eACL := resp.GetBody().GetEACL()
|
|
if eACL == nil {
|
|
cc.err = newErrMissingResponseField("eACL")
|
|
return
|
|
}
|
|
|
|
res.table = *eacl.NewTableFromV2(eACL)
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmContainerSetEACL groups parameters of ContainerSetEACL operation.
|
|
type PrmContainerSetEACL struct {
|
|
prmCommonMeta
|
|
|
|
tableSet bool
|
|
table eacl.Table
|
|
|
|
sessionSet bool
|
|
session session.Container
|
|
}
|
|
|
|
// SetTable sets eACL table structure to be set for the container.
|
|
// Required parameter.
|
|
func (x *PrmContainerSetEACL) SetTable(table eacl.Table) {
|
|
x.table = table
|
|
x.tableSet = true
|
|
}
|
|
|
|
// WithinSession specifies session within which extended ACL of the container
|
|
// should be saved.
|
|
//
|
|
// Creator of the session acquires the authorship of the request. This affects
|
|
// the execution of an operation (e.g. access control).
|
|
//
|
|
// Session is optional, if set the following requirements apply:
|
|
// - if particular container is specified (ApplyOnlyTo), it MUST equal the container
|
|
// for which extended ACL is going to be set
|
|
// - session operation MUST be session.VerbContainerSetEACL (ForVerb)
|
|
// - token MUST be signed using private key of the owner of the container to be saved
|
|
func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
|
|
x.session = s
|
|
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.
|
|
//
|
|
// 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`.
|
|
// 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.
|
|
// The required time is also not predictable.
|
|
//
|
|
// Success can be verified by reading by identifier (see EACL).
|
|
//
|
|
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
|
|
// Context is required and must not be nil. It is used for network communication.
|
|
//
|
|
// Return statuses:
|
|
// - global (see Client docs).
|
|
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) (*ResContainerSetEACL, error) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case !prm.tableSet:
|
|
panic("eACL table not set")
|
|
}
|
|
|
|
// sign the eACL table
|
|
eaclV2 := prm.table.ToV2()
|
|
|
|
var sig neofscrypto.Signature
|
|
|
|
err := sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), eaclV2.StableMarshal(nil))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("calculate signature: %w", err)
|
|
}
|
|
|
|
var sigv2 refs.Signature
|
|
|
|
sig.WriteToV2(&sigv2)
|
|
|
|
// form request body
|
|
reqBody := new(v2container.SetExtendedACLRequestBody)
|
|
reqBody.SetEACL(eaclV2)
|
|
reqBody.SetSignature(&sigv2)
|
|
|
|
// form meta header
|
|
var meta v2session.RequestMetaHeader
|
|
prm.prmCommonMeta.writeToMetaHeader(&meta)
|
|
|
|
if prm.sessionSet {
|
|
var tokv2 v2session.Token
|
|
prm.session.WriteToV2(&tokv2)
|
|
|
|
meta.SetSessionToken(&tokv2)
|
|
}
|
|
|
|
// form request
|
|
var req v2container.SetExtendedACLRequest
|
|
|
|
req.SetBody(reqBody)
|
|
req.SetMetaHeader(&meta)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResContainerSetEACL
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.SetEACL(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// PrmAnnounceSpace groups parameters of ContainerAnnounceUsedSpace operation.
|
|
type PrmAnnounceSpace struct {
|
|
prmCommonMeta
|
|
|
|
announcements []container.SizeEstimation
|
|
}
|
|
|
|
// SetValues sets values describing volume of space that is used for the container objects.
|
|
// Required parameter. Must not be empty.
|
|
//
|
|
// Must not be mutated before the end of the operation.
|
|
func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) {
|
|
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.
|
|
//
|
|
// 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`.
|
|
// 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.
|
|
// The required time is also not predictable.
|
|
//
|
|
// 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 statuses:
|
|
// - global (see Client docs).
|
|
func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) (*ResAnnounceSpace, error) {
|
|
// check parameters
|
|
switch {
|
|
case ctx == nil:
|
|
panic(panicMsgMissingContext)
|
|
case len(prm.announcements) == 0:
|
|
panic("missing announcements")
|
|
}
|
|
|
|
// convert list of SDK announcement structures into NeoFS-API v2 list
|
|
v2announce := make([]v2container.UsedSpaceAnnouncement, len(prm.announcements))
|
|
for i := range prm.announcements {
|
|
prm.announcements[i].WriteToV2(&v2announce[i])
|
|
}
|
|
|
|
// prepare body of the NeoFS-API v2 request and request itself
|
|
reqBody := new(v2container.AnnounceUsedSpaceRequestBody)
|
|
reqBody.SetAnnouncements(v2announce)
|
|
|
|
// form request
|
|
var req v2container.AnnounceUsedSpaceRequest
|
|
|
|
req.SetBody(reqBody)
|
|
|
|
// init call context
|
|
|
|
var (
|
|
cc contextCall
|
|
res ResAnnounceSpace
|
|
)
|
|
|
|
c.initCallContext(&cc)
|
|
cc.meta = prm.prmCommonMeta
|
|
cc.req = &req
|
|
cc.statusRes = &res
|
|
cc.call = func() (responseV2, error) {
|
|
return rpcapi.AnnounceUsedSpace(&c.c, &req, client.WithContext(ctx))
|
|
}
|
|
|
|
// process call
|
|
if !cc.processCall() {
|
|
return nil, cc.err
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
// SyncContainerWithNetwork requests network configuration using passed client
|
|
// and applies it to the container. Container MUST not be nil.
|
|
//
|
|
// Note: if container does not match network configuration, SyncContainerWithNetwork
|
|
// changes it.
|
|
//
|
|
// Returns any network/parsing config errors.
|
|
//
|
|
// See also NetworkInfo, container.ApplyNetworkConfig.
|
|
func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, c *Client) error {
|
|
res, err := c.NetworkInfo(ctx, PrmNetworkInfo{})
|
|
if err != nil {
|
|
return fmt.Errorf("network info call: %w", err)
|
|
}
|
|
|
|
container.ApplyNetworkConfig(cnr, res.Info())
|
|
|
|
return nil
|
|
}
|