From 6d01bf40621a6aa63791d793afff4e2c248c4e42 Mon Sep 17 00:00:00 2001 From: Daniel Milchev Date: Tue, 19 Dec 2023 10:40:19 +0200 Subject: [PATCH] [#213] Fixed according to comments and caught a bug with the stop timeout flag. --- containerm/cli/cli_command_ctrs_list.go | 23 +++++++++--------- containerm/cli/cli_command_ctrs_list_test.go | 20 +++++++++++----- containerm/cli/cli_command_ctrs_stop.go | 4 ++-- containerm/cli/cli_command_ctrs_stop_test.go | 2 +- integration/framework/cli/cmd_base.go | 4 ---- integration/testdata/list-help.golden | 7 +++--- integration/testdata/list-test.yaml | 25 +++++++++++++++++++- integration/testdata/stop-help.golden | 3 ++- integration/testdata/stop-test.yaml | 2 +- 9 files changed, 59 insertions(+), 31 deletions(-) diff --git a/containerm/cli/cli_command_ctrs_list.go b/containerm/cli/cli_command_ctrs_list.go index 563b359..e25e203 100644 --- a/containerm/cli/cli_command_ctrs_list.go +++ b/containerm/cli/cli_command_ctrs_list.go @@ -17,7 +17,6 @@ import ( "fmt" "os" "strconv" - "strings" "text/tabwriter" @@ -47,7 +46,7 @@ func (cc *listCmd) init(cli *cli) { RunE: func(cmd *cobra.Command, args []string) error { return cc.run(args) }, - Example: " list\n list --name \n list -n \n list -q\n list --filter ", + Example: " list\n list --name \n list --quiet\n list --filter status=created", } cc.setupFlags() } @@ -61,18 +60,21 @@ func (cc *listCmd) run(args []string) error { if err != nil { return err } - if len(cc.config.filter) > 0 && len(ctrs) > 0 { + if len(cc.config.filter) > 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) + if cc.config.quiet { + for i, ctr := range ctrs { + if i != len(ctrs)-1 { + fmt.Printf("%s ", ctr.ID) + } else { + fmt.Println(ctr.ID) + } } - fmt.Println() return nil } if len(ctrs) == 0 { @@ -88,7 +90,7 @@ func (cc *listCmd) setupFlags() { // 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.") + flagSet.StringSliceVar(&cc.config.filter, "filter", nil, "Lists only containers with a specified filter. The containers can be filtered by their status, image and exitcode.") } func filterBy(input []string, ctrs []*types.Container) ([]*types.Container, error) { @@ -105,13 +107,12 @@ func filterBy(input []string, ctrs []*types.Container) ([]*types.Container, erro } 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) + convertedExitCode, err = strconv.Atoi(strings.TrimPrefix(inp, "exitcode=")) if err != nil { return nil, err } } else { - return nil, fmt.Errorf("no such filter") + return nil, fmt.Errorf("no filter: %s", strings.Split(inp, "=")[0]) } } for _, ctr := range ctrs { diff --git a/containerm/cli/cli_command_ctrs_list_test.go b/containerm/cli/cli_command_ctrs_list_test.go index b1e341a..ee95de3 100644 --- a/containerm/cli/cli_command_ctrs_list_test.go +++ b/containerm/cli/cli_command_ctrs_list_test.go @@ -14,6 +14,7 @@ package main import ( "context" + "fmt" "testing" "github.com/eclipse-kanto/container-management/containerm/client" @@ -212,11 +213,18 @@ func (listTc *listCommandTest) mockExecListByNameNoCtrs(args []string) error { func (listTc *listCommandTest) mockExecListQuiet(args []string) error { // setup expected calls - ctrs := []*types.Container{{ - ID: listContainerID, - Name: listFlagName, - State: &types.State{}, - }} + ctrs := []*types.Container{ + { + ID: fmt.Sprintf("%s-%d", listContainerID, 1), + Name: listFlagName, + State: &types.State{}, + }, + { + ID: fmt.Sprintf("%s-%d", listContainerID, 2), + Name: listFlagName, + State: &types.State{}, + }, + } listTc.mockClient.EXPECT().List(context.Background()).Times(1).Return(ctrs, nil) // no error expected return nil @@ -235,7 +243,7 @@ func (listTc *listCommandTest) mockExecListWithFilter(args []string) error { } func (listTc *listCommandTest) mockExecListWithFilterError(args []string) error { - err := log.NewError("no such filter") + err := log.NewError("no filter: test") ctrs := []*types.Container{{ ID: listContainerID, Name: listFlagName, diff --git a/containerm/cli/cli_command_ctrs_stop.go b/containerm/cli/cli_command_ctrs_stop.go index 3a4336f..7ca2a02 100644 --- a/containerm/cli/cli_command_ctrs_stop.go +++ b/containerm/cli/cli_command_ctrs_stop.go @@ -44,7 +44,7 @@ func (cc *stopCmd) init(cli *cli) { RunE: func(cmd *cobra.Command, args []string) error { return cc.run(args) }, - Example: "stop \n stop --name \n stop -n ", + Example: " stop \n stop --name \n stop -n ", } cc.setupFlags() } @@ -75,7 +75,7 @@ func (cc *stopCmd) run(args []string) error { func (cc *stopCmd) setupFlags() { flagSet := cc.cmd.Flags() // init timeout flag - flagSet.Int64VarP(&cc.config.timeout, "timeout", "t", math.MinInt64, "Sets the timeout period in seconds to gracefully stop the container. When timeout expires the container process would be forcibly killed.") + flagSet.Int64VarP(&cc.config.timeout, "time", "t", math.MinInt64, "Sets the timeout period in seconds to gracefully stop the container. When timeout expires the container process would be forcibly killed.") // init name flag flagSet.StringVarP(&cc.config.name, "name", "n", "", "Stop a container with a specific name.") // init force flag diff --git a/containerm/cli/cli_command_ctrs_stop_test.go b/containerm/cli/cli_command_ctrs_stop_test.go index 9c17e95..3f3c29e 100644 --- a/containerm/cli/cli_command_ctrs_stop_test.go +++ b/containerm/cli/cli_command_ctrs_stop_test.go @@ -26,7 +26,7 @@ import ( const ( // command flags - stopCmdFlagTimeout = "timeout" + stopCmdFlagTimeout = "time" stopCmdFlagName = "name" stopCmdFlagForce = "force" stopCmdFlagSignal = "signal" diff --git a/integration/framework/cli/cmd_base.go b/integration/framework/cli/cmd_base.go index 610a608..ed103ad 100644 --- a/integration/framework/cli/cmd_base.go +++ b/integration/framework/cli/cmd_base.go @@ -106,9 +106,7 @@ func RunCmdTestCases(t *testing.T, cmdList []TestCaseCMD) { runMultipleCommands(t, *cmd.setupCmd) } 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)) } @@ -167,7 +165,6 @@ func fromAPITestCommand(cmd TestCommand) TestCaseCMD { return TestCaseCMD{ name: cmd.Name, 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, @@ -190,7 +187,6 @@ func buildCmdArrFromCommand(cmd *[]Command) *[]icmd.Cmd { cmds := make([]icmd.Cmd, 0) for _, cmd := range *cmd { cmds = append(cmds, icmd.Command(cmd.Binary, cmd.Args...)) - // cmds = append(cmds, *checkArguments(cmd.Binary, cmd.Args...)) } return &cmds } diff --git a/integration/testdata/list-help.golden b/integration/testdata/list-help.golden index df62823..c05fbf1 100644 --- a/integration/testdata/list-help.golden +++ b/integration/testdata/list-help.golden @@ -6,12 +6,11 @@ Usage: Examples: list list --name - list -n - list -q - list --filter + list --quiet + list --filter status=created Flags: - --filter strings Lists only containers with the filter. + --filter strings Lists only containers with a specified filter. The containers can be filtered by their status, image and exitcode. -h, --help help for list -n, --name string List all containers with a specific name. -q, --quiet List only container IDs. diff --git a/integration/testdata/list-test.yaml b/integration/testdata/list-test.yaml index d36c3fd..7038de9 100644 --- a/integration/testdata/list-test.yaml +++ b/integration/testdata/list-test.yaml @@ -58,7 +58,7 @@ setupCmd: 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"] + args: ["list", "--host", "$KANTO_HOST", "--quiet"] expected: exitCode: 0 customResult: @@ -70,6 +70,29 @@ onExit: - binary: "kanto-cm" args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_quiet_two", "-f"] --- +name: list_containers_with_filter +setupCmd: + - binary: kanto-cm + args: ["create", "--host", "$KANTO_HOST", "-n", "list_containers_with_filter_one", "docker.io/library/influxdb:1.8.4"] + - binary: kanto-cm + args: ["create", "--host", "$KANTO_HOST", "-n", "list_containers_with_filter_two", "docker.io/library/influxdb:1.8.4"] +command: + binary: kanto-cm + args: ["list", "--host", "$KANTO_HOST", "--filter", "status=created"] +expected: + exitCode: 0 +customResult: + type: REGEX + args: ["ID |Name |Image |Status |Finished At |Exit Code | + ------------------------------------- |------------------------------------- |------------------------------------------------------------ |---------- |------------------------------ |---------- | + [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12} |list_containers_with_filter_one |docker.io/library/influxdb:1.8.4 |Created | |0 | + [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12} |list_containers_with_filter_two |docker.io/library/influxdb:1.8.4 |Created | |0 |"] +onExit: + - binary: "kanto-cm" + args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_filter_one", "-f"] + - binary: "kanto-cm" + args: ["remove", "--host", "$KANTO_HOST", "-n", "list_containers_with_filter_two", "-f"] +--- name: list_existing_container setupCmd: - binary: kanto-cm diff --git a/integration/testdata/stop-help.golden b/integration/testdata/stop-help.golden index c423665..48f0ec9 100644 --- a/integration/testdata/stop-help.golden +++ b/integration/testdata/stop-help.golden @@ -4,7 +4,7 @@ Usage: kanto-cm stop Examples: -stop + stop stop --name stop -n @@ -13,6 +13,7 @@ Flags: -h, --help help for stop -n, --name string Stop a container with a specific name. -s, --signal string Stop a container using a specific signal. Signals could be specified by using their names or numbers, e.g. SIGINT or 2. (default "SIGTERM") + -t, --time int Sets the timeout period in seconds to gracefully stop the container. When timeout expires the container process would be forcibly killed. (default -9223372036854775808) Global Flags: --debug Switch commands log level to DEBUG mode diff --git a/integration/testdata/stop-test.yaml b/integration/testdata/stop-test.yaml index 1d7ac45..dac4350 100644 --- a/integration/testdata/stop-test.yaml +++ b/integration/testdata/stop-test.yaml @@ -1,4 +1,4 @@ -name: remove_help +name: stop_help command: binary: kanto-cm args: ["stop", "-h"]