forked from TrueCloudLab/frostfs-node
Ekaterina Lebedeva
af64263b93
* Added new method for listing containers to container service. It opens stream and sends containers in batches. * Added TransportSplitter wrapper around ExecutionService to split container ID list read from contract in parts that are smaller than grpc max message size. Batch size can be changed in node configuration file (as in example config file). * Changed `container list` implementaion in cli: now ListStream is called by default. Old List is called only if ListStream is not implemented. Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
147 lines
4.1 KiB
Go
147 lines
4.1 KiB
Go
package container
|
|
|
|
import (
|
|
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
"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"
|
|
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
"github.com/spf13/cobra"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
// flags of list command.
|
|
const (
|
|
flagListPrintAttr = "with-attr"
|
|
flagListContainerOwner = "owner"
|
|
flagListName = "name"
|
|
|
|
generateKeyContainerUsage = commonflags.GenerateKeyUsage + ", should be used with --owner flag"
|
|
)
|
|
|
|
// flag vars of list command.
|
|
var (
|
|
flagVarListPrintAttr bool
|
|
flagVarListContainerOwner string
|
|
flagVarListName string
|
|
)
|
|
|
|
var listContainersCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all created containers",
|
|
Long: "List all created containers",
|
|
Run: func(cmd *cobra.Command, _ []string) {
|
|
var idUser user.ID
|
|
|
|
generateKey, _ := cmd.Flags().GetBool(commonflags.GenerateKey)
|
|
if flagVarListContainerOwner == "" && generateKey {
|
|
cmd.PrintErrln("WARN: using -g without --owner - output will be empty")
|
|
}
|
|
|
|
key := key.GetOrGenerate(cmd)
|
|
|
|
if flagVarListContainerOwner == "" {
|
|
user.IDFromKey(&idUser, key.PublicKey)
|
|
} else {
|
|
err := idUser.DecodeString(flagVarListContainerOwner)
|
|
commonCmd.ExitOnErr(cmd, "invalid user ID: %w", err)
|
|
}
|
|
|
|
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
|
|
|
var prm internalclient.ListContainersPrm
|
|
prm.SetClient(cli)
|
|
prm.OwnerID = idUser
|
|
prmGet := internalclient.GetContainerPrm{
|
|
Client: cli,
|
|
}
|
|
var containerIDs []cid.ID
|
|
|
|
err := internalclient.ListContainersStream(cmd.Context(), prm, func(id cid.ID) {
|
|
if flagVarListName == "" && !flagVarListPrintAttr {
|
|
cmd.Println(id.String())
|
|
return
|
|
}
|
|
|
|
prmGet.ClientParams.ContainerID = &id
|
|
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
|
|
if err != nil {
|
|
cmd.Printf(" failed to read attributes: %v\n", err)
|
|
return
|
|
}
|
|
|
|
cnr := res.Container()
|
|
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
|
|
return
|
|
}
|
|
cmd.Println(id.String())
|
|
|
|
if flagVarListPrintAttr {
|
|
cnr.IterateUserAttributes(func(key, val string) {
|
|
cmd.Printf(" %s: %s\n", key, val)
|
|
})
|
|
}
|
|
})
|
|
|
|
if err != nil {
|
|
if e, ok := status.FromError(err); ok {
|
|
switch e.Code() {
|
|
case codes.Unimplemented:
|
|
res, err := internalclient.ListContainers(cmd.Context(), prm)
|
|
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
containerIDs = res.SortedIDList()
|
|
default:
|
|
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
}
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
|
|
for _, cnrID := range containerIDs {
|
|
if flagVarListName == "" && !flagVarListPrintAttr {
|
|
cmd.Println(cnrID.String())
|
|
continue
|
|
}
|
|
|
|
prmGet.ClientParams.ContainerID = &cnrID
|
|
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
|
|
if err != nil {
|
|
cmd.Printf(" failed to read attributes: %v\n", err)
|
|
continue
|
|
}
|
|
|
|
cnr := res.Container()
|
|
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
|
|
continue
|
|
}
|
|
cmd.Println(cnrID.String())
|
|
|
|
if flagVarListPrintAttr {
|
|
cnr.IterateUserAttributes(func(key, val string) {
|
|
cmd.Printf(" %s: %s\n", key, val)
|
|
})
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
func initContainerListContainersCmd() {
|
|
commonflags.Init(listContainersCmd)
|
|
|
|
flags := listContainersCmd.Flags()
|
|
|
|
flags.StringVar(&flagVarListName, flagListName, "",
|
|
"List containers by the attribute name",
|
|
)
|
|
flags.StringVar(&flagVarListContainerOwner, flagListContainerOwner, "",
|
|
"Owner of containers (omit to use owner from private key)",
|
|
)
|
|
flags.BoolVar(&flagVarListPrintAttr, flagListPrintAttr, false,
|
|
"Request and print attributes of each container",
|
|
)
|
|
flags.Lookup(commonflags.GenerateKey).Usage = generateKeyContainerUsage
|
|
}
|