Handle push/pull of repositories

This commit is contained in:
creack 2013-03-22 01:25:27 -07:00
parent d8fa52b7b5
commit 11c4294846
3 changed files with 128 additions and 9 deletions

View file

@ -15,7 +15,8 @@ import (
const CONFIGFILE = "/var/lib/docker/.dockercfg"
// the registry server we want to login against
const REGISTRY_SERVER = "https://registry.docker.io"
//const REGISTRY_SERVER = "https://registry.docker.io"
const REGISTRY_SERVER = "http://192.168.56.1:5000"
type AuthConfig struct {
Username string `json:"username"`

View file

@ -423,7 +423,8 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
}
func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "push", "[OPTIONS] IMAGE", "Push an image to the registry")
cmd := rcli.Subcmd(stdout, "push", "[OPTIONS] IMAGE", "Push an image or a repository to the registry")
user := cmd.String("u", "", "specify the user for the repository")
if err := cmd.Parse(args); err != nil {
return nil
}
@ -432,16 +433,31 @@ func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string
return nil
}
// Try to get the image
// FIXME: Handle lookup
// FIXME: Also push the tags in case of ./docker push myrepo:mytag
// img, err := srv.runtime.LookupImage(cmd.Arg(0))
img, err := srv.runtime.graph.Get(cmd.Arg(0))
if err != nil {
return err
if *user == "" {
return fmt.Errorf("Not logged in and no user specified\n")
}
// If it fails, try to get the repository
if repo, exists := srv.runtime.repositories.Repositories[cmd.Arg(0)]; exists {
if err := srv.runtime.graph.PushRepository(*user, cmd.Arg(0), repo); err != nil {
return err
}
} else {
return err
}
return nil
}
// FIXME: Handle repositories, etc. Not jist images
return srv.runtime.graph.PushImage(img)
}
func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "pull", "[OPTIONS] IMAGE", "Pull an image from the registry")
cmd := rcli.Subcmd(stdout, "pull", "[OPTIONS] IMAGE", "Pull an image or a repository from the registry")
user := cmd.String("u", "", "specify the user for the repository")
if err := cmd.Parse(args); err != nil {
return nil
}
@ -449,8 +465,15 @@ func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string
cmd.Usage()
return nil
}
// FIXME: Handle repositories, etc. Not jist images
return srv.runtime.graph.PullImage(cmd.Arg(0))
if srv.runtime.graph.LookupRemoteImage(cmd.Arg(0)) {
return srv.runtime.graph.PullImage(cmd.Arg(0))
}
if *user == "" {
return fmt.Errorf("Not loggin and no user specified\n")
}
// FIXME: Allow pull repo:tag
return srv.runtime.graph.PullRepository(*user, cmd.Arg(0), "", srv.runtime.repositories)
}
func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...string) error {

View file

@ -3,6 +3,7 @@ package docker
import (
"encoding/json"
"fmt"
"github.com/dotcloud/docker/auth"
"io"
"io/ioutil"
"net/http"
@ -12,7 +13,7 @@ import (
//FIXME: Set the endpoint in a conf file or via commandline
//const REGISTRY_ENDPOINT = "http://registry-creack.dotcloud.com/v1"
const REGISTRY_ENDPOINT = "http://192.168.56.1:5000/v1"
const REGISTRY_ENDPOINT = auth.REGISTRY_SERVER + "/v1"
// Build an Image object from raw json data
func NewImgJson(src []byte) (*Image, error) {
@ -67,6 +68,15 @@ func (graph *Graph) getRemoteHistory(imgId string) ([]*Image, error) {
return history, nil
}
// Check if an image exists in the Registry
func (graph *Graph) LookupRemoteImage(imgId string) bool {
res, err := http.Get(REGISTRY_ENDPOINT + "/images/" + imgId + "/json")
if err != nil {
return false
}
return res.StatusCode == 307
}
// Retrieve an image from the Registry.
// Returns the Image object as well as the layer as an Archive (io.Reader)
func (graph *Graph) getRemoteImage(imgId string) (*Image, Archive, error) {
@ -118,6 +128,46 @@ func (graph *Graph) PullImage(imgId string) error {
return nil
}
// FIXME: Handle the askedTag parameter
func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories *TagStore) error {
client := &http.Client{}
req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/users/"+user+"/"+repoName, nil)
if err != nil {
return err
}
authStruct, err := auth.LoadConfig()
if err != nil {
return err
}
req.SetBasicAuth(authStruct.Username, authStruct.Password)
res, err := client.Do(req)
if err != nil {
return err
}
rawJson, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
t := map[string]string{}
if err = json.Unmarshal(rawJson, &t); err != nil {
return err
}
for tag, rev := range t {
if err = graph.PullImage(rev); err != nil {
return err
}
if err = repositories.Set(repoName, tag, rev); err != nil {
return err
}
}
if err = repositories.Save(); err != nil {
return err
}
return nil
}
// Push a local image to the registry with its history if needed
func (graph *Graph) PushImage(imgOrig *Image) error {
client := &http.Client{}
@ -130,9 +180,12 @@ func (graph *Graph) PushImage(imgOrig *Image) error {
if err != nil {
return fmt.Errorf("Error while retreiving the path for {%s}: %s", img.Id, err)
}
// FIXME: try json with URF8
// FIXME: try json with UTF8
jsonData := strings.NewReader(string(jsonRaw))
req, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/images/"+img.Id+"/json", jsonData)
if err != nil {
return err
}
res, err := client.Do(req)
if err != nil || res.StatusCode != 200 {
if res == nil {
@ -199,3 +252,45 @@ func (graph *Graph) PushImage(imgOrig *Image) error {
}
return nil
}
func (graph *Graph) pushTag(user, repo, revision, tag string) error {
if tag == "" {
tag = "lastest"
}
revision = "\"" + revision + "\""
client := &http.Client{}
req, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/users/"+user+"/"+repo+"/"+tag, strings.NewReader(revision))
req.Header.Add("Content-type", "application/json")
res, err := client.Do(req)
if err != nil {
return err
}
fmt.Printf("Result of push tag: %d\n", res.StatusCode)
switch res.StatusCode {
default:
return fmt.Errorf("Error %d\n", res.StatusCode)
case 200:
case 201:
}
return nil
}
func (graph *Graph) PushRepository(user, repoName string, repo Repository) error {
for tag, imgId := range repo {
fmt.Printf("tag: %s, imgId: %s\n", tag, imgId)
img, err := graph.Get(imgId)
if err != nil {
return err
}
if err = graph.PushImage(img); err != nil {
return err
}
if err = graph.pushTag(user, repoName, imgId, tag); err != nil {
return err
}
}
return nil
}