diff options
-rw-r--r-- | cmd/kpod/ps.go | 314 | ||||
-rw-r--r-- | libpod/container.go | 79 | ||||
-rw-r--r-- | test/kpod_ps.bats | 250 |
3 files changed, 315 insertions, 328 deletions
diff --git a/cmd/kpod/ps.go b/cmd/kpod/ps.go index a5f64ed11..13d72429e 100644 --- a/cmd/kpod/ps.go +++ b/cmd/kpod/ps.go @@ -15,9 +15,11 @@ import ( "k8s.io/apimachinery/pkg/fields" + "fmt" "github.com/pkg/errors" "github.com/projectatomic/libpod/cmd/kpod/formats" "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/libpod" "github.com/projectatomic/libpod/oci" "github.com/urfave/cli" ) @@ -144,18 +146,19 @@ func psCmd(c *cli.Context) error { if err := validateFlags(c, psFlags); err != nil { return err } - config, err := getConfig(c) - if err != nil { - return errors.Wrapf(err, "could not get config") + + // latest, and last are mutually exclusive. + if c.Int("last") >= 0 && c.Bool("latest") { + return errors.Errorf("last and latest are mutually exclusive") } - server, err := libkpod.New(config) + + runtime, err := getRuntime(c) if err != nil { - return errors.Wrapf(err, "error creating server") - } - if err := server.Update(); err != nil { - return errors.Wrapf(err, "error updating list of containers") + return errors.Wrapf(err, "error creating libpod runtime") } + defer runtime.Shutdown(false) + if len(c.Args()) > 0 { return errors.Errorf("too many arguments, ps takes no arguments") } @@ -177,38 +180,128 @@ func psCmd(c *cli.Context) error { namespace: c.Bool("namespace"), } - // all, latest, and last are mutually exclusive. Only one flag can be used at a time - exclusiveOpts := 0 - if opts.last >= 0 { - exclusiveOpts++ - } - if opts.latest { - exclusiveOpts++ - } - if opts.all { - exclusiveOpts++ - } - if exclusiveOpts > 1 { - return errors.Errorf("Last, latest and all are mutually exclusive") + var filterFuncs []libpod.ContainerFilter + // When we are dealing with latest or last=n, we need to + // get all containers. + if !opts.all && !opts.latest && opts.last < 1 { + // only get running containers + filterFuncs = append(filterFuncs, func(c *libpod.Container) bool { + state, _ := c.State() + return state == libpod.ContainerStateRunning + }) } - containers, err := server.ListContainers() - if err != nil { - return errors.Wrapf(err, "error getting containers from server") - } - var params *FilterParamsPS if opts.filter != "" { - params, err = parseFilter(opts.filter, containers) - if err != nil { - return errors.Wrapf(err, "error parsing filter") + filters := strings.Split(opts.filter, ",") + for _, f := range filters { + filterSplit := strings.Split(f, "=") + if len(filterSplit) < 2 { + return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) + } + generatedFunc, err := generateContainerFilterFuncs(filterSplit[0], filterSplit[1], runtime) + if err != nil { + return errors.Wrapf(err, "invalid filter") + } + filterFuncs = append(filterFuncs, generatedFunc) } + } + + containers, err := runtime.GetContainers(filterFuncs...) + var outputContainers []*libpod.Container + if opts.latest && len(containers) > 0 { + outputContainers = append(outputContainers, containers[0]) + } else if opts.last > 0 && opts.last <= len(containers) { + outputContainers = append(outputContainers, containers[:opts.last]...) } else { - params = nil + outputContainers = containers } - containerList := getContainersMatchingFilter(containers, params, server) + return generatePsOutput(outputContainers, opts) +} - return generatePsOutput(containerList, server, opts) +func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Runtime) (func(container *libpod.Container) bool, error) { + switch filter { + case "id": + return func(c *libpod.Container) bool { + return c.ID() == filterValue + }, nil + case "label": + return func(c *libpod.Container) bool { + for _, label := range c.Labels() { + if label == filterValue { + return true + } + } + return false + }, nil + case "name": + return func(c *libpod.Container) bool { + return c.Name() == filterValue + }, nil + case "exited": + exitCode, err := strconv.ParseInt(filterValue, 10, 32) + if err != nil { + return nil, errors.Wrapf(err, "exited code out of range %q", filterValue) + } + return func(c *libpod.Container) bool { + ec, err := c.ExitCode() + if ec == int32(exitCode) && err == nil { + return true + } + return false + }, nil + case "status": + if !libpod.StringInSlice(filterValue, []string{"created", "restarting", "running", "paused", "exited", "unknown"}) { + return nil, errors.Errorf("%s is not a valid status", filterValue) + } + return func(c *libpod.Container) bool { + status, err := c.State() + if err != nil { + return false + } + return status.String() == filterValue + }, nil + case "ancestor": + // This needs to refine to match docker + // - ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩) - containers created from an image or a descendant. + return func(c *libpod.Container) bool { + containerConfig := c.Config() + if containerConfig.RootfsImageID == filterValue || containerConfig.RootfsImageName == filterValue { + return true + } + return false + }, nil + case "before": + ctr, err := runtime.LookupContainer(filterValue) + if err != nil { + return nil, errors.Errorf("unable to find container by name or id of %s", filterValue) + } + containerConfig := ctr.Config() + createTime := containerConfig.CreatedTime + return func(c *libpod.Container) bool { + cc := c.Config() + return createTime.After(cc.CreatedTime) + }, nil + case "since": + ctr, err := runtime.LookupContainer(filterValue) + if err != nil { + return nil, errors.Errorf("unable to find container by name or id of %s", filterValue) + } + containerConfig := ctr.Config() + createTime := containerConfig.CreatedTime + return func(c *libpod.Container) bool { + cc := c.Config() + return createTime.Before(cc.CreatedTime) + }, nil + case "volume": + //- volume=(<volume-name>|<mount-point-destination>) + return func(c *libpod.Container) bool { + containerConfig := c.Config() + //TODO We need to still lookup against volumes too + return containerConfig.MountLabel == filterValue + }, nil + } + return nil, errors.Errorf("%s is an invalid filter", filter) } // generate the template based on conditions given @@ -280,37 +373,60 @@ func getContainers(containers []*libkpod.ContainerData, opts psOptions) []*libkp } // getTemplateOutput returns the modified container information -func getTemplateOutput(containers []*libkpod.ContainerData, opts psOptions) (psOutput []psTemplateParams) { +func getTemplateOutput(containers []*libpod.Container, opts psOptions) ([]psTemplateParams, error) { + var psOutput []psTemplateParams var status string for _, ctr := range containers { - ctrID := ctr.ID - runningFor := units.HumanDuration(time.Since(ctr.State.Created)) + ctrID := ctr.ID() + conConfig := ctr.Config() + conState, err := ctr.State() + if err != nil { + return psOutput, errors.Wrapf(err, "unable to obtain container state") + } + exitCode, err := ctr.ExitCode() + if err != nil { + return psOutput, errors.Wrapf(err, "unable to obtain container exit code") + } + pid, err := ctr.PID() + if err != nil { + return psOutput, errors.Wrapf(err, "unable to obtain container pid") + } + runningFor := units.HumanDuration(time.Since(conConfig.CreatedTime)) createdAt := runningFor + " ago" - command := getStrFromSquareBrackets(ctr.ImageCreatedBy) - imageName := ctr.FromImage - mounts := getMounts(ctr.Mounts, opts.noTrunc) - ports := getPorts(ctr.Config.ExposedPorts) - size := units.HumanSize(float64(ctr.SizeRootFs)) - labels := getLabels(ctr.Labels) - - ns := getNamespaces(ctr.State.Pid) - - switch ctr.State.Status { - case oci.ContainerStateStopped: - status = "Exited (" + strconv.FormatInt(int64(ctr.State.ExitCode), 10) + ") " + runningFor + " ago" - case oci.ContainerStateRunning: + imageName := conConfig.RootfsImageName + + // TODO We currently dont have the ability to get many of + // these data items. Uncomment as progress is made + + //command := getStrFromSquareBrackets(ctr.ImageCreatedBy) + command := strings.Join(ctr.Spec().Process.Args, " ") + //mounts := getMounts(ctr.Mounts, opts.noTrunc) + //ports := getPorts(ctr.Config.ExposedPorts) + //size := units.HumanSize(float64(ctr.SizeRootFs)) + labels := formatLabels(ctr.Labels()) + ns := getNamespaces(pid) + + switch conState { + case libpod.ContainerStateStopped: + status = fmt.Sprintf("Exited (%d) %s ago", exitCode, runningFor) + case libpod.ContainerStateRunning: status = "Up " + runningFor + " ago" - case oci.ContainerStatePaused: + case libpod.ContainerStatePaused: status = "Paused" - default: + case libpod.ContainerStateCreated: status = "Created" + default: + status = "Dead" } if !opts.noTrunc { - ctrID = ctr.ID[:idTruncLength] - imageName = getImageName(ctr.FromImage) + ctrID = ctr.ID()[:idTruncLength] + imageName = conConfig.RootfsImageName } + // TODO We currently dont have the ability to get many of + // these data items. Uncomment as progress is made + params := psTemplateParams{ ID: ctrID, Image: imageName, @@ -318,23 +434,23 @@ func getTemplateOutput(containers []*libkpod.ContainerData, opts psOptions) (psO CreatedAt: createdAt, RunningFor: runningFor, Status: status, - Ports: ports, - Size: size, - Names: ctr.Name, - Labels: labels, - Mounts: mounts, - PID: ctr.State.Pid, - Cgroup: ns.Cgroup, - IPC: ns.IPC, - MNT: ns.MNT, - NET: ns.NET, - PIDNS: ns.PID, - User: ns.User, - UTS: ns.UTS, + //Ports: ports, + //Size: size, + Names: ctr.Name(), + Labels: labels, + //Mounts: mounts, + PID: pid, + Cgroup: ns.Cgroup, + IPC: ns.IPC, + MNT: ns.MNT, + NET: ns.NET, + PIDNS: ns.PID, + User: ns.User, + UTS: ns.UTS, } psOutput = append(psOutput, params) } - return + return psOutput, nil } func getNamespaces(pid int) *namespace { @@ -368,50 +484,64 @@ func getNamespaceInfo(path string) (string, error) { } // getJSONOutput returns the container info in its raw form -func getJSONOutput(containers []*libkpod.ContainerData, nSpace bool) (psOutput []psJSONParams) { +func getJSONOutput(containers []*libpod.Container, nSpace bool) ([]psJSONParams, error) { + var psOutput []psJSONParams var ns *namespace for _, ctr := range containers { + pid, err := ctr.PID() + if err != nil { + return psOutput, errors.Wrapf(err, "unable to obtain container pid") + } if nSpace { - ns = getNamespaces(ctr.State.Pid) + ns = getNamespaces(pid) + } + cc := ctr.Config() + conState, err := ctr.State() + if err != nil { + return psOutput, errors.Wrapf(err, "unable to obtain container state for JSON output") } - params := psJSONParams{ - ID: ctr.ID, - Image: ctr.FromImage, - ImageID: ctr.FromImageID, - Command: getStrFromSquareBrackets(ctr.ImageCreatedBy), - CreatedAt: ctr.State.Created, - RunningFor: time.Since(ctr.State.Created), - Status: ctr.State.Status, - Ports: ctr.Config.ExposedPorts, - Size: ctr.SizeRootFs, - Names: ctr.Name, - Labels: ctr.Labels, - Mounts: ctr.Mounts, - ContainerRunning: ctr.State.Status == oci.ContainerStateRunning, + // TODO When we have ability to obtain the commented out data, we need + // TODO to add it + ID: ctr.ID(), + Image: cc.RootfsImageName, + ImageID: cc.RootfsImageID, + //Command: getStrFromSquareBrackets(ctr.ImageCreatedBy), + Command: strings.Join(ctr.Spec().Process.Args, " "), + CreatedAt: cc.CreatedTime, + RunningFor: time.Since(cc.CreatedTime), + Status: conState.String(), + //Ports: cc.Spec.Linux.Resources.Network. + //Size: ctr.SizeRootFs, + Names: cc.Name, + Labels: cc.Labels, + Mounts: cc.Spec.Mounts, + ContainerRunning: conState.String() == oci.ContainerStateRunning, Namespaces: ns, } psOutput = append(psOutput, params) } - return + return psOutput, nil } -func generatePsOutput(containers []*libkpod.ContainerData, server *libkpod.ContainerServer, opts psOptions) error { - containersOutput := getContainers(containers, opts) - // In the case of JSON, we want to continue so we at least pass - // {} --valid JSON-- to the consumer - if len(containersOutput) == 0 && opts.format != formats.JSONString { +func generatePsOutput(containers []*libpod.Container, opts psOptions) error { + if len(containers) == 0 && opts.format != formats.JSONString { return nil } - var out formats.Writer switch opts.format { case formats.JSONString: - psOutput := getJSONOutput(containersOutput, opts.namespace) + psOutput, err := getJSONOutput(containers, opts.namespace) + if err != nil { + return errors.Wrapf(err, "unable to create JSON for output") + } out = formats.JSONStructArray{Output: psToGeneric([]psTemplateParams{}, psOutput)} default: - psOutput := getTemplateOutput(containersOutput, opts) + psOutput, err := getTemplateOutput(containers, opts) + if err != nil { + return errors.Wrapf(err, "unable to create output") + } out = formats.StdoutTemplateArray{Output: psToGeneric(psOutput, []psJSONParams{}), Template: opts.format, Fields: psOutput[0].headerMap()} } @@ -440,7 +570,7 @@ func getImageName(img string) string { } // getLabels converts the labels to a string of the form "key=value, key2=value2" -func getLabels(labels fields.Set) string { +func formatLabels(labels map[string]string) string { var arr []string if len(labels) > 0 { for key, val := range labels { diff --git a/libpod/container.go b/libpod/container.go index 9ec0fb121..b58c156a0 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -124,6 +124,26 @@ type ContainerConfig struct { // TODO allow overriding of log path } +// ContainerStater returns a string representation for users +// of a container state +func (t ContainerState) String() string { + switch t { + case ContainerStateUnknown: + return "unknown" + case ContainerStateConfigured: + return "configured" + case ContainerStateCreated: + return "created" + case ContainerStateRunning: + return "running" + case ContainerStateStopped: + return "exited" + case ContainerStatePaused: + return "paused" + } + return "" +} + // ID returns the container's ID func (c *Container) ID() string { return c.config.ID @@ -170,6 +190,59 @@ func (c *Container) LogPath() string { return c.logPath() } +// ExitCode returns the exit code of the container as +// an int32 +func (c *Container) ExitCode() (int32, error) { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return 0, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + return c.state.ExitCode, nil +} + +// Mounted returns a bool as to if the container's storage +// is mounted +func (c *Container) Mounted() (bool, error) { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return false, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + return c.state.Mounted, nil +} + +// Mountpoint returns the path to the container's mounted +// storage as a string +func (c *Container) Mountpoint() (string, error) { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + } + return c.state.Mountpoint, nil +} + +// StartedTime is the time the container was started +func (c *Container) StartedTime() (time.Time, error) { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + return c.state.StartedTime, nil +} + +// FinishedTime is the time the container was stopped +func (c *Container) FinishedTime() (time.Time, error) { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + return c.state.FinishedTime, nil +} + // State returns the current state of the container func (c *Container) State() (ContainerState, error) { c.lock.Lock() @@ -178,7 +251,6 @@ func (c *Container) State() (ContainerState, error) { if err := c.syncContainer(); err != nil { return ContainerStateUnknown, err } - return c.state.State, nil } @@ -199,11 +271,9 @@ func (c *Container) PID() (int, error) { func (c *Container) MountPoint() (string, error) { c.lock.Lock() defer c.lock.Unlock() - - if err := c.runtime.state.UpdateContainer(c); err != nil { + if err := c.syncContainer(); err != nil { return "", errors.Wrapf(err, "error updating container %s state", c.ID()) } - return c.state.Mountpoint, nil } @@ -229,7 +299,6 @@ func (c *Container) syncContainer() error { if err := c.runtime.state.UpdateContainer(c); err != nil { return err } - // If runc knows about the container, update its status in runc // And then save back to disk if (c.state.State != ContainerStateUnknown) && diff --git a/test/kpod_ps.bats b/test/kpod_ps.bats index c62dfe194..4f722da34 100644 --- a/test/kpod_ps.bats +++ b/test/kpod_ps.bats @@ -15,317 +15,105 @@ function setup() { } @test "kpod ps default" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps all flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a echo "$output" [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps --all - echo "$output" - [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps size flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a -s - echo "$output" - [ "$status" -eq 0 ] + skip "Need size flag implemented in container backend" + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --size echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps quiet flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a -q - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --quiet echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps latest flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps --latest echo "$output" [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -l - echo "$output" - [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps last flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${BB} ls + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls -s run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps --last 2 echo "$output" [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -n 2 - echo "$output" - [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps no-trunc flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --no-trunc echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps namespace flag" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --ns - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps --all --namespace echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps namespace flag and format flag = json" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --ns --format json | python -m json.tool | grep namespace" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps without namespace flag and format flag = json" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --format json | python -m json.tool | grep namespace" echo "$output" [ "$status" -eq 1 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps format flag = go template" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --format "table {{.ID}} {{.Image}} {{.Labels}}" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps filter flag - ancestor" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --filter ancestor=${IMAGE} + ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls + run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --filter ancestor=${ALPINE} echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps filter flag - id" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + run ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} ls ctr_id="$output" run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --filter id="$ctr_id" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio } @test "kpod ps filter flag - status" { - skip "Test needs to be converted to kpod run" - start_crio - run crioctl pod run --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] + run ${KPOD_BINARY} ${KPOD_OPTIONS} run -d ${ALPINE} sleep 99 ctr_id="$output" run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} ps -a --filter status=running echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio + run ${KPOD_BINARY} ${KPOD_OPTIONS} stop $ctr_id } |