Browse code

POC of push/pull for images, pull works, push do push but without the layer

creack authored on 2013/03/21 19:53:27
Showing 1 changed files
... ...
@@ -6,8 +6,10 @@ import (
6 6
 	"errors"
7 7
 	"fmt"
8 8
 	"github.com/dotcloud/docker/auth"
9
+	"github.com/dotcloud/docker/graph"
9 10
 	"github.com/dotcloud/docker/rcli"
10 11
 	"io"
12
+	"io/ioutil"
11 13
 	"log"
12 14
 	"math/rand"
13 15
 	"net/http"
... ...
@@ -400,6 +402,173 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
400 400
 	return nil
401 401
 }
402 402
 
403
+func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
404
+	cmd := rcli.Subcmd(stdout, "push", "[OPTIONS] IMAGE", "Push an image to the registry")
405
+	if err := cmd.Parse(args); err != nil {
406
+		return nil
407
+	}
408
+	if cmd.NArg() == 0 {
409
+		cmd.Usage()
410
+		return nil
411
+	}
412
+
413
+	client := &http.Client{}
414
+	if img, err := srv.runtime.graph.Get(cmd.Arg(0)); err != nil {
415
+		return nil
416
+	} else {
417
+		img.WalkHistory(func(img *graph.Image) {
418
+			fmt.Fprintf(stdout, "Pushing %s\n", img.Id)
419
+
420
+			data := strings.NewReader("{\"id\": \"ddd\", \"created\": \"2013-03-21T00:18:18-07:00\"}")
421
+
422
+			req, err := http.NewRequest("PUT", "http://192.168.56.1:5000/v1/images/"+img.Id+"/json", data)
423
+			res, err := client.Do(req)
424
+			if err != nil || res.StatusCode != 200 {
425
+				switch res.StatusCode {
426
+				case 400:
427
+					fmt.Fprintf(stdout, "Error: Invalid Json\n")
428
+					return
429
+				default:
430
+					fmt.Fprintf(stdout, "Error: Internal server error\n")
431
+					return
432
+				}
433
+				fmt.Fprintf(stdout, "Error trying to push image {%s} (json): %s\n", img.Id, err)
434
+				return
435
+			}
436
+
437
+			req2, err := http.NewRequest("PUT", "http://192.168.56.1:5000/v1/images/"+img.Id+"/layer", nil)
438
+			res2, err := client.Do(req2)
439
+			if err != nil || res2.StatusCode != 307 {
440
+				fmt.Fprintf(stdout, "Error trying to push image {%s} (layer 1): %s\n", img.Id, err)
441
+				return
442
+			}
443
+			url, err := res2.Location()
444
+			if err != nil || url == nil {
445
+				fmt.Fprintf(stdout, "Fail to retrieve layer storage URL for image {%s}: %s\n", img.Id, err)
446
+				return
447
+			}
448
+
449
+			req3, err := http.NewRequest("PUT", url.String(), data)
450
+			res3, err := client.Do(req3)
451
+			if err != nil {
452
+				fmt.Fprintf(stdout, "Error trying to push image {%s} (layer 2): %s\n", img.Id, err)
453
+				return
454
+			}
455
+			fmt.Fprintf(stdout, "Status code storage: %d\n", res3.StatusCode)
456
+		})
457
+	}
458
+	return nil
459
+}
460
+
461
+func newImgJson(src []byte) (*graph.Image, error) {
462
+	ret := &graph.Image{}
463
+
464
+	fmt.Printf("Json string: {%s}\n", src)
465
+	// FIXME: Is there a cleaner way to "puryfy" the input json?
466
+	src = []byte(strings.Replace(string(src), "null", "\"\"", -1))
467
+
468
+	if err := json.Unmarshal(src, ret); err != nil {
469
+		return nil, err
470
+	}
471
+	return ret, nil
472
+}
473
+
474
+func newMultipleImgJson(src []byte) (map[*graph.Image]graph.Archive, error) {
475
+	ret := map[*graph.Image]graph.Archive{}
476
+
477
+	fmt.Printf("Json string2: {%s}\n", src)
478
+	dec := json.NewDecoder(strings.NewReader(strings.Replace(string(src), "null", "\"\"", -1)))
479
+	for {
480
+		m := &graph.Image{}
481
+		if err := dec.Decode(m); err == io.EOF {
482
+			break
483
+		} else if err != nil {
484
+			return nil, err
485
+		}
486
+		ret[m] = nil
487
+	}
488
+	return ret, nil
489
+}
490
+
491
+func getHistory(base_uri, id string) (map[*graph.Image]graph.Archive, error) {
492
+	res, err := http.Get(base_uri + id + "/history")
493
+	if err != nil {
494
+		return nil, fmt.Errorf("Error while getting from the server: %s\n", err)
495
+	}
496
+	defer res.Body.Close()
497
+
498
+	jsonString, err := ioutil.ReadAll(res.Body)
499
+	if err != nil {
500
+		return nil, fmt.Errorf("Error while reading the http response: %s\n", err)
501
+	}
502
+
503
+	history, err := newMultipleImgJson(jsonString)
504
+	if err != nil {
505
+		return nil, fmt.Errorf("Error while parsing the json: %s\n", err)
506
+	}
507
+	return history, nil
508
+}
509
+
510
+func getRemoteImage(base_uri, id string) (*graph.Image, graph.Archive, error) {
511
+	// Get the Json
512
+	res, err := http.Get(base_uri + id + "/json")
513
+	if err != nil {
514
+		return nil, nil, fmt.Errorf("Error while getting from the server: %s\n", err)
515
+	}
516
+	defer res.Body.Close()
517
+
518
+	jsonString, err := ioutil.ReadAll(res.Body)
519
+	if err != nil {
520
+		return nil, nil, fmt.Errorf("Error while reading the http response: %s\n", err)
521
+	}
522
+
523
+	img, err := newImgJson(jsonString)
524
+	if err != nil {
525
+		return nil, nil, fmt.Errorf("Error while parsing the json: %s\n", err)
526
+	}
527
+	img.Id = id
528
+
529
+	// Get the layer
530
+	res, err = http.Get(base_uri + id + "/layer")
531
+	if err != nil {
532
+		return nil, nil, fmt.Errorf("Error while getting from the server: %s\n", err)
533
+	}
534
+	return img, res.Body, nil
535
+}
536
+
537
+func (srv *Server) CmdPulli(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
538
+	cmd := rcli.Subcmd(stdout, "pulli", "[OPTIONS] IMAGE", "Pull an image from the registry")
539
+	if err := cmd.Parse(args); err != nil {
540
+		return nil
541
+	}
542
+	if cmd.NArg() == 0 {
543
+		cmd.Usage()
544
+		return nil
545
+	}
546
+
547
+	// First, retrieve the history
548
+	base_uri := "http://192.168.56.1:5000/v1/images/"
549
+
550
+	// Now we have the history, remove the images we already have
551
+	history, err := getHistory(base_uri, cmd.Arg(0))
552
+	if err != nil {
553
+		return err
554
+	}
555
+	for j := range history {
556
+		if !srv.runtime.graph.Exists(j.Id) {
557
+			img, layer, err := getRemoteImage(base_uri, j.Id)
558
+			if err != nil {
559
+				// FIXME: Keep goging in case of error?
560
+				return err
561
+			}
562
+			if err = srv.runtime.graph.Register(layer, img); err != nil {
563
+				return err
564
+			}
565
+		}
566
+	}
567
+	return nil
568
+}
569
+
403 570
 func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
404 571
 	cmd := rcli.Subcmd(stdout, "images", "[OPTIONS] [NAME]", "List images")
405 572
 	//limit := cmd.Int("l", 0, "Only show the N most recent versions of each image")