Skip to content
This repository was archived by the owner on Feb 1, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,57 @@ func getVersion(c *context, w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(version)
}

// GET /images/get
func getImages(c *context, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
httpError(w, err.Error(), http.StatusInternalServerError)
return
}
names := r.Form["names"]

// find an engine which has all images
// Engine.Addr : [found names]
imageMap := make(map[string][]string)
var foundEngineAddr string
for _, image := range c.cluster.Images() {
for _, name := range names {
if image.Match(name) {
// check if engine addr already exists
value, exists := imageMap[image.Engine.Addr]
if exists {
// check if name already exists
nameAlreadyExisted := false
for _, tempName := range value {
if tempName == name {
nameAlreadyExisted = true
}
}
if nameAlreadyExisted == false {
imageMap[image.Engine.Addr] = append(value, name)
if len(names) == len(imageMap[image.Engine.Addr]) {
foundEngineAddr = image.Engine.Addr
}
}
} else {
imageMap[image.Engine.Addr] = []string{name}
}
}
if foundEngineAddr != "" {
break
}
}
if foundEngineAddr != "" {
break
}
}

if foundEngineAddr != "" {
proxy(c.tlsConfig, foundEngineAddr, w, r)
} else {
httpError(w, fmt.Sprintf("Not found an engine which has all images: %s", names), http.StatusNotFound)
}
}

// GET /images/json
func getImagesJSON(c *context, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var routes = map[string]map[string]handler{
"/images/json": getImagesJSON,
"/images/viz": notImplementedHandler,
"/images/search": proxyRandom,
"/images/get": notImplementedHandler,
"/images/get": getImages,
"/images/{name:.*}/get": proxyImage,
"/images/{name:.*}/history": proxyImage,
"/images/{name:.*}/json": proxyImage,
Expand Down
44 changes: 44 additions & 0 deletions test/integration/api/save.bats
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,47 @@ function teardown() {
rm -f $temp_file_name
rm -f $temp_file_name_o
}

@test "docker save multi-images" {
start_docker_with_busybox 2
start_docker 1
# tag busybox
docker -H ${HOSTS[0]} tag busybox test1
docker -H ${HOSTS[1]} tag busybox test2

# start manage
swarm_manage

# make sure image exists
run docker_swarm images
[ "$status" -eq 0 ]
[[ "${output}" == *"busybox"* ]]
[[ "${output}" == *"test1"* ]]
[[ "${output}" == *"test2"* ]]

temp_file_name=$(mktemp)

# do not support save images which are on multi machine
run docker_swarm save busybox test1 test2 > $temp_file_name
[ "$status" -ne 0 ]
[[ "${output}" == *"Not found an engine which has all images"* ]]

# save images which are on same machine
docker_swarm save busybox test1 > $temp_file_name

# saved image file exists, not empty and is tar file
[ -s $temp_file_name ]
run file $temp_file_name
[ "$status" -eq 0 ]
[[ "${output}" == *"tar archive"* ]]

# load image on node-3
docker -H ${HOSTS[2]} load < $temp_file_name
# check image
run docker -H ${HOSTS[2]} images
[ "$status" -eq 0 ]
[[ "${output}" == *"busybox"* ]]
[[ "${output}" == *"test1"* ]]

rm -f $temp_file_name
}