package tree import ( "crypto/sha256" "errors" "io" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) var getSubtreeCmd = &cobra.Command{ Use: "get-subtree", Short: "Get subtree", Run: getSubTree, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) }, } func initGetSubtreeCmd() { commonflags.Init(getSubtreeCmd) initCTID(getSubtreeCmd) ff := getSubtreeCmd.Flags() ff.Uint64(rootIDFlagKey, 0, "Root ID to traverse from.") ff.Uint32(depthFlagKey, 10, "Traversal depth.") ff.Bool(orderFlagKey, false, "Sort output by ascending FileName.") _ = getSubtreeCmd.MarkFlagRequired(commonflags.CIDFlag) _ = getSubtreeCmd.MarkFlagRequired(treeIDFlagKey) _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func getSubTree(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) cidString, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID err := cnr.DecodeString(cidString) commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) ctx, cancel := contextWithTimeout(cmd) defer cancel() cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) tid, _ := cmd.Flags().GetString(treeIDFlagKey) rid, _ := cmd.Flags().GetUint64(rootIDFlagKey) depth, _ := cmd.Flags().GetUint32(depthFlagKey) order, _ := cmd.Flags().GetBool(orderFlagKey) bodyOrder := tree.GetSubTreeRequest_Body_Order_None if order { bodyOrder = tree.GetSubTreeRequest_Body_Order_Asc } var bt []byte if t := common.ReadBearerToken(cmd, bearerFlagKey); t != nil { bt = t.Marshal() } req := &tree.GetSubTreeRequest{ Body: &tree.GetSubTreeRequest_Body{ ContainerId: rawCID, TreeId: tid, RootId: []uint64{rid}, Depth: depth, BearerToken: bt, OrderBy: &tree.GetSubTreeRequest_Body_Order{ Direction: bodyOrder, }, }, } commonCmd.ExitOnErr(cmd, "signing message: %w", tree.SignMessage(req, pk)) resp, err := cli.GetSubTree(ctx, req) commonCmd.ExitOnErr(cmd, "failed to call getSubTree: %w", err) subtreeResp, err := resp.Recv() for ; err == nil; subtreeResp, err = resp.Recv() { b := subtreeResp.GetBody() if len(b.GetNodeId()) == 1 { cmd.Printf("Node ID: %d\n", b.GetNodeId()) cmd.Println("\tParent ID: ", b.GetParentId()) cmd.Println("\tTimestamp: ", b.GetTimestamp()) } else { cmd.Printf("Node IDs: %v\n", b.GetNodeId()) cmd.Println("\tParent IDs: ", b.GetParentId()) cmd.Println("\tTimestamps: ", b.GetTimestamp()) } if meta := b.GetMeta(); len(meta) > 0 { cmd.Println("\tMeta pairs: ") for _, kv := range meta { cmd.Printf("\t\t%s: %s\n", kv.GetKey(), string(kv.GetValue())) } } } if !errors.Is(err, io.EOF) { commonCmd.ExitOnErr(cmd, "rpc call: %w", err) } }