Skip to content
This repository was archived by the owner on May 6, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ var runtimeCommands = []cli.Command{
killCLICommand,
listCLICommand,
pauseCLICommand,
psCLICommand,
resumeCLICommand,
runCLICommand,
startCLICommand,
Expand Down
89 changes: 89 additions & 0 deletions ps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"

vc "github.com/containers/virtcontainers"
"github.com/urfave/cli"
)

var psCLICommand = cli.Command{
Name: "ps",
Usage: "ps displays the processes running inside a container",
ArgsUsage: `<container-id> [ps options]`,
Flags: []cli.Flag{
cli.StringFlag{
Name: "format, f",
Value: "table",
Usage: `select one of: ` + formatOptions,
},
},
Action: func(context *cli.Context) error {
if context.Args().Present() == false {
return fmt.Errorf("Missing container ID, should at least provide one")
}

var args []string
if len(context.Args()) > 1 {
// [1:] is to remove container_id:
// context.Args(): [container_id ps_arg1 ps_arg2 ...]
// args: [ps_arg1 ps_arg2 ...]
args = context.Args()[1:]
}

return ps(context.Args().First(), context.String("format"), args)
},
SkipArgReorder: true,
}

func ps(containerID, format string, args []string) error {
if containerID == "" {
return fmt.Errorf("Missing container ID")
}

// Checks the MUST and MUST NOT from OCI runtime specification
status, podID, err := getExistingContainerInfo(containerID)
if err != nil {
return err
}

containerID = status.ID

// container MUST be running
if status.State.State != vc.StateRunning {
return fmt.Errorf("Container %s is not running", containerID)
}

var options vc.ProcessListOptions

options.Args = args
if len(options.Args) == 0 {
options.Args = []string{"-ef"}
}

options.Format = format

msg, err := vci.ProcessListContainer(containerID, podID, options)
if err != nil {
return err
}

fmt.Print(string(msg))

return nil
}
134 changes: 134 additions & 0 deletions ps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"flag"
"testing"

vc "github.com/containers/virtcontainers"
"github.com/containers/virtcontainers/pkg/oci"
"github.com/containers/virtcontainers/pkg/vcMock"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
)

func TestPSCLIAction(t *testing.T) {
assert := assert.New(t)

flagSet := flag.NewFlagSet("flag", flag.ContinueOnError)
flagSet.Parse([]string{"cc-runtime"})

// create a new fake context
ctx := cli.NewContext(&cli.App{Metadata: map[string]interface{}{}}, flagSet, nil)

// get Action function
actionFunc, ok := psCLICommand.Action.(func(ctx *cli.Context) error)
assert.True(ok)

err := actionFunc(ctx)
assert.Error(err, "Missing container ID")
}

func TestPSFailure(t *testing.T) {
assert := assert.New(t)

pod := &vcMock.Pod{
MockID: testContainerID,
}

pod.MockContainers = []*vcMock.Container{
{
MockID: pod.ID(),
MockPod: pod,
},
}

testingImpl.ListPodFunc = func() ([]vc.PodStatus, error) {
// return a podStatus with the container status
return []vc.PodStatus{
{
ID: pod.ID(),
ContainersStatus: []vc.ContainerStatus{
{
ID: pod.ID(),
Annotations: map[string]string{
oci.ContainerTypeKey: string(vc.PodContainer),
},
},
},
},
}, nil
}

defer func() {
testingImpl.ListPodFunc = nil
}()

// inexistent container
err := ps("xyz123abc", "json", []string{"-ef"})
assert.Error(err)

// container is not running
err = ps(pod.ID(), "json", []string{"-ef"})
assert.Error(err)
}

func TestPSSuccessful(t *testing.T) {
assert := assert.New(t)

pod := &vcMock.Pod{
MockID: testContainerID,
}

pod.MockContainers = []*vcMock.Container{
{
MockID: pod.ID(),
MockPod: pod,
},
}

testingImpl.ListPodFunc = func() ([]vc.PodStatus, error) {
// return a podStatus with the container status
return []vc.PodStatus{
{
ID: pod.ID(),
ContainersStatus: []vc.ContainerStatus{
{
State: vc.State{
State: vc.StateRunning,
},
ID: pod.ID(),
Annotations: map[string]string{
oci.ContainerTypeKey: string(vc.PodContainer),
},
},
},
},
}, nil
}

testingImpl.ProcessListContainerFunc = func(podID, containerID string, options vc.ProcessListOptions) (vc.ProcessList, error) {
return []byte("echo,sleep,grep"), nil
}

defer func() {
testingImpl.ListPodFunc = nil
testingImpl.ProcessListContainerFunc = nil
}()

err := ps(pod.ID(), "json", []string{})
assert.NoError(err)
}