From d4daee4f274e0d4821f1e0b3a70d995e319e3ed0 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Wed, 12 Aug 2015 07:39:11 -0400 Subject: [PATCH] add support images -a Signed-off-by: Xian Chaobo --- api/handlers.go | 10 ++++++---- cluster/cluster.go | 2 +- cluster/engine.go | 8 +++++--- cluster/engine_test.go | 16 ++++++++-------- cluster/mesos/cluster.go | 4 ++-- cluster/swarm/cluster.go | 6 +++--- cluster/swarm/cluster_test.go | 4 ++-- scheduler/node/node.go | 2 +- test/integration/api/images.bats | 4 ++++ 9 files changed, 32 insertions(+), 24 deletions(-) diff --git a/api/handlers.go b/api/handlers.go index 5e97a5c185..f2d39f57a1 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -28,7 +28,7 @@ const APIVERSION = "1.16" func getInfo(c *context, w http.ResponseWriter, r *http.Request) { info := dockerclient.Info{ Containers: int64(len(c.cluster.Containers())), - Images: int64(len(c.cluster.Images())), + Images: int64(len(c.cluster.Images(false))), DriverStatus: c.statusHandler.Status(), NEventsListener: int64(c.eventsHandler.Size()), Debug: c.debug, @@ -78,7 +78,7 @@ func getImages(c *context, w http.ResponseWriter, r *http.Request) { // Create a map of engine address to the list of images it holds. engineImages := make(map[string][]*cluster.Image) - for _, image := range c.cluster.Images() { + for _, image := range c.cluster.Images(true) { engineImages[image.Engine.Addr] = append(engineImages[image.Engine.Addr], image) } @@ -114,6 +114,8 @@ func getImagesJSON(c *context, w http.ResponseWriter, r *http.Request) { return } + all := boolValue(r, "all") + filters, err := dockerfilters.FromParam(r.Form.Get("filters")) if err != nil { httpError(w, err.Error(), http.StatusInternalServerError) @@ -123,7 +125,7 @@ func getImagesJSON(c *context, w http.ResponseWriter, r *http.Request) { accepteds, _ := filters["node"] images := []*cluster.Image{} - for _, image := range c.cluster.Images() { + for _, image := range c.cluster.Images(all) { if len(accepteds) != 0 { found := false for _, accepted := range accepteds { @@ -585,7 +587,7 @@ func proxyImage(c *context, w http.ResponseWriter, r *http.Request) { func proxyImageTagOptional(c *context, w http.ResponseWriter, r *http.Request) { name := mux.Vars(r)["name"] - for _, image := range c.cluster.Images() { + for _, image := range c.cluster.Images(true) { if len(strings.SplitN(name, ":", 2)) == 2 && image.Match(name, true) || len(strings.SplitN(name, ":", 2)) == 1 && image.Match(name, false) { proxy(c.tlsConfig, image.Engine.Addr, w, r) diff --git a/cluster/cluster.go b/cluster/cluster.go index 0ad2bda19f..f50262334b 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -15,7 +15,7 @@ type Cluster interface { RemoveContainer(container *Container, force bool) error // Return all images - Images() []*Image + Images(all bool) []*Image // Return one image matching `IDOrName` Image(IDOrName string) *Image diff --git a/cluster/engine.go b/cluster/engine.go index 5409796f48..6f11b75e2b 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -185,7 +185,7 @@ func (e *Engine) RemoveImage(image *Image, name string) ([]*dockerclient.ImageDe // RefreshImages refreshes the list of images on the engine. func (e *Engine) RefreshImages() error { - images, err := e.client.ListImages(false) + images, err := e.client.ListImages(true) if err != nil { return err } @@ -507,12 +507,14 @@ func (e *Engine) Containers() Containers { } // Images returns all the images in the engine -func (e *Engine) Images() []*Image { +func (e *Engine) Images(all bool) []*Image { e.RLock() images := make([]*Image, 0, len(e.images)) for _, image := range e.images { - images = append(images, image) + if all || (!all && len(image.RepoTags) != 0 && image.RepoTags[0] != ":") { + images = append(images, image) + } } e.RUnlock() return images diff --git a/cluster/engine_test.go b/cluster/engine_test.go index a51823259f..858c8e94ce 100644 --- a/cluster/engine_test.go +++ b/cluster/engine_test.go @@ -64,7 +64,7 @@ func TestEngineCpusMemory(t *testing.T) { client.On("Info").Return(mockInfo, nil) client.On("Version").Return(mockVersion, nil) client.On("ListContainers", true, false, "").Return([]dockerclient.Container{}, nil) - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil) + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() assert.NoError(t, engine.ConnectWithClient(client)) @@ -85,7 +85,7 @@ func TestEngineSpecs(t *testing.T) { client.On("Info").Return(mockInfo, nil) client.On("Version").Return(mockVersion, nil) client.On("ListContainers", true, false, "").Return([]dockerclient.Container{}, nil) - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil) + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() assert.NoError(t, engine.ConnectWithClient(client)) @@ -114,7 +114,7 @@ func TestEngineState(t *testing.T) { // The client will return one container at first, then a second one will appear. client.On("ListContainers", true, false, "").Return([]dockerclient.Container{{Id: "one"}}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil).Once() + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil).Once() client.On("InspectContainer", "one").Return(&dockerclient.ContainerInfo{Config: &dockerclient.ContainerConfig{CpuShares: 100}}, nil).Once() client.On("ListContainers", true, false, fmt.Sprintf("{%q:[%q]}", "id", "two")).Return([]dockerclient.Container{{Id: "two"}}, nil).Once() client.On("InspectContainer", "two").Return(&dockerclient.ContainerInfo{Config: &dockerclient.ContainerConfig{CpuShares: 100}}, nil).Once() @@ -159,7 +159,7 @@ func TestCreateContainer(t *testing.T) { client.On("Version").Return(mockVersion, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() client.On("ListContainers", true, false, "").Return([]dockerclient.Container{}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil).Once() + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil).Once() assert.NoError(t, engine.ConnectWithClient(client)) assert.True(t, engine.isConnected()) @@ -172,7 +172,7 @@ func TestCreateContainer(t *testing.T) { id := "id1" client.On("CreateContainer", &mockConfig, name).Return(id, nil).Once() client.On("ListContainers", true, false, fmt.Sprintf(`{"id":[%q]}`, id)).Return([]dockerclient.Container{{Id: id}}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil).Once() + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil).Once() client.On("InspectContainer", id).Return(&dockerclient.ContainerInfo{Config: &config.ContainerConfig}, nil).Once() container, err := engine.Create(config, name, false) assert.Nil(t, err) @@ -195,7 +195,7 @@ func TestCreateContainer(t *testing.T) { client.On("CreateContainer", &mockConfig, name).Return("", dockerclient.ErrNotFound).Once() client.On("CreateContainer", &mockConfig, name).Return(id, nil).Once() client.On("ListContainers", true, false, fmt.Sprintf(`{"id":[%q]}`, id)).Return([]dockerclient.Container{{Id: id}}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil).Once() + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil).Once() client.On("InspectContainer", id).Return(&dockerclient.ContainerInfo{Config: &config.ContainerConfig}, nil).Once() container, err = engine.Create(config, name, true) assert.Nil(t, err) @@ -241,7 +241,7 @@ func TestUsedCpus(t *testing.T) { client.On("Info").Return(mockInfo, nil) client.On("Version").Return(mockVersion, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil).Once() + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil).Once() client.On("ListContainers", true, false, "").Return([]dockerclient.Container{{Id: "test"}}, nil).Once() client.On("InspectContainer", "test").Return(&dockerclient.ContainerInfo{Config: &dockerclient.ContainerConfig{CpuShares: cpuShares}}, nil).Once() engine.ConnectWithClient(client) @@ -268,7 +268,7 @@ func TestContainerRemovedDuringRefresh(t *testing.T) { client.On("Info").Return(mockInfo, nil) client.On("Version").Return(mockVersion, nil) - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil) + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() client.On("ListContainers", true, false, "").Return([]dockerclient.Container{container1, container2}, nil) client.On("InspectContainer", "c1").Return(info1, errors.New("Not found")) diff --git a/cluster/mesos/cluster.go b/cluster/mesos/cluster.go index 67e18e82d8..887702fd7f 100644 --- a/cluster/mesos/cluster.go +++ b/cluster/mesos/cluster.go @@ -190,13 +190,13 @@ func (c *Cluster) RemoveContainer(container *cluster.Container, force bool) erro } // Images returns all the images in the cluster. -func (c *Cluster) Images() []*cluster.Image { +func (c *Cluster) Images(all bool) []*cluster.Image { c.RLock() defer c.RUnlock() out := []*cluster.Image{} for _, s := range c.slaves { - out = append(out, s.engine.Images()...) + out = append(out, s.engine.Images(all)...) } return out diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index ff2f203feb..9e990ebe0f 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -259,13 +259,13 @@ func (c *Cluster) monitorDiscovery(ch <-chan discovery.Entries, errCh <-chan err } // Images returns all the images in the cluster. -func (c *Cluster) Images() []*cluster.Image { +func (c *Cluster) Images(all bool) []*cluster.Image { c.RLock() defer c.RUnlock() out := []*cluster.Image{} for _, e := range c.engines { - out = append(out, e.Images()...) + out = append(out, e.Images(all)...) } return out @@ -298,7 +298,7 @@ func (c *Cluster) RemoveImages(name string) ([]*dockerclient.ImageDelete, error) errs := []string{} var err error for _, e := range c.engines { - for _, image := range e.Images() { + for _, image := range e.Images(true) { if image.Match(name, true) { content, err := image.Engine.RemoveImage(image, name) if err != nil { diff --git a/cluster/swarm/cluster_test.go b/cluster/swarm/cluster_test.go index 4db853647b..598a6e8f38 100644 --- a/cluster/swarm/cluster_test.go +++ b/cluster/swarm/cluster_test.go @@ -129,7 +129,7 @@ func TestImportImage(t *testing.T) { client.On("Version").Return(mockVersion, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() client.On("ListContainers", true, false, "").Return([]dockerclient.Container{}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil) + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil) // connect client engine.ConnectWithClient(client) @@ -177,7 +177,7 @@ func TestLoadImage(t *testing.T) { client.On("Version").Return(mockVersion, nil) client.On("StartMonitorEvents", mock.Anything, mock.Anything, mock.Anything).Return() client.On("ListContainers", true, false, "").Return([]dockerclient.Container{}, nil).Once() - client.On("ListImages", false).Return([]*dockerclient.Image{}, nil) + client.On("ListImages", mock.Anything).Return([]*dockerclient.Image{}, nil) // connect client engine.ConnectWithClient(client) diff --git a/scheduler/node/node.go b/scheduler/node/node.go index c3d4a65cb9..333d609aed 100644 --- a/scheduler/node/node.go +++ b/scheduler/node/node.go @@ -34,7 +34,7 @@ func NewNode(e *cluster.Engine) *Node { Name: e.Name, Labels: e.Labels, Containers: e.Containers(), - Images: e.Images(), + Images: e.Images(true), UsedMemory: e.UsedMemory(), UsedCpus: e.UsedCpus(), TotalMemory: e.TotalMemory(), diff --git a/test/integration/api/images.bats b/test/integration/api/images.bats index 623f395262..6154bc6b7b 100644 --- a/test/integration/api/images.bats +++ b/test/integration/api/images.bats @@ -38,4 +38,8 @@ function teardown() { [ "$status" -eq 0 ] [ "${#lines[@]}" -eq 2 ] [[ "${lines[1]}" == *"busybox"* ]] + + # Try images -a + run docker_swarm images -a + [ "${#lines[@]}" -ge 5 ] }