From 14f85184ab02dfe992f3b1231c111ea507d3801f Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Tue, 22 Sep 2020 16:53:33 +0300 Subject: [PATCH] [#37] Implement container related morph wrapper functions Container get wrapper implements container.Source interface so it can be used in object service as container storage. Signed-off-by: Alex Vanin --- .../client/container/wrapper/container.go | 138 ++++++++++++++++-- pkg/morph/client/container/wrapper/wrapper.go | 4 - 2 files changed, 124 insertions(+), 18 deletions(-) diff --git a/pkg/morph/client/container/wrapper/container.go b/pkg/morph/client/container/wrapper/container.go index c049c8aa..8fa408a8 100644 --- a/pkg/morph/client/container/wrapper/container.go +++ b/pkg/morph/client/container/wrapper/container.go @@ -1,20 +1,53 @@ package wrapper -// OwnerID represents the container owner identifier. -// FIXME: correct the definition. -type OwnerID struct{} +import ( + "crypto/sha256" -// Container represents the NeoFS Container structure. -// FIXME: correct the definition. -type Container struct{} + "github.com/nspcc-dev/neofs-api-go/pkg/container" + "github.com/nspcc-dev/neofs-api-go/pkg/owner" + v2container "github.com/nspcc-dev/neofs-api-go/v2/container" + msgContainer "github.com/nspcc-dev/neofs-api-go/v2/container/grpc" + v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs" + msgRefs "github.com/nspcc-dev/neofs-api-go/v2/refs/grpc" + core "github.com/nspcc-dev/neofs-node/pkg/core/container" + client "github.com/nspcc-dev/neofs-node/pkg/morph/client/container" + "github.com/pkg/errors" +) + +var ( + errNilArgument = errors.New("empty argument") + errUnsupported = errors.New("unsupported structure version") +) // Put saves passed container structure in NeoFS system // through Container contract call. // // Returns calculated container identifier and any error // encountered that caused the saving to interrupt. -func (w *Wrapper) Put(cnr *Container) (*CID, error) { - panic("implement me") +func (w *Wrapper) Put(cnr *container.Container, pubKey, signature []byte) (*container.ID, error) { + if cnr == nil || len(pubKey) == 0 || len(signature) == 0 { + return nil, errNilArgument + } + + args := client.PutArgs{} + args.SetPublicKey(pubKey) + args.SetSignature(signature) + + id := new(container.ID) + + if v2 := cnr.ToV2(); v2 == nil { + return nil, errUnsupported // use other major version if there any + } else { + data, err := v2.StableMarshal(nil) + if err != nil { + return nil, errors.Wrap(err, "can't marshal container") + } + + id.SetSHA256(sha256.Sum256(data)) + args.SetContainer(data) + } + + return id, w.client.Put(args) } // Get reads the container from NeoFS system by identifier @@ -22,8 +55,37 @@ func (w *Wrapper) Put(cnr *Container) (*CID, error) { // // If an empty slice is returned for the requested identifier, // storage.ErrNotFound error is returned. -func (w *Wrapper) Get(cid CID) (*Container, error) { - panic("implement me") +func (w *Wrapper) Get(cid *container.ID) (*container.Container, error) { + if cid == nil { + return nil, errNilArgument + } + + args := client.GetArgs{} + + if v2 := cid.ToV2(); v2 == nil { + return nil, errUnsupported // use other major version if there any + } else { + args.SetCID(v2.GetValue()) + } + + // ask RPC neo node to get serialized container + rpcAnswer, err := w.client.Get(args) + if err != nil { + return nil, errors.Wrap(core.ErrNotFound, err.Error()) + } + + // convert serialized bytes into GRPC structure + grpcMsg := new(msgContainer.Container) + err = grpcMsg.Unmarshal(rpcAnswer.Container()) + if err != nil { + // use other major version if there any + return nil, errors.Wrap(err, "can't unmarshal container") + } + + // convert GRPC structure into SDK structure, used in the code + v2Cnr := v2container.ContainerFromGRPCMessage(grpcMsg) + + return container.NewContainerFromV2(v2Cnr), nil } // Delete removes the container from NeoFS system @@ -31,8 +93,21 @@ func (w *Wrapper) Get(cid CID) (*Container, error) { // // Returns any error encountered that caused // the removal to interrupt. -func (w *Wrapper) Delete(cid CID) error { - panic("implement me") +func (w *Wrapper) Delete(cid *container.ID, signature []byte) error { + if cid == nil || len(signature) == 0 { + return errNilArgument + } + + args := client.DeleteArgs{} + args.SetSignature(signature) + + if v2 := cid.ToV2(); v2 == nil { + return errUnsupported // use other major version if there any + } else { + args.SetCID(v2.GetValue()) + } + + return w.client.Delete(args) } // List returns a list of container identifiers belonging @@ -41,6 +116,41 @@ func (w *Wrapper) Delete(cid CID) error { // // Returns the identifiers of all NeoFS containers if pointer // to owner identifier is nil. -func (w *Wrapper) List(ownerID *OwnerID) ([]CID, error) { - panic("implement me") +func (w *Wrapper) List(ownerID *owner.ID) ([]*container.ID, error) { + args := client.ListArgs{} + + if ownerID == nil { + args.SetOwnerID([]byte{}) + } else if v2 := ownerID.ToV2(); v2 == nil { + return nil, errUnsupported // use other major version if there any + } else { + args.SetOwnerID(v2.GetValue()) + } + + // ask RPC neo node to get serialized container + rpcAnswer, err := w.client.List(args) + if err != nil { + return nil, err + } + + rawIDs := rpcAnswer.CIDList() + result := make([]*container.ID, 0, len(rawIDs)) + + for i := range rawIDs { + // convert serialized bytes into GRPC structure + grpcMsg := new(msgRefs.ContainerID) + err = grpcMsg.Unmarshal(rawIDs[i]) + if err != nil { + // use other major version if there any + return nil, errors.Wrap(err, "can't unmarshal container id") + } + + // convert GRPC structure into SDK structure, used in the code + v2 := v2refs.ContainerIDFromGRPCMessage(grpcMsg) + cid := container.NewIDFromV2(v2) + + result = append(result, cid) + } + + return result, nil } diff --git a/pkg/morph/client/container/wrapper/wrapper.go b/pkg/morph/client/container/wrapper/wrapper.go index 18b0d1f1..e7c469b1 100644 --- a/pkg/morph/client/container/wrapper/wrapper.go +++ b/pkg/morph/client/container/wrapper/wrapper.go @@ -10,10 +10,6 @@ import ( // github.com/nspcc-dev/neofs-node/pkg/morph/client/container.Client. type Client = container.Client -// CID represents the container identifier. -// FIXME: correct the definition. -type CID struct{} - // Wrapper is a wrapper over container contract // client which implements container storage and // eACL storage methods.