Skip to content

Commit

Permalink
[eclipse-kanto#213] Added both flags and tests.
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Milchev [email protected]
  • Loading branch information
daniel-milchev committed Dec 14, 2023
1 parent e361ff5 commit 4107cef
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 23 deletions.
62 changes: 60 additions & 2 deletions containerm/cli/cli_command_ctrs_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"fmt"
"os"
"strconv"

"strings"
"text/tabwriter"

"github.com/eclipse-kanto/container-management/containerm/client"
Expand All @@ -30,7 +32,9 @@ type listCmd struct {
}

type listConfig struct {
name string
name string
quiet bool
filter []string
}

func (cc *listCmd) init(cli *cli) {
Expand All @@ -43,7 +47,7 @@ func (cc *listCmd) init(cli *cli) {
RunE: func(cmd *cobra.Command, args []string) error {
return cc.run(args)
},
Example: "list\n list --name <container-name>\n list -n <container-name>",
Example: " list\n list --name <container-name>\n list -n <container-name>\n list -q\n list --filter <status/image/exitcode>",
}
cc.setupFlags()
}
Expand All @@ -57,6 +61,20 @@ func (cc *listCmd) run(args []string) error {
if err != nil {
return err
}
if len(cc.config.filter) > 0 && len(ctrs) > 0 {
filtered, err := filterBy(cc.config.filter, ctrs)
if err != nil {
return err
}
ctrs = filtered
}
if cc.config.quiet != false && len(ctrs) > 0 {
for _, ctr := range ctrs {
fmt.Printf("%s ", ctr.ID)
}
fmt.Println()
return nil
}
if len(ctrs) == 0 {
fmt.Println("No found containers.")
} else {
Expand All @@ -69,6 +87,46 @@ func (cc *listCmd) setupFlags() {
flagSet := cc.cmd.Flags()
// init name flags
flagSet.StringVarP(&cc.config.name, "name", "n", "", "List all containers with a specific name.")
flagSet.BoolVarP(&cc.config.quiet, "quiet", "q", false, "List only container IDs.")
flagSet.StringSliceVar(&cc.config.filter, "filter", nil, "Lists only containers with the filter.")
}

func filterBy(input []string, ctrs []*types.Container) ([]*types.Container, error) {
var (
holderStatus string
holderImage string
convertedExitCode int = -1
err error
)
filteredCtrs := []*types.Container{}
for _, inp := range input {
if strings.HasPrefix(inp, "status=") {
holderStatus = strings.TrimPrefix(inp, "status=")
} else if strings.HasPrefix(inp, "image=") {
holderImage = strings.TrimPrefix(inp, "image=")
} else if strings.HasPrefix(inp, "exitcode=") {
exitcodeHolder := strings.TrimPrefix(inp, "exitcode=")
convertedExitCode, err = strconv.Atoi(exitcodeHolder)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("No such filter.")
}
}
for _, ctr := range ctrs {
if holderStatus != "" && !strings.EqualFold(ctr.State.Status.String(), holderStatus) {
continue
}
if holderImage != "" && !strings.EqualFold(ctr.Image.Name, holderImage) {
continue
}
if int64(convertedExitCode) != -1 && ctr.State.ExitCode != int64(convertedExitCode) {
continue
}
filteredCtrs = append(filteredCtrs, ctr)
}
return filteredCtrs, nil
}

/*
Expand Down
75 changes: 74 additions & 1 deletion containerm/cli/cli_command_ctrs_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import (

const (
// command flags
listCmdFlagName = "name"
listCmdFlagName = "name"
listCmdFlagQuiet = "quiet"
listCmdFlagFilter = "filter"

// test input constants
listContainerID = "test-ctr"
Expand Down Expand Up @@ -117,6 +119,42 @@ func (listTc *listCommandTest) generateRunExecutionConfigs() map[string]testRunE
},
mockExecution: listTc.mockExecListByNameNoCtrs,
},
"test_list_quiet": {
flags: map[string]string{
listCmdFlagQuiet: "true",
},
mockExecution: listTc.mockExecListQuiet,
},
"test_list_with_filter_status": {
flags: map[string]string{
listCmdFlagFilter: "status=creating",
},
mockExecution: listTc.mockExecListWithFilter,
},
"test_list_with_filter_image": {
flags: map[string]string{
listCmdFlagFilter: "image=test",
},
mockExecution: listTc.mockExecListWithFilter,
},
"test_list_with_filter_exit_code": {
flags: map[string]string{
listCmdFlagFilter: "exitcode=0",
},
mockExecution: listTc.mockExecListWithFilter,
},
"test_list_with_multiple_filters": {
flags: map[string]string{
listCmdFlagFilter: "image=test,exitcode=0",
},
mockExecution: listTc.mockExecListWithFilter,
},
"test_list_with_filter_error": {
flags: map[string]string{
listCmdFlagFilter: "test=test",
},
mockExecution: listTc.mockExecListWithFilterError,
},
"test_list_by_name_err": {
flags: map[string]string{
listCmdFlagName: listFlagName,
Expand Down Expand Up @@ -172,6 +210,41 @@ func (listTc *listCommandTest) mockExecListByNameNoCtrs(args []string) error {
return nil
}

func (listTc *listCommandTest) mockExecListQuiet(args []string) error {
// setup expected calls
ctrs := []*types.Container{{
ID: listContainerID,
Name: listFlagName,
State: &types.State{},
}}
listTc.mockClient.EXPECT().List(context.Background()).Times(1).Return(ctrs, nil)
// no error expected
return nil
}

func (listTc *listCommandTest) mockExecListWithFilter(args []string) error {
// setup expected calls
ctrs := []*types.Container{{
ID: listContainerID,
Name: listFlagName,
State: &types.State{},
}}
listTc.mockClient.EXPECT().List(context.Background()).Times(1).Return(ctrs, nil)
// no error expected
return nil
}

func (listTc *listCommandTest) mockExecListWithFilterError(args []string) error {
err := log.NewError("No such filter.")
ctrs := []*types.Container{{
ID: listContainerID,
Name: listFlagName,
State: &types.State{},
}}
listTc.mockClient.EXPECT().List(context.Background()).Times(1).Return(ctrs, nil)
return err
}

func (listTc *listCommandTest) mockExecListByNameErrors(args []string) error {
// setup expected calls
err := log.NewError("failed to get containers list")
Expand Down
48 changes: 32 additions & 16 deletions integration/framework/cli/cmd_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ func RunCmdTestCases(t *testing.T, cmdList []TestCaseCMD) {
if cmd.setupCmd != nil {
runMultipleCommands(t, *cmd.setupCmd)
}
result := icmd.RunCmd(cmd.icmd)
checkArguments(t, &cmd.icmd)
fmt.Printf("Running command: %s %s\n", cmd.icmd.Command[0], cmd.icmd.Command[1:])
result := icmd.RunCommand(cmd.icmd.Command[0], cmd.icmd.Command[1:]...)
// result := icmd.RunCmd(cmd.icmd)
if cmd.goldenFile != "" {
assert.Assert(t, golden.String(result.Stdout(), cmd.goldenFile))
}
Expand All @@ -122,25 +125,36 @@ func RunCmdTestCases(t *testing.T, cmdList []TestCaseCMD) {
}
}

func runMultipleCommands(t *testing.T, cmdArr []icmd.Cmd) {
for _, cmd := range cmdArr {
result := icmd.RunCmd(cmd)
result.Assert(t, icmd.Expected{ExitCode: 0})
}
}

func buildCmd(binary string, args ...string) *icmd.Cmd {
envArgs := []string{}
for _, arg := range args {
func checkArguments(t *testing.T, cmd *icmd.Cmd) {
execCmd := []string{}
for _, arg := range cmd.Command {
if strings.HasPrefix(arg, "$(") && strings.HasSuffix(arg, ")") {
arg = strings.TrimPrefix(arg, "$(")
arg = strings.TrimSuffix(arg, ")")
arguments := strings.Split(arg, " ")
cmd := icmd.Command(arguments[0], arguments[1:]...)
checkArguments(t, &cmd)
result := icmd.RunCmd(cmd)
assert.Equal(t, result.ExitCode, 0)
execCmd = append(execCmd, strings.Split(strings.TrimSuffix(strings.TrimSuffix(result.Stdout(), "\n"), " "), " ")...)
continue
}
if strings.HasPrefix(arg, "$") {
if val, ok := os.LookupEnv(strings.TrimPrefix(arg, "$")); ok {
arg = val
}
}
envArgs = append(envArgs, arg)
execCmd = append(execCmd, arg)
}
*cmd = icmd.Cmd{Command: execCmd}
}

func runMultipleCommands(t *testing.T, cmdArr []icmd.Cmd) {
for _, cmd := range cmdArr {
checkArguments(t, &cmd)
result := icmd.RunCommand(cmd.Command[0], cmd.Command[1:]...)
result.Assert(t, icmd.Expected{ExitCode: 0})
}
cmd := icmd.Command(binary, envArgs...)
return &cmd
}

func assertCustomResult(t *testing.T, result icmd.Result, name string, args ...string) {
Expand All @@ -152,7 +166,8 @@ func assertCustomResult(t *testing.T, result icmd.Result, name string, args ...s
func fromAPITestCommand(cmd TestCommand) TestCaseCMD {
return TestCaseCMD{
name: cmd.Name,
icmd: *buildCmd(cmd.Command.Binary, cmd.Command.Args...),
icmd: icmd.Command(cmd.Command.Binary, cmd.Command.Args...),
// icmd: *checkArguments(cmd.Command.Binary, cmd.Command.Args...),
expected: icmd.Expected{
ExitCode: cmd.Expected.ExitCode,
Timeout: cmd.Expected.Timeout,
Expand All @@ -174,7 +189,8 @@ func buildCmdArrFromCommand(cmd *[]Command) *[]icmd.Cmd {
}
cmds := make([]icmd.Cmd, 0)
for _, cmd := range *cmd {
cmds = append(cmds, *buildCmd(cmd.Binary, cmd.Args...))
cmds = append(cmds, icmd.Command(cmd.Binary, cmd.Args...))
// cmds = append(cmds, *checkArguments(cmd.Binary, cmd.Args...))
}
return &cmds
}
10 changes: 7 additions & 3 deletions integration/testdata/list-help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ Usage:
kanto-cm list

Examples:
list
list
list --name <container-name>
list -n <container-name>
list -q
list --filter <status/image/exitcode>

Flags:
-h, --help help for list
-n, --name string List all containers with a specific name.
--filter strings Lists only containers with the filter.
-h, --help help for list
-n, --name string List all containers with a specific name.
-q, --quiet List only container IDs.

Global Flags:
--debug Switch commands log level to DEBUG mode
Expand Down
20 changes: 20 additions & 0 deletions integration/testdata/list-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,26 @@ onExit:
- binary: "kanto-cm"
args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_state_created", "-f"]
---
name: list_containers_with_quiet
setupCmd:
- binary: kanto-cm
args: ["create", "--host", "$KANTO_HOST", "-n", "list_containers_with_quiet_one", "docker.io/library/influxdb:1.8.4"]
- binary: kanto-cm
args: ["create", "--host", "$KANTO_HOST", "-n", "list_containers_with_quiet_two", "docker.io/library/influxdb:1.8.4"]
command:
binary: kanto-cm
args: ["list", "--host", "$KANTO_HOST", "-q"]
expected:
exitCode: 0
customResult:
type: REGEX
args: ["[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"]
onExit:
- binary: "kanto-cm"
args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_quiet_one", "-f"]
- binary: "kanto-cm"
args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_quiet_two", "-f"]
---
name: list_existing_container
setupCmd:
- binary: kanto-cm
Expand Down
14 changes: 13 additions & 1 deletion integration/testdata/remove-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,16 @@ onExit:
- binary: kanto-cm
args: ["stop", "--host", "$KANTO_HOST", "-s", "SIGKILL", "-n", "remove_container_with_state_running"]
- binary: "kanto-cm"
args: ["remove", "--host", "$KANTO_HOST", "-n", "remove_container_with_state_running", "-f"]
args: ["remove", "--host", "$KANTO_HOST", "-n", "remove_container_with_state_running", "-f"]
---
name: remove_multiple_containers
setupCmd:
- binary: kanto-cm
args: ["create", "--host", "$KANTO_HOST", "-n", "remove_container_one", "docker.io/library/influxdb:1.8.4"]
- binary: kanto-cm
args: ["create", "--host", "$KANTO_HOST", "-n", "remove_container_two", "docker.io/library/influxdb:1.8.4"]
command:
binary: kanto-cm
args: ["remove", "--host", "$KANTO_HOST", "$(kanto-cm list --quiet)"]
expected:
exitCode: 0

0 comments on commit 4107cef

Please sign in to comment.