Browse Source

Support for the new registry/index API (wip)

shin- 12 years ago
parent
commit
2421838b0a
2 changed files with 36 additions and 34 deletions
  1. 3 3
      auth/auth.go
  2. 33 31
      registry.go

+ 3 - 3
auth/auth.go

@@ -16,7 +16,7 @@ import (
 const CONFIGFILE = ".dockercfg"
 const CONFIGFILE = ".dockercfg"
 
 
 // the registry server we want to login against
 // the registry server we want to login against
-const REGISTRY_SERVER = "https://registry.docker.io"
+const INDEX_SERVER = "https://index.docker.io"
 
 
 type AuthConfig struct {
 type AuthConfig struct {
 	Username string `json:"username"`
 	Username string `json:"username"`
@@ -113,7 +113,7 @@ func Login(authConfig *AuthConfig) (string, error) {
 
 
 	// using `bytes.NewReader(jsonBody)` here causes the server to respond with a 411 status.
 	// using `bytes.NewReader(jsonBody)` here causes the server to respond with a 411 status.
 	b := strings.NewReader(string(jsonBody))
 	b := strings.NewReader(string(jsonBody))
-	req1, err := http.Post(REGISTRY_SERVER+"/v1/users", "application/json; charset=utf-8", b)
+	req1, err := http.Post(INDEX_SERVER+"/v1/users", "application/json; charset=utf-8", b)
 	if err != nil {
 	if err != nil {
 		errMsg = fmt.Sprintf("Server Error: %s", err)
 		errMsg = fmt.Sprintf("Server Error: %s", err)
 		return "", errors.New(errMsg)
 		return "", errors.New(errMsg)
@@ -134,7 +134,7 @@ func Login(authConfig *AuthConfig) (string, error) {
 		// FIXME: This should be 'exists', not 'exist'. Need to change on the server first.
 		// FIXME: This should be 'exists', not 'exist'. Need to change on the server first.
 		if string(reqBody) == "Username or email already exist" {
 		if string(reqBody) == "Username or email already exist" {
 			client := &http.Client{}
 			client := &http.Client{}
-			req, err := http.NewRequest("GET", REGISTRY_SERVER+"/v1/users", nil)
+			req, err := http.NewRequest("GET", INDEX_SERVER+"/v1/users", nil)
 			req.SetBasicAuth(authConfig.Username, authConfig.Password)
 			req.SetBasicAuth(authConfig.Username, authConfig.Password)
 			resp, err := client.Do(req)
 			resp, err := client.Do(req)
 			if err != nil {
 			if err != nil {

+ 33 - 31
registry.go

@@ -13,8 +13,8 @@ import (
 )
 )
 
 
 //FIXME: Set the endpoint in a conf file or via commandline
 //FIXME: Set the endpoint in a conf file or via commandline
-//const REGISTRY_ENDPOINT = "http://registry-creack.dotcloud.com/v1"
-const REGISTRY_ENDPOINT = auth.REGISTRY_SERVER + "/v1"
+//const INDEX_ENDPOINT = "http://registry-creack.dotcloud.com/v1"
+const INDEX_ENDPOINT = auth.INDEX_SERVER + "/v1"
 
 
 // Build an Image object from raw json data
 // Build an Image object from raw json data
 func NewImgJson(src []byte) (*Image, error) {
 func NewImgJson(src []byte) (*Image, error) {
@@ -48,10 +48,10 @@ func NewMultipleImgJson(src []byte) ([]*Image, error) {
 
 
 // Retrieve the history of a given image from the Registry.
 // Retrieve the history of a given image from the Registry.
 // Return a list of the parent's json (requested image included)
 // Return a list of the parent's json (requested image included)
-func (graph *Graph) getRemoteHistory(imgId string, authConfig *auth.AuthConfig) ([]*Image, error) {
+func (graph *Graph) getRemoteHistory(imgId, registry string, authConfig *auth.AuthConfig) ([]*Image, error) {
 	client := &http.Client{}
 	client := &http.Client{}
 
 
-	req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/history", nil)
+	req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/ancestry", nil)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -78,29 +78,26 @@ func (graph *Graph) getRemoteHistory(imgId string, authConfig *auth.AuthConfig)
 }
 }
 
 
 // Check if an image exists in the Registry
 // Check if an image exists in the Registry
-func (graph *Graph) LookupRemoteImage(imgId string, authConfig *auth.AuthConfig) bool {
+func (graph *Graph) LookupRemoteImage(imgId, registry string, authConfig *auth.AuthConfig) bool {
 	rt := &http.Transport{Proxy: http.ProxyFromEnvironment}
 	rt := &http.Transport{Proxy: http.ProxyFromEnvironment}
 
 
-	req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/json", nil)
+	req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/json", nil)
 	if err != nil {
 	if err != nil {
 		return false
 		return false
 	}
 	}
 	req.SetBasicAuth(authConfig.Username, authConfig.Password)
 	req.SetBasicAuth(authConfig.Username, authConfig.Password)
 	res, err := rt.RoundTrip(req)
 	res, err := rt.RoundTrip(req)
-	if err != nil || res.StatusCode != 307 {
-		return false
-	}
-	return res.StatusCode == 307
+	return err == nil && res.StatusCode == 307
 }
 }
 
 
 // Retrieve an image from the Registry.
 // Retrieve an image from the Registry.
 // Returns the Image object as well as the layer as an Archive (io.Reader)
 // Returns the Image object as well as the layer as an Archive (io.Reader)
-func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *auth.AuthConfig) (*Image, Archive, error) {
+func (graph *Graph) getRemoteImage(stdout io.Writer, imgId, registry string, authConfig *auth.AuthConfig) (*Image, Archive, error) {
 	client := &http.Client{}
 	client := &http.Client{}
 
 
 	fmt.Fprintf(stdout, "Pulling %s metadata\r\n", imgId)
 	fmt.Fprintf(stdout, "Pulling %s metadata\r\n", imgId)
 	// Get the Json
 	// Get the Json
-	req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/json", nil)
+	req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/json", nil)
 	if err != nil {
 	if err != nil {
 		return nil, nil, fmt.Errorf("Failed to download json: %s", err)
 		return nil, nil, fmt.Errorf("Failed to download json: %s", err)
 	}
 	}
@@ -127,7 +124,7 @@ func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *a
 
 
 	// Get the layer
 	// Get the layer
 	fmt.Fprintf(stdout, "Pulling %s fs layer\r\n", imgId)
 	fmt.Fprintf(stdout, "Pulling %s fs layer\r\n", imgId)
-	req, err = http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/layer", nil)
+	req, err = http.NewRequest("GET", registry+"/images/"+imgId+"/layer", nil)
 	if err != nil {
 	if err != nil {
 		return nil, nil, fmt.Errorf("Error while getting from the server: %s\n", err)
 		return nil, nil, fmt.Errorf("Error while getting from the server: %s\n", err)
 	}
 	}
@@ -139,7 +136,7 @@ func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *a
 	return img, ProgressReader(res.Body, int(res.ContentLength), stdout, "Downloading %v/%v (%v)"), nil
 	return img, ProgressReader(res.Body, int(res.ContentLength), stdout, "Downloading %v/%v (%v)"), nil
 }
 }
 
 
-func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.AuthConfig) error {
+func (graph *Graph) PullImage(stdout io.Writer, imgId, registry string, authConfig *auth.AuthConfig) error {
 	history, err := graph.getRemoteHistory(imgId, authConfig)
 	history, err := graph.getRemoteHistory(imgId, authConfig)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -148,7 +145,7 @@ func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.A
 	// FIXME: Lunch the getRemoteImage() in goroutines
 	// FIXME: Lunch the getRemoteImage() in goroutines
 	for _, j := range history {
 	for _, j := range history {
 		if !graph.Exists(j.Id) {
 		if !graph.Exists(j.Id) {
-			img, layer, err := graph.getRemoteImage(stdout, j.Id, authConfig)
+			img, layer, err := graph.getRemoteImage(stdout, j.Id, registry, authConfig)
 			if err != nil {
 			if err != nil {
 				// FIXME: Keep goging in case of error?
 				// FIXME: Keep goging in case of error?
 				return err
 				return err
@@ -162,7 +159,7 @@ func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.A
 }
 }
 
 
 // FIXME: Handle the askedTag parameter
 // FIXME: Handle the askedTag parameter
-func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, repositories *TagStore, authConfig *auth.AuthConfig) error {
+func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag, registry string, repositories *TagStore, authConfig *auth.AuthConfig) error {
 	client := &http.Client{}
 	client := &http.Client{}
 
 
 	fmt.Fprintf(stdout, "Pulling repository %s\r\n", remote)
 	fmt.Fprintf(stdout, "Pulling repository %s\r\n", remote)
@@ -170,9 +167,9 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re
 	var repositoryTarget string
 	var repositoryTarget string
 	// If we are asking for 'root' repository, lookup on the Library's registry
 	// If we are asking for 'root' repository, lookup on the Library's registry
 	if strings.Index(remote, "/") == -1 {
 	if strings.Index(remote, "/") == -1 {
-		repositoryTarget = REGISTRY_ENDPOINT + "/library/" + remote
+		repositoryTarget = registry + "/library/" + remote
 	} else {
 	} else {
-		repositoryTarget = REGISTRY_ENDPOINT + "/users/" + remote
+		repositoryTarget = registry + "/users/" + remote
 	}
 	}
 
 
 	req, err := http.NewRequest("GET", repositoryTarget, nil)
 	req, err := http.NewRequest("GET", repositoryTarget, nil)
@@ -198,7 +195,7 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re
 	}
 	}
 	for tag, rev := range t {
 	for tag, rev := range t {
 		fmt.Fprintf(stdout, "Pulling tag %s:%s\r\n", remote, tag)
 		fmt.Fprintf(stdout, "Pulling tag %s:%s\r\n", remote, tag)
-		if err = graph.PullImage(stdout, rev, authConfig); err != nil {
+		if err = graph.PullImage(stdout, rev, registry, authConfig); err != nil {
 			return err
 			return err
 		}
 		}
 		if err = repositories.Set(remote, tag, rev, true); err != nil {
 		if err = repositories.Set(remote, tag, rev, true); err != nil {
@@ -303,7 +300,7 @@ func (graph *Graph) PushImage(stdout io.Writer, imgOrig *Image, authConfig *auth
 
 
 // push a tag on the registry.
 // push a tag on the registry.
 // Remote has the format '<user>/<repo>
 // Remote has the format '<user>/<repo>
-func (graph *Graph) pushTag(remote, revision, tag string, authConfig *auth.AuthConfig) error {
+func (graph *Graph) pushTag(remote, revision, tag, registry string, authConfig *auth.AuthConfig) error {
 
 
 	// Keep this for backward compatibility
 	// Keep this for backward compatibility
 	if tag == "" {
 	if tag == "" {
@@ -313,10 +310,10 @@ func (graph *Graph) pushTag(remote, revision, tag string, authConfig *auth.AuthC
 	// "jsonify" the string
 	// "jsonify" the string
 	revision = "\"" + revision + "\""
 	revision = "\"" + revision + "\""
 
 
-	Debugf("Pushing tags for rev [%s] on {%s}\n", revision, REGISTRY_ENDPOINT+"/users/"+remote+"/"+tag)
+	Debugf("Pushing tags for rev [%s] on {%s}\n", revision, registry+"/users/"+remote+"/"+tag)
 
 
 	client := &http.Client{}
 	client := &http.Client{}
-	req, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/users/"+remote+"/"+tag, strings.NewReader(revision))
+	req, err := http.NewRequest("PUT", registry+"/users/"+remote+"/"+tag, strings.NewReader(revision))
 	req.Header.Add("Content-type", "application/json")
 	req.Header.Add("Content-type", "application/json")
 	req.SetBasicAuth(authConfig.Username, authConfig.Password)
 	req.SetBasicAuth(authConfig.Username, authConfig.Password)
 	res, err := client.Do(req)
 	res, err := client.Do(req)
@@ -337,15 +334,20 @@ func (graph *Graph) pushTag(remote, revision, tag string, authConfig *auth.AuthC
 	return nil
 	return nil
 }
 }
 
 
-func (graph *Graph) LookupRemoteRepository(remote string, authConfig *auth.AuthConfig) bool {
+func (graph *Graph) LookupRemoteRepository(remote, registry string, authConfig *auth.AuthConfig) bool {
 	rt := &http.Transport{Proxy: http.ProxyFromEnvironment}
 	rt := &http.Transport{Proxy: http.ProxyFromEnvironment}
 
 
 	var repositoryTarget string
 	var repositoryTarget string
 	// If we are asking for 'root' repository, lookup on the Library's registry
 	// If we are asking for 'root' repository, lookup on the Library's registry
 	if strings.Index(remote, "/") == -1 {
 	if strings.Index(remote, "/") == -1 {
-		repositoryTarget = REGISTRY_ENDPOINT + "/library/" + remote + "/lookup"
+		repositoryTarget = registry + "/library/" + remote + "/lookup"
 	} else {
 	} else {
-		repositoryTarget = REGISTRY_ENDPOINT + "/users/" + remote + "/lookup"
+		parts := strings.Split(remote, "/")
+		if len(parts) != 2 {
+			Debugf("Repository must abide to following format: user/repo_name")
+			return false
+		}
+		repositoryTarget = registry + "/users/" + parts[0] + "/repositories/" + parts[1]
 	}
 	}
 	Debugf("Checking for permissions on: %s", repositoryTarget)
 	Debugf("Checking for permissions on: %s", repositoryTarget)
 	req, err := http.NewRequest("PUT", repositoryTarget, strings.NewReader("\"\""))
 	req, err := http.NewRequest("PUT", repositoryTarget, strings.NewReader("\"\""))
@@ -368,7 +370,7 @@ func (graph *Graph) LookupRemoteRepository(remote string, authConfig *auth.AuthC
 }
 }
 
 
 // FIXME: this should really be PushTag
 // FIXME: this should really be PushTag
-func (graph *Graph) pushPrimitive(stdout io.Writer, remote, tag, imgId string, authConfig *auth.AuthConfig) error {
+func (graph *Graph) pushPrimitive(stdout io.Writer, remote, tag, imgId, registry string, authConfig *auth.AuthConfig) error {
 	// Check if the local impage exists
 	// Check if the local impage exists
 	img, err := graph.Get(imgId)
 	img, err := graph.Get(imgId)
 	if err != nil {
 	if err != nil {
@@ -377,12 +379,12 @@ func (graph *Graph) pushPrimitive(stdout io.Writer, remote, tag, imgId string, a
 	}
 	}
 	fmt.Fprintf(stdout, "Pushing tag %s:%s\r\n", remote, tag)
 	fmt.Fprintf(stdout, "Pushing tag %s:%s\r\n", remote, tag)
 	// Push the image
 	// Push the image
-	if err = graph.PushImage(stdout, img, authConfig); err != nil {
+	if err = graph.PushImage(stdout, img, registry, authConfig); err != nil {
 		return err
 		return err
 	}
 	}
 	fmt.Fprintf(stdout, "Registering tag %s:%s\r\n", remote, tag)
 	fmt.Fprintf(stdout, "Registering tag %s:%s\r\n", remote, tag)
 	// And then the tag
 	// And then the tag
-	if err = graph.pushTag(remote, imgId, tag, authConfig); err != nil {
+	if err = graph.pushTag(remote, imgId, registry, tag, authConfig); err != nil {
 		return err
 		return err
 	}
 	}
 	return nil
 	return nil
@@ -390,16 +392,16 @@ func (graph *Graph) pushPrimitive(stdout io.Writer, remote, tag, imgId string, a
 
 
 // Push a repository to the registry.
 // Push a repository to the registry.
 // Remote has the format '<user>/<repo>
 // Remote has the format '<user>/<repo>
-func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Repository, authConfig *auth.AuthConfig) error {
+func (graph *Graph) PushRepository(stdout io.Writer, remote, registry string, localRepo Repository, authConfig *auth.AuthConfig) error {
 	// Check if the remote repository exists/if we have the permission
 	// Check if the remote repository exists/if we have the permission
-	if !graph.LookupRemoteRepository(remote, authConfig) {
+	if !graph.LookupRemoteRepository(remote, registry, authConfig) {
 		return fmt.Errorf("Permission denied on repository %s\n", remote)
 		return fmt.Errorf("Permission denied on repository %s\n", remote)
 	}
 	}
 
 
 	fmt.Fprintf(stdout, "Pushing repository %s (%d tags)\r\n", remote, len(localRepo))
 	fmt.Fprintf(stdout, "Pushing repository %s (%d tags)\r\n", remote, len(localRepo))
 	// For each image within the repo, push them
 	// For each image within the repo, push them
 	for tag, imgId := range localRepo {
 	for tag, imgId := range localRepo {
-		if err := graph.pushPrimitive(stdout, remote, tag, imgId, authConfig); err != nil {
+		if err := graph.pushPrimitive(stdout, remote, tag, imgId, registry, authConfig); err != nil {
 			// FIXME: Continue on error?
 			// FIXME: Continue on error?
 			return err
 			return err
 		}
 		}