From 772fa909838321f089fadc1fe111f3ac49453704 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Apr 2023 08:33:17 +0300 Subject: [PATCH] [#48] client/container: Form requests in a separate function Signed-off-by: Evgenii Stratonikov --- client/container_delete.go | 91 ++++++++++++++++++------------------ client/container_eacl.go | 38 ++++++++------- client/container_get.go | 37 ++++++++------- client/container_list.go | 38 ++++++++------- client/container_put.go | 85 ++++++++++++++++----------------- client/container_set_eacl.go | 81 ++++++++++++++++---------------- client/container_space.go | 43 +++++++++-------- 7 files changed, 216 insertions(+), 197 deletions(-) diff --git a/client/container_delete.go b/client/container_delete.go index 07cee4f..5e1fa51 100644 --- a/client/container_delete.go +++ b/client/container_delete.go @@ -33,6 +33,48 @@ func (x *PrmContainerDelete) SetContainer(id cid.ID) { x.idSet = true } +func (x *PrmContainerDelete) formRequest(c *Client) (*v2container.DeleteRequest, error) { + if !x.idSet { + return nil, errorMissingContainer + } + + var cidV2 refs.ContainerID + x.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 frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.key), data) + if err != nil { + return nil, fmt.Errorf("calculate signature: %w", err) + } + + var sigv2 refs.Signature + sig.WriteToV2(&sigv2) + + reqBody := new(v2container.DeleteRequestBody) + reqBody.SetContainerID(&cidV2) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta) + + if x.tokSet { + var tokv2 v2session.Token + x.tok.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.DeleteRequest + req.SetBody(reqBody) + req.SetMetaHeader(&meta) + return &req, nil +} + // WithinSession specifies session within which container should be removed. // // Creator of the session acquires the authorship of the request. @@ -71,52 +113,11 @@ type ResContainerDelete struct { // Return statuses: // - global (see Client docs). func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*ResContainerDelete, error) { - // check parameters - if !prm.idSet { - return nil, errorMissingContainer - } - - // 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 frostfscrypto.Signature - - err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.key), data) + req, err := prm.formRequest(c) if err != nil { - return nil, fmt.Errorf("calculate signature: %w", err) + return nil, 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 - writeXHeadersToMeta(prm.prmCommonMeta.xHeaders, &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 ( @@ -125,10 +126,10 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (* ) c.initCallContext(&cc) - cc.req = &req + cc.req = req cc.statusRes = &res 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 diff --git a/client/container_eacl.go b/client/container_eacl.go index 8ea388d..acd0778 100644 --- a/client/container_eacl.go +++ b/client/container_eacl.go @@ -26,6 +26,22 @@ func (x *PrmContainerEACL) SetContainer(id cid.ID) { x.idSet = true } +func (x *PrmContainerEACL) formRequest(c *Client) (*v2container.GetExtendedACLRequest, error) { + if !x.idSet { + return nil, errorMissingContainer + } + + var cidV2 refs.ContainerID + x.id.WriteToV2(&cidV2) + + reqBody := new(v2container.GetExtendedACLRequestBody) + reqBody.SetContainerID(&cidV2) + + var req v2container.GetExtendedACLRequest + req.SetBody(reqBody) + return &req, nil +} + // ResContainerEACL groups resulting values of ContainerEACL operation. type ResContainerEACL struct { statusRes @@ -54,23 +70,11 @@ func (x ResContainerEACL) Table() eacl.Table { // - *apistatus.ContainerNotFound; // - *apistatus.EACLNotFound. func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) { - // check parameters - if !prm.idSet { - return nil, errorMissingContainer + req, err := prm.formRequest(c) + if err != nil { + return nil, err } - 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 ( @@ -80,10 +84,10 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC c.initCallContext(&cc) cc.meta = prm.prmCommonMeta - cc.req = &req + cc.req = req cc.statusRes = &res cc.call = func() (responseV2, error) { - return rpcapi.GetEACL(&c.c, &req, client.WithContext(ctx)) + return rpcapi.GetEACL(&c.c, req, client.WithContext(ctx)) } cc.result = func(r responseV2) { resp := r.(*v2container.GetExtendedACLResponse) diff --git a/client/container_get.go b/client/container_get.go index 0cbad88..e91ccdf 100644 --- a/client/container_get.go +++ b/client/container_get.go @@ -28,6 +28,22 @@ func (x *PrmContainerGet) SetContainer(id cid.ID) { x.idSet = true } +func (x *PrmContainerGet) formRequest(_ *Client) (*v2container.GetRequest, error) { + if !x.idSet { + return nil, errorMissingContainer + } + + var cidV2 refs.ContainerID + x.id.WriteToV2(&cidV2) + + reqBody := new(v2container.GetRequestBody) + reqBody.SetContainerID(&cidV2) + + var req v2container.GetRequest + req.SetBody(reqBody) + return &req, nil +} + // ResContainerGet groups resulting values of ContainerGet operation. type ResContainerGet struct { statusRes @@ -57,22 +73,11 @@ func (x ResContainerGet) Container() container.Container { // - global (see Client docs); // - *apistatus.ContainerNotFound. func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) { - if !prm.idSet { - return nil, errorMissingContainer + req, err := prm.formRequest(c) + if err != nil { + return nil, err } - 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 ( @@ -82,10 +87,10 @@ func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResCon c.initCallContext(&cc) cc.meta = prm.prmCommonMeta - cc.req = &req + cc.req = req cc.statusRes = &res cc.call = func() (responseV2, error) { - return rpcapi.GetContainer(&c.c, &req, client.WithContext(ctx)) + return rpcapi.GetContainer(&c.c, req, client.WithContext(ctx)) } cc.result = func(r responseV2) { resp := r.(*v2container.GetResponse) diff --git a/client/container_list.go b/client/container_list.go index 85b4c37..6108c99 100644 --- a/client/container_list.go +++ b/client/container_list.go @@ -27,6 +27,22 @@ func (x *PrmContainerList) SetAccount(id user.ID) { x.ownerSet = true } +func (x *PrmContainerList) formRequest(_ *Client) (*v2container.ListRequest, error) { + if !x.ownerSet { + return nil, errorAccountNotSet + } + + var ownerV2 refs.OwnerID + x.ownerID.WriteToV2(&ownerV2) + + reqBody := new(v2container.ListRequestBody) + reqBody.SetOwnerID(&ownerV2) + + var req v2container.ListRequest + req.SetBody(reqBody) + return &req, nil +} + // ResContainerList groups resulting values of ContainerList operation. type ResContainerList struct { statusRes @@ -55,23 +71,11 @@ func (x ResContainerList) Containers() []cid.ID { // Return statuses: // - global (see Client docs). func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) { - // check parameters - if !prm.ownerSet { - return nil, errorAccountNotSet + req, err := prm.formRequest(c) + if err != nil { + return nil, err } - // 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 ( @@ -81,10 +85,10 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC c.initCallContext(&cc) cc.meta = prm.prmCommonMeta - cc.req = &req + cc.req = req cc.statusRes = &res cc.call = func() (responseV2, error) { - return rpcapi.ListContainers(&c.c, &req, client.WithContext(ctx)) + return rpcapi.ListContainers(&c.c, req, client.WithContext(ctx)) } cc.result = func(r responseV2) { resp := r.(*v2container.ListResponse) diff --git a/client/container_put.go b/client/container_put.go index 83896b8..92f35ab 100644 --- a/client/container_put.go +++ b/client/container_put.go @@ -46,6 +46,45 @@ func (x *PrmContainerPut) WithinSession(s session.Container) { x.sessionSet = true } +func (x *PrmContainerPut) formRequest(c *Client) (*v2container.PutRequest, error) { + if !x.cnrSet { + return nil, errorMissingContainer + } + + // TODO: check private key is set before forming the request + var cnr v2container.Container + x.cnr.WriteToV2(&cnr) + + var sig frostfscrypto.Signature + + err := container.CalculateSignature(&sig, x.cnr, c.prm.key) + if err != nil { + return nil, fmt.Errorf("calculate container signature: %w", err) + } + + var sigv2 refs.Signature + sig.WriteToV2(&sigv2) + + reqBody := new(v2container.PutRequestBody) + reqBody.SetContainer(&cnr) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta) + + if x.sessionSet { + var tokv2 v2session.Token + x.session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.PutRequest + req.SetBody(reqBody) + req.SetMetaHeader(&meta) + return &req, nil +} + // ResContainerPut groups resulting values of ContainerPut operation. type ResContainerPut struct { statusRes @@ -81,49 +120,11 @@ func (x ResContainerPut) ID() cid.ID { // // nolint: funlen func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) { - // check parameters - if !prm.cnrSet { - return nil, errorMissingContainer - } - - // TODO: check private key is set before forming the request - // sign container - var cnr v2container.Container - prm.cnr.WriteToV2(&cnr) - - var sig frostfscrypto.Signature - - err := container.CalculateSignature(&sig, prm.cnr, c.prm.key) + req, err := prm.formRequest(c) if err != nil { - return nil, fmt.Errorf("calculate container signature: %w", err) + return nil, 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 - writeXHeadersToMeta(prm.prmCommonMeta.xHeaders, &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 ( @@ -132,10 +133,10 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon ) c.initCallContext(&cc) - cc.req = &req + cc.req = req cc.statusRes = &res cc.call = func() (responseV2, error) { - return rpcapi.PutContainer(&c.c, &req, client.WithContext(ctx)) + return rpcapi.PutContainer(&c.c, req, client.WithContext(ctx)) } cc.result = func(r responseV2) { resp := r.(*v2container.PutResponse) diff --git a/client/container_set_eacl.go b/client/container_set_eacl.go index d0266f1..f3b76e7 100644 --- a/client/container_set_eacl.go +++ b/client/container_set_eacl.go @@ -49,6 +49,43 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) { x.sessionSet = true } +func (x *PrmContainerSetEACL) formRequest(c *Client) (*v2container.SetExtendedACLRequest, error) { + if !x.tableSet { + return nil, errorEACLTableNotSet + } + + eaclV2 := x.table.ToV2() + + var sig frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.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) + + reqBody := new(v2container.SetExtendedACLRequestBody) + reqBody.SetEACL(eaclV2) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta) + + if x.sessionSet { + var tokv2 v2session.Token + x.session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.SetExtendedACLRequest + req.SetBody(reqBody) + req.SetMetaHeader(&meta) + return &req, nil +} + // ResContainerSetEACL groups resulting values of ContainerSetEACL operation. type ResContainerSetEACL struct { statusRes @@ -73,47 +110,11 @@ type ResContainerSetEACL struct { // Return statuses: // - global (see Client docs). func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) (*ResContainerSetEACL, error) { - // check parameters - if !prm.tableSet { - return nil, errorEACLTableNotSet - } - - // sign the eACL table - eaclV2 := prm.table.ToV2() - - var sig frostfscrypto.Signature - - err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.key), eaclV2.StableMarshal(nil)) + req, err := prm.formRequest(c) if err != nil { - return nil, fmt.Errorf("calculate signature: %w", err) + return nil, 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 - writeXHeadersToMeta(prm.prmCommonMeta.xHeaders, &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 ( @@ -122,10 +123,10 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) ) c.initCallContext(&cc) - cc.req = &req + cc.req = req cc.statusRes = &res 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 diff --git a/client/container_space.go b/client/container_space.go index 2b7bdc8..69dfc5e 100644 --- a/client/container_space.go +++ b/client/container_space.go @@ -24,6 +24,24 @@ func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) { x.announcements = vs } +func (x *PrmAnnounceSpace) formRequest(c *Client) (*v2container.AnnounceUsedSpaceRequest, error) { + if len(x.announcements) == 0 { + return nil, errorMissingAnnouncements + } + + v2announce := make([]v2container.UsedSpaceAnnouncement, len(x.announcements)) + for i := range x.announcements { + x.announcements[i].WriteToV2(&v2announce[i]) + } + + reqBody := new(v2container.AnnounceUsedSpaceRequestBody) + reqBody.SetAnnouncements(v2announce) + + var req v2container.AnnounceUsedSpaceRequest + req.SetBody(reqBody) + return &req, nil +} + // ResAnnounceSpace groups resulting values of ContainerAnnounceUsedSpace operation. type ResAnnounceSpace struct { statusRes @@ -48,26 +66,11 @@ type ResAnnounceSpace struct { // Return statuses: // - global (see Client docs). func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) (*ResAnnounceSpace, error) { - // check parameters - if len(prm.announcements) == 0 { - return nil, errorMissingAnnouncements + req, err := prm.formRequest(c) + if err != nil { + return nil, err } - // convert list of SDK announcement structures into FrostFS-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 FrostFS-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 ( @@ -77,10 +80,10 @@ func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounce c.initCallContext(&cc) cc.meta = prm.prmCommonMeta - cc.req = &req + cc.req = req cc.statusRes = &res 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