From 9534ade71674ee39e98fd079b4e3bfb7dd8e103f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 22 Mar 2023 17:25:35 +0300 Subject: [PATCH] [#161] adm: Refactor restore-containers command Resolve funlen linter for restoreContainers function Signed-off-by: Dmitrii Stepanov --- .../internal/modules/morph/container.go | 117 ++++++++++++------ 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index 1dec6127..9bc6cae4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -152,7 +152,6 @@ func listContainers(cmd *cobra.Command, _ []string) error { return nil } -// nolint: funlen func restoreContainers(cmd *cobra.Command, _ []string) error { filename, err := cmd.Flags().GetString(containerDumpFlag) if err != nil { @@ -165,25 +164,14 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { } defer wCtx.close() - nnsCs, err := wCtx.Client.GetContractStateByID(1) + containers, err := parseContainers(filename) if err != nil { - return fmt.Errorf("can't get NNS contract state: %w", err) + return err } - ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, containerContract+".frostfs") + ch, err := fetchContainerContractHash(wCtx) if err != nil { - return fmt.Errorf("can't fetch container contract hash: %w", err) - } - - data, err := os.ReadFile(filename) - if err != nil { - return fmt.Errorf("can't read dump file: %w", err) - } - - var containers []Container - err = json.Unmarshal(data, &containers) - if err != nil { - return fmt.Errorf("can't parse dump file: %w", err) + return err } isOK, err := getCIDFilterFunc(cmd) @@ -191,6 +179,15 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return err } + err = restoreOrPutContainers(containers, isOK, cmd, wCtx, ch) + if err != nil { + return err + } + + return wCtx.awaitTx() +} + +func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *initializeContext, ch util.Uint160) error { bw := io.NewBufBinWriter() for _, cnt := range containers { hv := hash.Sha256(cnt.Value) @@ -198,33 +195,18 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { continue } bw.Reset() - emit.AppCall(bw.BinWriter, ch, "get", callflag.All, hv.BytesBE()) - res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) + restored, err := isContainerRestored(cmd, wCtx, ch, bw, hv) if err != nil { - return fmt.Errorf("can't check if container is already restored: %w", err) + return err } - if len(res.Stack) == 0 { - return errors.New("empty stack") - } - - old := new(Container) - if err := old.FromStackItem(res.Stack[0]); err != nil { - return fmt.Errorf("%w: %v", errInvalidContainerResponse, err) - } - if len(old.Value) != 0 { - var id cid.ID - id.SetSHA256(hv) - cmd.Printf("Container %s is already deployed.\n", id) + if restored { continue } bw.Reset() - emit.AppCall(bw.BinWriter, ch, "put", callflag.All, - cnt.Value, cnt.Signature, cnt.PublicKey, cnt.Token) - if ea := cnt.EACL; ea != nil { - emit.AppCall(bw.BinWriter, ch, "setEACL", callflag.All, - ea.Value, ea.Signature, ea.PublicKey, ea.Token) - } + + putContainer(bw, ch, cnt) + if bw.Err != nil { panic(bw.Err) } @@ -233,8 +215,67 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return err } } + return nil +} - return wCtx.awaitTx() +func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) { + emit.AppCall(bw.BinWriter, ch, "put", callflag.All, + cnt.Value, cnt.Signature, cnt.PublicKey, cnt.Token) + if ea := cnt.EACL; ea != nil { + emit.AppCall(bw.BinWriter, ch, "setEACL", callflag.All, + ea.Value, ea.Signature, ea.PublicKey, ea.Token) + } +} + +func isContainerRestored(cmd *cobra.Command, wCtx *initializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { + emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE()) + res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) + if err != nil { + return false, fmt.Errorf("can't check if container is already restored: %w", err) + } + if len(res.Stack) == 0 { + return false, errors.New("empty stack") + } + + old := new(Container) + if err := old.FromStackItem(res.Stack[0]); err != nil { + return false, fmt.Errorf("%w: %v", errInvalidContainerResponse, err) + } + if len(old.Value) != 0 { + var id cid.ID + id.SetSHA256(hashValue) + cmd.Printf("Container %s is already deployed.\n", id) + return true, nil + } + + return false, nil +} + +func parseContainers(filename string) ([]Container, error) { + data, err := os.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("can't read dump file: %w", err) + } + + var containers []Container + err = json.Unmarshal(data, &containers) + if err != nil { + return nil, fmt.Errorf("can't parse dump file: %w", err) + } + return containers, nil +} + +func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { + nnsCs, err := wCtx.Client.GetContractStateByID(1) + if err != nil { + return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) + } + + ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, containerContract+".frostfs") + if err != nil { + return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) + } + return ch, nil } // Container represents container struct in contract storage.