Skip to content

Commit

Permalink
feature: when image is being used, must use --force to delete the image
Browse files Browse the repository at this point in the history
Signed-off-by: HusterWan <zirenwan@gmail.com>
  • Loading branch information
HusterWan committed Dec 27, 2017
1 parent 30910aa commit b686bf8
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 20 deletions.
4 changes: 3 additions & 1 deletion apis/server/container_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ func (s *Server) attachContainer(ctx context.Context, rw http.ResponseWriter, re
}

func (s *Server) getContainers(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
metas, err := s.ContainerMgr.List(ctx)
metas, err := s.ContainerMgr.List(ctx, func(meta *mgr.ContainerMeta) bool {
return true
})
if err != nil {
return err
}
Expand Down
27 changes: 23 additions & 4 deletions apis/server/image_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (s *Server) pullImage(ctx context.Context, rw http.ResponseWriter, req *htt
}

func (s *Server) listImages(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
filters := req.FormValue("failters")
filters := req.FormValue("filters")

imageList, err := s.ImageMgr.ListImages(ctx, filters)
if err != nil {
Expand Down Expand Up @@ -76,13 +76,32 @@ func (s *Server) searchImages(ctx context.Context, rw http.ResponseWriter, req *
return EncodeResponse(rw, http.StatusOK, searchResultItem)
}

// removeImage deletes an image by reference
// removeImage deletes an image by reference.
func (s *Server) removeImage(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
name := mux.Vars(req)["name"]

option := &mgr.ImageRemoveOption{}
image, err := s.ImageMgr.GetImage(ctx, name)
if err != nil {
return err
}

containers, err := s.ContainerMgr.List(ctx, func(meta *mgr.ContainerMeta) bool {
return meta.Image == image.Name
})
if err != nil {
return err
}

isForce := httputils.BoolValue(req, "force")
if !isForce && len(containers) > 0 {
return fmt.Errorf("Unable to remove the image %q (must force) - container %s is using this image", image.Name, containers[0].ID)
}

option := &mgr.ImageRemoveOption{
Force: isForce,
}

if err := s.ImageMgr.RemoveImage(ctx, name, option); err != nil {
if err := s.ImageMgr.RemoveImage(ctx, image, option); err != nil {
return err
}

Expand Down
7 changes: 6 additions & 1 deletion apis/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ paths:
description: "Remove an image by reference."
parameters:
- $ref: "#/parameters/imageid"
- name: "force"
in: "query"
description: "Remove the image even if it is being used"
type: "boolean"
default: false
responses:
204:
description: "No error"
Expand Down Expand Up @@ -1649,4 +1654,4 @@ responses:
500ErrorResponse:
description: An unexpected server error occured.
schema:
$ref: "#/definitions/Error"
$ref: "#/definitions/Error"
13 changes: 10 additions & 3 deletions cli/rmi.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"github.com/spf13/cobra"
)

var rmiDescription = "Remove one or more images by reference"
var rmiDescription = "Remove one or more images by reference." +
"When the image is being used by a container, you must specify -f to delete it." +
"But it is strongly discouraged, because the container will be in abnormal status."

// RmiCommand use to implement 'rmi' command, it remove one or more images by reference
type RmiCommand struct {
Expand Down Expand Up @@ -57,6 +59,11 @@ func (rmi *RmiCommand) runRmi(args []string) error {

// rmiExample shows examples in rmi command, and is used in auto-generated cli docs.
func rmiExample() string {
return `$ pouch rmi docker.io/library/busybox:latest
docker.io/library/busybox:latest`
return `$ pouch rmi registry.hub.docker.com/library/busybox:latest
registry.hub.docker.com/library/busybox:latest
$ pouch create --name test registry.hub.docker.com/library/busybox:latest
container ID: e5952417f9ee94621bbeaec532be1803ae2dedeb11a80f578a6d621e04a95afd, name: test
$ pouch rmi registry.hub.docker.com/library/busybox:latest
Error: failed to remove image: {"message":"Unable to remove the image \"registry.hub.docker.com/library/busybox:latest\" (must force) - container e5952417f9ee94621bbeaec532be1803ae2dedeb11a80f578a6d621e04a95afd is using this image"}
`
}
11 changes: 7 additions & 4 deletions daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type ContainerMgr interface {
Attach(ctx context.Context, name string, attach *AttachConfig) error

// List returns the list of containers.
List(ctx context.Context) ([]*ContainerMeta, error)
List(ctx context.Context, filter ContainerFilter) ([]*ContainerMeta, error)

// CreateExec creates exec process's environment.
CreateExec(ctx context.Context, name string, config *types.ExecCreateConfig) (string, error)
Expand Down Expand Up @@ -291,6 +291,7 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty
Status: types.StatusCreated,
},
ID: id,
Image: image.Name,
Name: name,
Config: &config.ContainerConfig,
HostConfig: config.HostConfig,
Expand Down Expand Up @@ -494,7 +495,7 @@ func (mgr *ContainerManager) Attach(ctx context.Context, name string, attach *At
}

// List returns the container's list.
func (mgr *ContainerManager) List(ctx context.Context) ([]*ContainerMeta, error) {
func (mgr *ContainerManager) List(ctx context.Context, filter ContainerFilter) ([]*ContainerMeta, error) {
metas := []*ContainerMeta{}

list, err := mgr.Store.List()
Expand All @@ -507,13 +508,15 @@ func (mgr *ContainerManager) List(ctx context.Context) ([]*ContainerMeta, error)
if !ok {
return nil, fmt.Errorf("failed to get container list, invalid meta type")
}
metas = append(metas, m)
if filter != nil && filter(m) {
metas = append(metas, m)
}
}

return metas, nil
}

// Get the detailed information of container
// Get the detailed information of container.
func (mgr *ContainerManager) Get(ctx context.Context, name string) (*ContainerMeta, error) {
c, err := mgr.container(name)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions daemon/mgr/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const (
DefaultStopTimeout = 10
)

// ContainerFilter defines a function to filter
// container in the store.
type ContainerFilter func(*ContainerMeta) bool

type containerExecConfig struct {
types.ExecCreateConfig

Expand Down
9 changes: 2 additions & 7 deletions daemon/mgr/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type ImageMgr interface {
GetImage(ctx context.Context, idOrRef string) (*types.ImageInfo, error)

// RemoveImage deletes an image by reference.
RemoveImage(ctx context.Context, name string, option *ImageRemoveOption) error
RemoveImage(ctx context.Context, image *types.ImageInfo, option *ImageRemoveOption) error
}

// ImageManager is an implementation of interface ImageMgr.
Expand Down Expand Up @@ -129,12 +129,7 @@ func (mgr *ImageManager) GetImage(ctx context.Context, idOrRef string) (*types.I
}

// RemoveImage deletes an image by reference.
func (mgr *ImageManager) RemoveImage(ctx context.Context, name string, option *ImageRemoveOption) error {
image, err := mgr.cache.get(name)
if err != nil {
return err
}

func (mgr *ImageManager) RemoveImage(ctx context.Context, image *types.ImageInfo, option *ImageRemoveOption) error {
if err := mgr.client.RemoveImage(ctx, image.Name); err != nil {
return err
}
Expand Down

0 comments on commit b686bf8

Please sign in to comment.