Implement kpod rm
Kpod rm removes a container from the system Signed-off-by: Ryan Cole <rcyoalne@gmail.com>
This commit is contained in:
parent
959aab4fd5
commit
f78c2625af
13 changed files with 297 additions and 59 deletions
|
@ -35,6 +35,7 @@ func main() {
|
|||
pullCommand,
|
||||
pushCommand,
|
||||
renameCommand,
|
||||
rmCommand,
|
||||
rmiCommand,
|
||||
saveCommand,
|
||||
tagCommand,
|
||||
|
|
75
cmd/kpod/rm.go
Normal file
75
cmd/kpod/rm.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-o/libkpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
rmFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Force removal of a running container. The default is false",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "link, l",
|
||||
Usage: "Remove the specified link and not the underlying container. The default is false",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "volumes, v",
|
||||
Usage: "Remove the volumes associated with the container. The default is false",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
rmDescription = "Remove one or more containers"
|
||||
rmCommand = cli.Command{
|
||||
Name: "rm",
|
||||
Usage: fmt.Sprintf(`kpod rm will remove one or more containers from the host. The container name or ID can be used.
|
||||
This does not remove images. Running containers will not be removed without the -f option.`),
|
||||
Description: rmDescription,
|
||||
Flags: rmFlags,
|
||||
Action: rmCmd,
|
||||
ArgsUsage: "",
|
||||
}
|
||||
)
|
||||
|
||||
// saveCmd saves the image to either docker-archive or oci
|
||||
func rmCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("need at least 1 argument")
|
||||
}
|
||||
|
||||
config, err := getConfig(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get config")
|
||||
}
|
||||
server, err := libkpod.New(config)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get container server")
|
||||
}
|
||||
defer server.Shutdown()
|
||||
err = server.Update()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not update list of containers")
|
||||
}
|
||||
force := c.Bool("force")
|
||||
|
||||
for _, container := range c.Args() {
|
||||
id, err2 := server.ContainerRemove(container, force)
|
||||
if err2 != nil {
|
||||
if err == nil {
|
||||
err = err2
|
||||
} else {
|
||||
err = errors.Wrapf(err, "%v. Stop the container before attempting removal or use -f\n", err2)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(id)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -201,6 +201,27 @@ _kpod_rename() {
|
|||
esac
|
||||
}
|
||||
|
||||
_kpod_rm() {
|
||||
local boolean_options="
|
||||
--force
|
||||
-f
|
||||
"
|
||||
|
||||
local options_with_args="
|
||||
"
|
||||
|
||||
local all_options="$options_with_args $boolean_options"
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||
;;
|
||||
*)
|
||||
__kpod_list_containers
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_kpod_rmi() {
|
||||
local boolean_options="
|
||||
--help
|
||||
|
|
31
docs/kpod-rm.1.md
Normal file
31
docs/kpod-rm.1.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
% kpod(1) kpod-rm - Remove one or more containers
|
||||
% Ryan Cole
|
||||
# kpod-rm "1" "August 2017" "kpod"
|
||||
|
||||
## NAME
|
||||
kpod rm - Remove one or more containers
|
||||
|
||||
## SYNOPSIS
|
||||
**kpod** **rm** [*options* [...]] container
|
||||
|
||||
## DESCRIPTION
|
||||
Kpod rm will remove one or more containers from the host. The container name or ID can be used. This does not remove images. Running containers will not be removed without the -f option
|
||||
|
||||
## OPTIONS
|
||||
|
||||
**--force, f**
|
||||
|
||||
Force the removal of a running container
|
||||
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
kpod rm mywebserver
|
||||
|
||||
kpod rm -f 860a4b23
|
||||
|
||||
## SEE ALSO
|
||||
kpod(1), kpod-rmi(1)
|
||||
|
||||
## HISTORY
|
||||
August 2017, Originally compiled by Ryan Cole <rycole@redhat.com>
|
|
@ -36,7 +36,7 @@ has the capability to debug pods/images created by crio.
|
|||
Path to the 'run directory' where all state information is stored
|
||||
|
||||
**--runtime**=**value**
|
||||
Path to the OCI-compatible binary used to run containers
|
||||
Path to the OCI compatible binary used to run containers
|
||||
|
||||
**--storage-driver, -s**=**value**
|
||||
Select which storage driver is used to manage storage of images and containers (default is overlay)
|
||||
|
@ -82,6 +82,9 @@ Push an image from local storage to elsewhere
|
|||
### rename
|
||||
Rename a container
|
||||
|
||||
### rm
|
||||
Remove one or more containers
|
||||
|
||||
### rmi
|
||||
Removes one or more locally stored images
|
||||
|
||||
|
|
52
libkpod/remove.go
Normal file
52
libkpod/remove.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package libkpod
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ContainerRemove removes a r
|
||||
func (c *ContainerServer) ContainerRemove(container string, force bool) (string, error) {
|
||||
ctr, err := c.LookupContainer(container)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ctrID := ctr.ID()
|
||||
|
||||
if err := c.runtime.UpdateStatus(ctr); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to update container state")
|
||||
}
|
||||
|
||||
err = c.runtime.UpdateStatus(ctr)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not update status for container %s", ctrID)
|
||||
}
|
||||
cState := c.runtime.ContainerStatus(ctr)
|
||||
if cState.Status == oci.ContainerStateRunning {
|
||||
if force {
|
||||
_, err = c.ContainerStop(container, -1)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "unable to stop container %s", ctrID)
|
||||
}
|
||||
} else {
|
||||
return "", errors.Errorf("cannot remove running container %s", ctrID)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.runtime.DeleteContainer(ctr); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to delete container %s", ctrID)
|
||||
}
|
||||
|
||||
c.RemoveContainer(ctr)
|
||||
|
||||
if err := c.storageRuntimeServer.DeleteContainer(ctrID); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to delete storage for container %s", ctrID)
|
||||
}
|
||||
|
||||
c.ReleaseContainerName(ctr.Name())
|
||||
|
||||
if err := c.ctrIDIndex.Delete(ctrID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ctrID, nil
|
||||
}
|
31
libkpod/stop.go
Normal file
31
libkpod/stop.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package libkpod
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ContainerStop stops a running container with a grace period (i.e., timeout).
|
||||
func (c *ContainerServer) ContainerStop(container string, timeout int64) (string, error) {
|
||||
ctr, err := c.LookupContainer(container)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to find container %s", container)
|
||||
}
|
||||
|
||||
if err := c.runtime.UpdateStatus(ctr); err != nil {
|
||||
return "", errors.Wrapf(err, "could not update runtime status of container server")
|
||||
}
|
||||
cStatus := c.runtime.ContainerStatus(ctr)
|
||||
if cStatus.Status != oci.ContainerStateStopped {
|
||||
if err := c.runtime.StopContainer(ctr, timeout); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to stop container %s", ctr.ID())
|
||||
}
|
||||
if err := c.storageRuntimeServer.StopContainer(ctr.ID()); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to unmount container %s", ctr.ID())
|
||||
}
|
||||
}
|
||||
|
||||
c.ContainerStateToDisk(ctr)
|
||||
|
||||
return ctr.ID(), nil
|
||||
}
|
|
@ -1,11 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||
|
@ -14,42 +9,11 @@ import (
|
|||
// RemoveContainer removes the container. If the container is running, the container
|
||||
// should be force removed.
|
||||
func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerRequest) (*pb.RemoveContainerResponse, error) {
|
||||
logrus.Debugf("RemoveContainerRequest %+v", req)
|
||||
c, err := s.GetContainerFromRequest(req.ContainerId)
|
||||
_, err := s.ContainerServer.ContainerRemove(req.ContainerId, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cState := s.Runtime().ContainerStatus(c)
|
||||
if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning {
|
||||
if err := s.Runtime().StopContainer(c, -1); err != nil {
|
||||
return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err)
|
||||
}
|
||||
if err := s.StorageRuntimeServer().StopContainer(c.ID()); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmount container %s: %v", c.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.Runtime().DeleteContainer(c); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete container %s: %v", c.ID(), err)
|
||||
}
|
||||
|
||||
if err := os.Remove(filepath.Join(s.config.ContainerExitsDir, c.ID())); err != nil {
|
||||
return nil, fmt.Errorf("failed to remove container exit file %s: %v", c.ID(), err)
|
||||
}
|
||||
|
||||
s.removeContainer(c)
|
||||
|
||||
if err := s.StorageRuntimeServer().DeleteContainer(c.ID()); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete storage for container %s: %v", c.ID(), err)
|
||||
}
|
||||
|
||||
s.ReleaseContainerName(c.Name())
|
||||
|
||||
if err := s.CtrIDIndex().Delete(c.ID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &pb.RemoveContainerResponse{}
|
||||
logrus.Debugf("RemoveContainerResponse: %+v", resp)
|
||||
return resp, nil
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||
|
@ -11,25 +8,12 @@ import (
|
|||
|
||||
// StopContainer stops a running container with a grace period (i.e., timeout).
|
||||
func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest) (*pb.StopContainerResponse, error) {
|
||||
logrus.Debugf("StopContainerRequest %+v", req)
|
||||
c, err := s.GetContainerFromRequest(req.ContainerId)
|
||||
_, err := s.ContainerServer.ContainerStop(req.ContainerId, req.Timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cStatus := s.Runtime().ContainerStatus(c)
|
||||
if cStatus.Status != oci.ContainerStateStopped {
|
||||
if err := s.Runtime().StopContainer(c, req.Timeout); err != nil {
|
||||
return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err)
|
||||
}
|
||||
if err := s.StorageRuntimeServer().StopContainer(c.ID()); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmount container %s: %v", c.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
s.ContainerStateToDisk(c)
|
||||
|
||||
resp := &pb.StopContainerResponse{}
|
||||
logrus.Debugf("StopContainerResponse %s: %+v", c.ID(), resp)
|
||||
logrus.Debugf("StopContainerResponse %s: %+v", req.ContainerId, resp)
|
||||
return resp, nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ load helpers
|
|||
IMAGE="alpine:latest"
|
||||
ROOT="$TESTDIR/crio"
|
||||
RUNROOT="$TESTDIR/crio-run"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT $STORAGE_OPTS"
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
|
@ -13,8 +13,10 @@ function teardown() {
|
|||
|
||||
@test "test diff of image and parent" {
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull $IMAGE
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS diff $IMAGE
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
echo "$output"
|
||||
run ${KKPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||
|
@ -28,9 +30,11 @@ function teardown() {
|
|||
|
||||
@test "test diff with json output" {
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull $IMAGE
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
# run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} diff --json $IMAGE | python -m json.tool"
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS diff --json $IMAGE
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
echo "$output"
|
||||
run ${KKPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||
|
|
|
@ -5,7 +5,7 @@ load helpers
|
|||
IMAGE="alpine:latest"
|
||||
ROOT="$TESTDIR/crio"
|
||||
RUNROOT="$TESTDIR/crio-run"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT $STORAGE_OPTS"
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
|
|
72
test/kpod_rm.bats
Normal file
72
test/kpod_rm.bats
Normal file
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
IMAGE="alpine:latest"
|
||||
ROOT="$TESTDIR/crio"
|
||||
RUNROOT="$TESTDIR/crio-run"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT $STORAGE_OPTS --runtime $RUNTIME_BINARY"
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
@test "remove a container" {
|
||||
start_crio
|
||||
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
pod_id="$output"
|
||||
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
ctr_id="$output"
|
||||
echo `which runc`
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS rm "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
@test "refuse to remove a running container" {
|
||||
start_crio
|
||||
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
pod_id="$output"
|
||||
run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
ctr_id="$output"
|
||||
run crioctl ctr start --id "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS rm "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -ne 0 ]
|
||||
cleanup_ctrs
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
@test "remove a running container" {
|
||||
start_crio
|
||||
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
pod_id="$output"
|
||||
run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
ctr_id="$output"
|
||||
run crioctl ctr start --id "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
echo `which runc`
|
||||
run ${KPOD_BINARY} $KPOD_OPTIONS rm -f "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
|
@ -5,7 +5,7 @@ load helpers
|
|||
IMAGE="alpine:latest"
|
||||
ROOT="$TESTDIR/crio"
|
||||
RUNROOT="$TESTDIR/crio-run"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT $STORAGE_OPTS"
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue