From fa16c9c8c8c1c81268430baeb4b4300e8fde6d31 Mon Sep 17 00:00:00 2001 From: Frank Ittermann Date: Thu, 22 Apr 2021 13:38:20 +0200 Subject: [PATCH 1/4] Add lsa command This commands list all child paths from a given parent path. Be careful to run from the root vault path. Can result in out of memory depends on the size of the vault. --- cli/command.go | 2 ++ cli/lsall.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ client/client.go | 14 ++++++++- client/list.go | 42 +++++++++++++++++++++++-- 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 cli/lsall.go diff --git a/cli/command.go b/cli/command.go index ca1557bf..4cbc7bcd 100644 --- a/cli/command.go +++ b/cli/command.go @@ -28,6 +28,7 @@ type Commands struct { Cp *CopyCommand Grep *GrepCommand Ls *ListCommand + Lsa *ListAllCommand Mv *MoveCommand Replace *ReplaceCommand Rm *RemoveCommand @@ -53,6 +54,7 @@ func NewCommands(client *client.Client) *Commands { Cp: NewCopyCommand(client), Grep: NewGrepCommand(client), Ls: NewListCommand(client), + Lsa: NewListAllCommand(client), Mv: NewMoveCommand(client), Replace: NewReplaceCommand(client), Rm: NewRemoveCommand(client), diff --git a/cli/lsall.go b/cli/lsall.go new file mode 100644 index 00000000..fe506667 --- /dev/null +++ b/cli/lsall.go @@ -0,0 +1,82 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/fishi0x01/vsh/client" + "github.com/fishi0x01/vsh/log" +) + +// ListCommand container for 'ls' parameters +type ListAllCommand struct { + name string + args *ListAllCommandArgs + + client *client.Client +} + +// ListCommandArgs provides a struct for go-arg parsing +type ListAllCommandArgs struct { + Path string `arg:"positional" help:"path to list all child paths of, defaults to current path"` +} + +// Description provides detail on what the command does +func (ListAllCommandArgs) Description() string { + return "lists all child paths from the a given parent path" +} + +// NewListCommand creates a new ListCommand parameter container +func NewListAllCommand(c *client.Client) *ListAllCommand { + return &ListAllCommand{ + name: "lsa", + client: c, + args: &ListAllCommandArgs{}, + } +} + +// GetName returns the ListCommand's name identifier +func (cmd *ListAllCommand) GetName() string { + return cmd.name +} + +// GetArgs provides the struct holding arguments for the command +func (cmd *ListAllCommand) GetArgs() interface{} { + return cmd.args +} + +// IsSane returns true if command is sane +func (cmd *ListAllCommand) IsSane() bool { + return cmd.args.Path != "" +} + +// PrintUsage print command usage +func (cmd *ListAllCommand) PrintUsage() { + fmt.Println(Help(cmd)) +} + +// Parse given arguments and return status +func (cmd *ListAllCommand) Parse(args []string) error { + _, err := parseCommandArgs(args, cmd) + if err != nil { + return err + } + if cmd.args.Path == "" { + cmd.args.Path = cmd.client.Pwd + } + + return nil +} + +// Run executes 'ls' with given ListCommand's parameters +func (cmd *ListAllCommand) Run() int { + newPwd := cmdPath(cmd.client.Pwd, cmd.args.Path) + result, err := cmd.client.ListAll(newPwd) + + if err != nil { + log.UserError("Not a valid path for operation: %s", newPwd) + return 1 + } + log.UserInfo(strings.Join(result, "\n")) + return 0 +} diff --git a/client/client.go b/client/client.go index ffed953f..32b4a1a8 100644 --- a/client/client.go +++ b/client/client.go @@ -137,7 +137,19 @@ func (client *Client) List(absolutePath string) (result []string, err error) { if client.isTopLevelPath(absolutePath) { result = client.listTopLevel() } else { - result, err = client.listLowLevel(normalizedVaultPath(absolutePath)) + result, err = client.listLowLevel(normalizedVaultPath(absolutePath), MODE_DIRECTORY_ONLY) + } + return result, err +} + +// List elements at the given absolutePath, using the given client +func (client *Client) ListAll(absolutePath string) (result []string, err error) { + if client.isTopLevelPath(absolutePath) { + result, err = client.listAllFromTopLevel() + } else { + res:= []string{} + result, err = client.listAllLowLevel(normalizedVaultPath(absolutePath), &res) + result = res } return result, err } diff --git a/client/list.go b/client/list.go index 727b37c4..9572dbb5 100644 --- a/client/list.go +++ b/client/list.go @@ -2,9 +2,16 @@ package client import ( "errors" + _"fmt" + "github.com/fishi0x01/vsh/log" ) +const ( + MODE_IGNORE_NONE_DIRECTORY = 0 + MODE_DIRECTORY_ONLY = 1 +) + func (client *Client) listTopLevel() (result []string) { for k := range client.KVBackends { result = append(result, k) @@ -12,10 +19,14 @@ func (client *Client) listTopLevel() (result []string) { return result } -func (client *Client) listLowLevel(path string) (result []string, err error) { +func (client *Client) listLowLevel(path string, mode int) (result []string, err error) { t := client.lowLevelType(path) if t != BACKEND && t != NODE { - return nil, errors.New("Not a directory: " + path) + if mode == MODE_DIRECTORY_ONLY { + return nil, errors.New("Not a directory: " + path) + } else if mode == MODE_IGNORE_NONE_DIRECTORY { + return nil, nil + } } s, err := client.cache.List(client.getKVMetaDataPath(path)) @@ -35,3 +46,30 @@ func (client *Client) listLowLevel(path string) (result []string, err error) { return result, err } + +func (client *Client) listAllLowLevel(path string, subResult* []string) (result[]string, err error) { + // fmt.Printf("lookup root %s\n", path) + subResult2, err := client.listLowLevel(path, MODE_IGNORE_NONE_DIRECTORY) + if subResult2 != nil { + var subResult3 []string + for _, resultPath := range subResult2 { + // fmt.Printf("lookup loop %s\n", path +resultPath) + _, err := client.listAllLowLevel(normalizedVaultPath(path + resultPath), subResult) + if err != nil { + log.AppTrace("%+v", err) + return subResult3, err + } + result = append(result, normalizedVaultPath(path + resultPath)) + } + } + *subResult = append(*subResult, result...) + return *subResult, err +} + +func (client *Client) listAllFromTopLevel() (result []string, err error) { + res:= []string{} + for k := range client.KVBackends { + result, err = client.listAllLowLevel(normalizedVaultPath(k), &res) + } + return result, err +} \ No newline at end of file From 16bd227722252c9fd7d4f135d4f5962c97bfff37 Mon Sep 17 00:00:00 2001 From: Frank Ittermann Date: Thu, 22 Apr 2021 16:21:02 +0200 Subject: [PATCH 2/4] Only return full path not sub path Instead of returning ``` secret/environment/dev/petshop secret/environment/dev secret/environment ``` it return's only the full path. ``` secret/environment/dev/petshop ``` --- client/list.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/list.go b/client/list.go index 9572dbb5..dfc7b919 100644 --- a/client/list.go +++ b/client/list.go @@ -48,12 +48,10 @@ func (client *Client) listLowLevel(path string, mode int) (result []string, err } func (client *Client) listAllLowLevel(path string, subResult* []string) (result[]string, err error) { - // fmt.Printf("lookup root %s\n", path) subResult2, err := client.listLowLevel(path, MODE_IGNORE_NONE_DIRECTORY) if subResult2 != nil { var subResult3 []string for _, resultPath := range subResult2 { - // fmt.Printf("lookup loop %s\n", path +resultPath) _, err := client.listAllLowLevel(normalizedVaultPath(path + resultPath), subResult) if err != nil { log.AppTrace("%+v", err) @@ -61,8 +59,9 @@ func (client *Client) listAllLowLevel(path string, subResult* []string) (result[ } result = append(result, normalizedVaultPath(path + resultPath)) } + } else { + *subResult = append(*subResult, path) } - *subResult = append(*subResult, result...) return *subResult, err } From cf457b09abb2aba8c194ce5319adc00c4f6716a4 Mon Sep 17 00:00:00 2001 From: Frank Ittermann Date: Tue, 14 Sep 2021 13:49:02 +0200 Subject: [PATCH 3/4] Fix Run function comment --- cli/lsall.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/lsall.go b/cli/lsall.go index fe506667..4b4c09f2 100644 --- a/cli/lsall.go +++ b/cli/lsall.go @@ -68,7 +68,7 @@ func (cmd *ListAllCommand) Parse(args []string) error { return nil } -// Run executes 'ls' with given ListCommand's parameters +// Run executes 'ls' with given ListAllCommand's parameters func (cmd *ListAllCommand) Run() int { newPwd := cmdPath(cmd.client.Pwd, cmd.args.Path) result, err := cmd.client.ListAll(newPwd) From df65bf52ffc5082c11e540e32ca9703f97601baf Mon Sep 17 00:00:00 2001 From: Frank Ittermann Date: Tue, 14 Sep 2021 13:49:45 +0200 Subject: [PATCH 4/4] Use the already implemented traverse functions --- client/client.go | 8 +++----- client/list.go | 39 ++------------------------------------- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/client/client.go b/client/client.go index 32b4a1a8..748cf258 100644 --- a/client/client.go +++ b/client/client.go @@ -137,7 +137,7 @@ func (client *Client) List(absolutePath string) (result []string, err error) { if client.isTopLevelPath(absolutePath) { result = client.listTopLevel() } else { - result, err = client.listLowLevel(normalizedVaultPath(absolutePath), MODE_DIRECTORY_ONLY) + result, err = client.listLowLevel(normalizedVaultPath(absolutePath)) } return result, err } @@ -145,11 +145,9 @@ func (client *Client) List(absolutePath string) (result []string, err error) { // List elements at the given absolutePath, using the given client func (client *Client) ListAll(absolutePath string) (result []string, err error) { if client.isTopLevelPath(absolutePath) { - result, err = client.listAllFromTopLevel() + result = client.topLevelTraverse() } else { - res:= []string{} - result, err = client.listAllLowLevel(normalizedVaultPath(absolutePath), &res) - result = res + result = client.lowLevelTraverse(normalizedVaultPath(absolutePath), false) } return result, err } diff --git a/client/list.go b/client/list.go index dfc7b919..96f0e8c5 100644 --- a/client/list.go +++ b/client/list.go @@ -7,11 +7,6 @@ import ( "github.com/fishi0x01/vsh/log" ) -const ( - MODE_IGNORE_NONE_DIRECTORY = 0 - MODE_DIRECTORY_ONLY = 1 -) - func (client *Client) listTopLevel() (result []string) { for k := range client.KVBackends { result = append(result, k) @@ -19,14 +14,10 @@ func (client *Client) listTopLevel() (result []string) { return result } -func (client *Client) listLowLevel(path string, mode int) (result []string, err error) { +func (client *Client) listLowLevel(path string) (result []string, err error) { t := client.lowLevelType(path) if t != BACKEND && t != NODE { - if mode == MODE_DIRECTORY_ONLY { - return nil, errors.New("Not a directory: " + path) - } else if mode == MODE_IGNORE_NONE_DIRECTORY { - return nil, nil - } + return nil, errors.New("Not a directory: " + path) } s, err := client.cache.List(client.getKVMetaDataPath(path)) @@ -46,29 +37,3 @@ func (client *Client) listLowLevel(path string, mode int) (result []string, err return result, err } - -func (client *Client) listAllLowLevel(path string, subResult* []string) (result[]string, err error) { - subResult2, err := client.listLowLevel(path, MODE_IGNORE_NONE_DIRECTORY) - if subResult2 != nil { - var subResult3 []string - for _, resultPath := range subResult2 { - _, err := client.listAllLowLevel(normalizedVaultPath(path + resultPath), subResult) - if err != nil { - log.AppTrace("%+v", err) - return subResult3, err - } - result = append(result, normalizedVaultPath(path + resultPath)) - } - } else { - *subResult = append(*subResult, path) - } - return *subResult, err -} - -func (client *Client) listAllFromTopLevel() (result []string, err error) { - res:= []string{} - for k := range client.KVBackends { - result, err = client.listAllLowLevel(normalizedVaultPath(k), &res) - } - return result, err -} \ No newline at end of file