diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index f93fd6686c..85d7423280 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -22,12 +22,13 @@ type Client struct { } const ( - putMethod = "put" - deleteMethod = "delete" - getMethod = "get" - listMethod = "list" - eaclMethod = "eACL" - setEACLMethod = "setEACL" + putMethod = "put" + deleteMethod = "delete" + getMethod = "get" + listMethod = "list" + containersOfMethod = "containersOf" + eaclMethod = "eACL" + setEACLMethod = "setEACL" startEstimationMethod = "startContainerEstimation" stopEstimationMethod = "stopContainerEstimation" diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go new file mode 100644 index 0000000000..8a3c7220f3 --- /dev/null +++ b/pkg/morph/client/container/containers_of.go @@ -0,0 +1,53 @@ +package container + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// ContainersOf returns a list of container identifiers belonging +// to the specified user of FrostFS system. If idUser is nil, returns the list of all containers. +// +// If remote RPC does not support neo-go session API, fallback to List() method. +func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { + var rawID []byte + + if idUser != nil { + rawID = idUser.WalletBytes() + } + + var cidList []cid.ID + cb := func(item stackitem.Item) error { + rawID, err := client.BytesFromStackItem(item) + if err != nil { + return fmt.Errorf("could not get byte array from stack item (%s): %w", containersOfMethod, err) + } + + var id cid.ID + + err = id.Decode(rawID) + if err != nil { + return fmt.Errorf("decode container ID: %w", err) + } + + cidList = append(cidList, id) + return nil + } + + cnrHash := c.client.ContractAddress() + err := c.client.Morph().TestInvokeIterator(cb, cnrHash, containersOfMethod, rawID) + if err != nil { + if errors.Is(err, unwrap.ErrNoSessionID) { + return c.List(idUser) + } + return nil, err + } + + return cidList, nil +}