forked from TrueCloudLab/frostfs-node
[#755] neofs-adm: allow to filter containers by ID
`--cid <cid1> --cid <cid2>` as well as `--cid <cid1>,<cid2>` is supported. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
00a299c1a4
commit
72b8d919fe
2 changed files with 51 additions and 0 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
@ -67,9 +68,17 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
||||||
cids = append(cids, id)
|
cids = append(cids, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isOK, err := getCIDFilterFunc(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var containers []*Container
|
var containers []*Container
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
for _, id := range cids {
|
for _, id := range cids {
|
||||||
|
if !isOK(id) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
bw.Reset()
|
bw.Reset()
|
||||||
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, id)
|
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, id)
|
||||||
emit.AppCall(bw.BinWriter, ch, "eACL", callflag.All, id)
|
emit.AppCall(bw.BinWriter, ch, "eACL", callflag.All, id)
|
||||||
|
@ -138,9 +147,17 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("can't parse dump file: %w", err)
|
return fmt.Errorf("can't parse dump file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isOK, err := getCIDFilterFunc(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
for _, cnt := range containers {
|
for _, cnt := range containers {
|
||||||
hv := hash.Sha256(cnt.Value)
|
hv := hash.Sha256(cnt.Value)
|
||||||
|
if !isOK(hv[:]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
bw.Reset()
|
bw.Reset()
|
||||||
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, hv.BytesBE())
|
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, hv.BytesBE())
|
||||||
res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil)
|
res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil)
|
||||||
|
@ -285,3 +302,34 @@ func (c *EACL) FromStackItem(item stackitem.Item) error {
|
||||||
c.Token = tok
|
c.Token = tok
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getCIDFilterFunc returns filtering function for container IDs.
|
||||||
|
// Raw byte slices are used because it works with structures returned
|
||||||
|
// from contract.
|
||||||
|
func getCIDFilterFunc(cmd *cobra.Command) (func([]byte) bool, error) {
|
||||||
|
rawIDs, err := cmd.Flags().GetStringSlice(containerIDsFlag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rawIDs) == 0 {
|
||||||
|
return func([]byte) bool { return true }, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range rawIDs {
|
||||||
|
err := cid.New().Parse(rawIDs[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't parse CID %s: %w", rawIDs[i], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(rawIDs)
|
||||||
|
return func(rawID []byte) bool {
|
||||||
|
var v [32]byte
|
||||||
|
copy(v[:], rawID)
|
||||||
|
|
||||||
|
id := cid.New()
|
||||||
|
id.SetSHA256(v)
|
||||||
|
idStr := id.String()
|
||||||
|
n := sort.Search(len(rawIDs), func(i int) bool { return rawIDs[i] >= idStr })
|
||||||
|
return n < len(rawIDs) && rawIDs[n] == idStr
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ const (
|
||||||
withdrawFeeCLIFlag = "withdraw-fee"
|
withdrawFeeCLIFlag = "withdraw-fee"
|
||||||
containerDumpFlag = "dump"
|
containerDumpFlag = "dump"
|
||||||
containerContractFlag = "container-contract"
|
containerContractFlag = "container-contract"
|
||||||
|
containerIDsFlag = "cid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -171,9 +172,11 @@ func init() {
|
||||||
dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
dumpContainersCmd.Flags().String(containerDumpFlag, "", "file where to save dumped containers")
|
dumpContainersCmd.Flags().String(containerDumpFlag, "", "file where to save dumped containers")
|
||||||
dumpContainersCmd.Flags().String(containerContractFlag, "", "container contract hash (for networks without NNS)")
|
dumpContainersCmd.Flags().String(containerContractFlag, "", "container contract hash (for networks without NNS)")
|
||||||
|
dumpContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "containers to dump")
|
||||||
|
|
||||||
RootCmd.AddCommand(restoreContainersCmd)
|
RootCmd.AddCommand(restoreContainersCmd)
|
||||||
restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir")
|
restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir")
|
||||||
restoreContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
restoreContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
restoreContainersCmd.Flags().String(containerDumpFlag, "", "file to restore containers from")
|
restoreContainersCmd.Flags().String(containerDumpFlag, "", "file to restore containers from")
|
||||||
|
restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "containers to restore")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue