diff --git a/api/api.go b/api/api.go index 5571620eea..3c9c6be3ab 100644 --- a/api/api.go +++ b/api/api.go @@ -90,7 +90,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() { if len(accepteds) != 0 { found := false for _, accepted := range accepteds { @@ -342,14 +342,23 @@ func deleteImages(c *context, w http.ResponseWriter, r *http.Request) { client, scheme := newClientAndScheme(c.tlsConfig) defer closeIdleConnections(client) - images := c.cluster.Images(name) - size := len(images) + matchedImages := []*cluster.Image{} + for _, image := range c.cluster.Images() { + if image.Match(name) { + fmt.Println("matched", image) + matchedImages = append(matchedImages, image) + } + } + + size := len(matchedImages) if size == 0 { httpError(w, fmt.Sprintf("No such image %s", name), http.StatusNotFound) return } + wf := NewWriteFlusher(w) - for i, image := range images { + for i, image := range matchedImages { + fmt.Println("delete", image) req, err := http.NewRequest("DELETE", scheme+"://"+image.Node.Addr()+"/images/"+name, nil) if err != nil { if size == 1 { @@ -364,7 +373,6 @@ func deleteImages(c *context, w http.ResponseWriter, r *http.Request) { } continue } - data, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { @@ -387,10 +395,10 @@ func deleteImages(c *context, w http.ResponseWriter, r *http.Request) { sdata = strings.Replace(sdata, "[", ",", -1) } - if i != len(images)-1 { + if i != size-1 { sdata = strings.Replace(sdata, "]", "", -1) } - fmt.Fprintf(w, sdata) + fmt.Fprintf(wf, sdata) } } diff --git a/api/events_test.go b/api/events_test.go index 0c2cbb1bbe..eafbdd7639 100644 --- a/api/events_test.go +++ b/api/events_test.go @@ -23,7 +23,7 @@ func (fn *FakeNode) ID() string { return "node_id" } func (fn *FakeNode) Name() string { return "node_name" } func (fn *FakeNode) IP() string { return "node_ip" } func (fn *FakeNode) Addr() string { return "node_addr" } -func (fn *FakeNode) Images(_ string) []*cluster.Image { return nil } +func (fn *FakeNode) Images() []*cluster.Image { return nil } func (fn *FakeNode) Image(_ string) *cluster.Image { return nil } func (fn *FakeNode) Containers() []*cluster.Container { return nil } func (fn *FakeNode) Container(_ string) *cluster.Container { return nil } diff --git a/cluster/cluster.go b/cluster/cluster.go index 258d4f09e3..1844363b35 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -9,9 +9,8 @@ type Cluster interface { // Remove a container RemoveContainer(container *Container, force bool) error - // Return all images matching `name` - // if `name` == "" return all images in the cluster - Images(name string) []*Image + // Return all images + Images() []*Image // Return one image matching `IdOrName` Image(IdOrName string) *Image diff --git a/cluster/image.go b/cluster/image.go index c640209e53..3c2e603446 100644 --- a/cluster/image.go +++ b/cluster/image.go @@ -1,9 +1,27 @@ package cluster -import "github.com/samalba/dockerclient" +import ( + "strings" + + "github.com/samalba/dockerclient" +) type Image struct { dockerclient.Image Node Node } + +func (image *Image) Match(IdOrName string) bool { + size := len(IdOrName) + + if image.Id == IdOrName || (size > 2 && strings.HasPrefix(image.Id, IdOrName)) { + return true + } + for _, repoTag := range image.RepoTags { + if repoTag == IdOrName || (size > 2 && strings.HasPrefix(repoTag, IdOrName)) { + return true + } + } + return false +} diff --git a/cluster/node.go b/cluster/node.go index 830a59b232..a27b73c547 100644 --- a/cluster/node.go +++ b/cluster/node.go @@ -9,7 +9,7 @@ type Node interface { IP() string //to inject the actual IP of the machine in docker ps (hostname:port or ip:port) Addr() string //to know where to connect with the proxy - Images(name string) []*Image //used by the API + Images() []*Image //used by the API Image(IdOrName string) *Image //used by the filters Containers() []*Container //used by the filters Container(IdOrName string) *Container //used by the filters diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index 564cc577e6..97eb90c0e9 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -155,15 +155,14 @@ func (c *Cluster) getNode(addr string) *node { return nil } -// Containers returns all the images in the cluster. -// If `name` is empty, return all the images -func (c *Cluster) Images(name string) []*cluster.Image { +// Images returns all the images in the cluster. +func (c *Cluster) Images() []*cluster.Image { c.RLock() defer c.RUnlock() out := []*cluster.Image{} for _, n := range c.nodes { - out = append(out, n.Images(name)...) + out = append(out, n.Images()...) } return out diff --git a/cluster/swarm/node.go b/cluster/swarm/node.go index 29024e25aa..017df112e9 100644 --- a/cluster/swarm/node.go +++ b/cluster/swarm/node.go @@ -459,30 +459,13 @@ func (n *node) Container(IdOrName string) *cluster.Container { return nil } -func matchImage(image *cluster.Image, IdOrName string) bool { - size := len(IdOrName) - - if image.Id == IdOrName || (size > 2 && strings.HasPrefix(image.Id, IdOrName)) { - return true - } - for _, repoTag := range image.RepoTags { - if repoTag == IdOrName || (size > 2 && strings.HasPrefix(repoTag, IdOrName)) { - return true - } - } - return false -} - -// Images returns a list for images matching name in the node -// If `name` is empty, returns all the images -func (n *node) Images(name string) []*cluster.Image { +// Images returns all the images in the node +func (n *node) Images() []*cluster.Image { images := []*cluster.Image{} n.RLock() for _, image := range n.images { - if name == "" || matchImage(image, name) { - images = append(images, image) - } + images = append(images, image) } n.RUnlock() return images @@ -494,7 +477,7 @@ func (n *node) Image(IdOrName string) *cluster.Image { defer n.RUnlock() for _, image := range n.images { - if matchImage(image, IdOrName) { + if image.Match(IdOrName) { return image } } diff --git a/scheduler/filter/affinity.go b/scheduler/filter/affinity.go index 403f42711c..223c0fa326 100644 --- a/scheduler/filter/affinity.go +++ b/scheduler/filter/affinity.go @@ -35,7 +35,7 @@ func (f *AffinityFilter) Filter(config *dockerclient.ContainerConfig, nodes []cl } case "image": images := []string{} - for _, image := range node.Images("") { + for _, image := range node.Images() { images = append(images, image.Id) images = append(images, image.RepoTags...) for _, tag := range image.RepoTags { diff --git a/scheduler/filter/fakenode_test.go b/scheduler/filter/fakenode_test.go index 8eefbcbf56..54dea30915 100644 --- a/scheduler/filter/fakenode_test.go +++ b/scheduler/filter/fakenode_test.go @@ -11,11 +11,11 @@ type FakeNode struct { labels map[string]string } -func (fn *FakeNode) ID() string { return fn.id } -func (fn *FakeNode) Name() string { return fn.name } -func (fn *FakeNode) IP() string { return "" } -func (fn *FakeNode) Addr() string { return fn.addr } -func (fn *FakeNode) Images(_ string) []*cluster.Image { return fn.images } +func (fn *FakeNode) ID() string { return fn.id } +func (fn *FakeNode) Name() string { return fn.name } +func (fn *FakeNode) IP() string { return "" } +func (fn *FakeNode) Addr() string { return fn.addr } +func (fn *FakeNode) Images() []*cluster.Image { return fn.images } func (fn *FakeNode) Image(id string) *cluster.Image { for _, image := range fn.images { if image.Id == id { diff --git a/scheduler/strategy/fakenode_test.go b/scheduler/strategy/fakenode_test.go index 6d2ed7f5d0..bd5c997c08 100644 --- a/scheduler/strategy/fakenode_test.go +++ b/scheduler/strategy/fakenode_test.go @@ -21,7 +21,7 @@ func (fn *FakeNode) ID() string { return fn.id } func (fn *FakeNode) Name() string { return fn.name } func (fn *FakeNode) IP() string { return "" } func (fn *FakeNode) Addr() string { return fn.addr } -func (fn *FakeNode) Images(_ string) []*cluster.Image { return nil } +func (fn *FakeNode) Images() []*cluster.Image { return nil } func (fn *FakeNode) Image(_ string) *cluster.Image { return nil } func (fn *FakeNode) Containers() []*cluster.Container { return fn.containers } func (fn *FakeNode) Container(_ string) *cluster.Container { return nil }