Browse code

Allow images to be saved and loaded by id and repository

Michael Crosby authored on 2013/11/21 10:28:19
Showing 3 changed files
... ...
@@ -539,19 +539,11 @@ func getImagesGet(srv *Server, version float64, w http.ResponseWriter, r *http.R
539 539
 	if version > 1.0 {
540 540
 		w.Header().Set("Content-Type", "application/x-tar")
541 541
 	}
542
-	err := srv.ImageExport(name, w)
543
-	if err != nil {
544
-		return err
545
-	}
546
-	return nil
542
+	return srv.ImageExport(name, w)
547 543
 }
548 544
 
549 545
 func postImagesLoad(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
550
-	err := srv.ImageLoad(r.Body)
551
-	if err != nil {
552
-		return err
553
-	}
554
-	return nil
546
+	return srv.ImageLoad(r.Body)
555 547
 }
556 548
 
557 549
 func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -1969,8 +1969,7 @@ func (cli *DockerCli) CmdCp(args ...string) error {
1969 1969
 func (cli *DockerCli) CmdSave(args ...string) error {
1970 1970
 	cmd := Subcmd("save", "IMAGE DESTINATION", "Save an image to a tar archive")
1971 1971
 	if err := cmd.Parse(args); err != nil {
1972
-		cmd.Usage()
1973
-		return nil
1972
+		return err
1974 1973
 	}
1975 1974
 
1976 1975
 	if cmd.NArg() != 1 {
... ...
@@ -1979,7 +1978,6 @@ func (cli *DockerCli) CmdSave(args ...string) error {
1979 1979
 	}
1980 1980
 
1981 1981
 	image := cmd.Arg(0)
1982
-
1983 1982
 	if err := cli.stream("GET", "/images/"+image+"/get", nil, cli.out, nil); err != nil {
1984 1983
 		return err
1985 1984
 	}
... ...
@@ -1988,17 +1986,18 @@ func (cli *DockerCli) CmdSave(args ...string) error {
1988 1988
 
1989 1989
 func (cli *DockerCli) CmdLoad(args ...string) error {
1990 1990
 	cmd := Subcmd("load", "SOURCE", "Load an image from a tar archive")
1991
+	if err := cmd.Parse(args); err != nil {
1992
+		return err
1993
+	}
1991 1994
 
1992 1995
 	if cmd.NArg() != 0 {
1993 1996
 		cmd.Usage()
1994 1997
 		return nil
1995 1998
 	}
1996 1999
 
1997
-	err := cli.stream("POST", "/images/load", cli.in, cli.out, nil)
1998
-	if err != nil {
1999
-		fmt.Println("Send failed", err)
2000
+	if err := cli.stream("POST", "/images/load", cli.in, cli.out, nil); err != nil {
2001
+		return err
2000 2002
 	}
2001
-
2002 2003
 	return nil
2003 2004
 }
2004 2005
 
... ...
@@ -212,67 +212,38 @@ func (srv *Server) ImageExport(name string, out io.Writer) error {
212 212
 
213 213
 	utils.Debugf("Serializing %s", name)
214 214
 
215
-	rootRepo := srv.runtime.repositories.Repositories[name]
216
-	for _, rootImage := range rootRepo {
217
-		image, _ := srv.ImageInspect(rootImage)
218
-		for i := image; i != nil; {
219
-			// temporary directory
220
-			tmpImageDir := path.Join(tempdir, i.ID)
221
-			if err := os.Mkdir(tmpImageDir, os.ModeDir); err != nil {
222
-				return err
223
-			}
224
-			defer os.RemoveAll(tmpImageDir)
225
-
226
-			var version = "1.0"
227
-			var versionBuf = []byte(version)
228
-
229
-			if err := ioutil.WriteFile(path.Join(tmpImageDir, "VERSION"), versionBuf, os.ModeAppend); err != nil {
230
-				return err
231
-			}
232
-
233
-			// serialize json
234
-			b, err := json.Marshal(i)
235
-			if err != nil {
236
-				return err
237
-			}
238
-			if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.ModeAppend); err != nil {
239
-				return err
240
-			}
241
-
242
-			// serialize filesystem
243
-			fs, err := archive.Tar(path.Join(srv.runtime.graph.Root, i.ID, "layer"), archive.Uncompressed)
215
+	rootRepo, err := srv.runtime.repositories.Get(name)
216
+	if err != nil {
217
+		return err
218
+	}
219
+	if rootRepo != nil {
220
+		for _, id := range rootRepo {
221
+			image, err := srv.ImageInspect(id)
244 222
 			if err != nil {
245 223
 				return err
246 224
 			}
247 225
 
248
-			fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
249
-			if err != nil {
250
-				return err
251
-			}
252
-			if _, err = io.Copy(fsTar, fs); err != nil {
226
+			if err := srv.exportImage(image, tempdir); err != nil {
253 227
 				return err
254 228
 			}
255
-			fsTar.Close()
256
-
257
-			// find parent
258
-			if i.Parent != "" {
259
-				i, err = srv.ImageInspect(i.Parent)
260
-				if err != nil {
261
-					return err
262
-				}
263
-			} else {
264
-				i = nil
265
-			}
266 229
 		}
267
-	}
268 230
 
269
-	// write repositories
270
-	rootRepoMap := map[string]Repository{}
271
-	rootRepoMap[name] = rootRepo
272
-	rootRepoJson, _ := json.Marshal(rootRepoMap)
231
+		// write repositories
232
+		rootRepoMap := map[string]Repository{}
233
+		rootRepoMap[name] = rootRepo
234
+		rootRepoJson, _ := json.Marshal(rootRepoMap)
273 235
 
274
-	if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.ModeAppend); err != nil {
275
-		return err
236
+		if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.ModeAppend); err != nil {
237
+			return err
238
+		}
239
+	} else {
240
+		image, err := srv.ImageInspect(name)
241
+		if err != nil {
242
+			return err
243
+		}
244
+		if err := srv.exportImage(image, tempdir); err != nil {
245
+			return err
246
+		}
276 247
 	}
277 248
 
278 249
 	fs, err := archive.Tar(tempdir, archive.Uncompressed)
... ...
@@ -286,6 +257,58 @@ func (srv *Server) ImageExport(name string, out io.Writer) error {
286 286
 	return nil
287 287
 }
288 288
 
289
+func (srv *Server) exportImage(image *Image, tempdir string) error {
290
+	for i := image; i != nil; {
291
+		// temporary directory
292
+		tmpImageDir := path.Join(tempdir, i.ID)
293
+		if err := os.Mkdir(tmpImageDir, os.ModeDir); err != nil {
294
+			return err
295
+		}
296
+
297
+		var version = "1.0"
298
+		var versionBuf = []byte(version)
299
+
300
+		if err := ioutil.WriteFile(path.Join(tmpImageDir, "VERSION"), versionBuf, os.ModeAppend); err != nil {
301
+			return err
302
+		}
303
+
304
+		// serialize json
305
+		b, err := json.Marshal(i)
306
+		if err != nil {
307
+			return err
308
+		}
309
+		if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.ModeAppend); err != nil {
310
+			return err
311
+		}
312
+
313
+		// serialize filesystem
314
+		fs, err := archive.Tar(path.Join(srv.runtime.graph.Root, i.ID, "layer"), archive.Uncompressed)
315
+		if err != nil {
316
+			return err
317
+		}
318
+
319
+		fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
320
+		if err != nil {
321
+			return err
322
+		}
323
+		if _, err = io.Copy(fsTar, fs); err != nil {
324
+			return err
325
+		}
326
+		fsTar.Close()
327
+
328
+		// find parent
329
+		if i.Parent != "" {
330
+			i, err = srv.ImageInspect(i.Parent)
331
+			if err != nil {
332
+				return err
333
+			}
334
+		} else {
335
+			i = nil
336
+		}
337
+	}
338
+	return nil
339
+}
340
+
289 341
 // Loads a set of images into the repository. This is the complementary of ImageExport.
290 342
 // The input stream is an uncompressed tar ball containing images and metadata.
291 343
 func (srv *Server) ImageLoad(in io.Reader) error {
... ...
@@ -319,25 +342,38 @@ func (srv *Server) ImageLoad(in io.Reader) error {
319 319
 	if err := archive.Untar(repoFile, repoDir); err != nil {
320 320
 		return err
321 321
 	}
322
-	repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
322
+
323
+	dirs, err := ioutil.ReadDir(repoDir)
323 324
 	if err != nil {
324 325
 		return err
325 326
 	}
326
-	repositories := map[string]Repository{}
327
-	if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
328
-		return err
329
-	}
330 327
 
331
-	for imageName, tagMap := range repositories {
332
-		for tag, address := range tagMap {
333
-			if err := srv.recursiveLoad(address, tmpImageDir); err != nil {
328
+	for _, d := range dirs {
329
+		if d.IsDir() {
330
+			if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
334 331
 				return err
335 332
 			}
336
-			if err := srv.runtime.repositories.Set(imageName, tag, address, true); err != nil {
337
-				return err
333
+		}
334
+	}
335
+
336
+	repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
337
+	if err == nil {
338
+		repositories := map[string]Repository{}
339
+		if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
340
+			return err
341
+		}
342
+
343
+		for imageName, tagMap := range repositories {
344
+			for tag, address := range tagMap {
345
+				if err := srv.runtime.repositories.Set(imageName, tag, address, true); err != nil {
346
+					return err
347
+				}
338 348
 			}
339 349
 		}
350
+	} else if !os.IsNotExist(err) {
351
+		return err
340 352
 	}
353
+
341 354
 	return nil
342 355
 }
343 356
 
... ...
@@ -373,6 +409,7 @@ func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
373 373
 		}
374 374
 	}
375 375
 	utils.Debugf("Completed processing %s", address)
376
+
376 377
 	return nil
377 378
 }
378 379