Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

Commit

Permalink
cli: implement ps command
Browse files Browse the repository at this point in the history
ps command is used by ```docker top``` to show
the processes running inside the container

partially fixes #95

Signed-off-by: Julio Montes <julio.montes@intel.com>
  • Loading branch information
Julio Montes committed Dec 5, 2017
1 parent 7ce8c5a commit 2cb8855
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 0 deletions.
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
90 changes: 90 additions & 0 deletions ps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// 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 {
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

// [1:] is to remove command name, ex:
// context.Args(): [containet_id ps_arg1 ps_arg2 ...]
// psArgs: [ps_arg1 ps_arg2 ...]
//
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)
}

0 comments on commit 2cb8855

Please sign in to comment.