Reimplemented feature: downloading all tags on a repository using docker pull. Temporarily commented out CmdPush
This commit is contained in:
parent
2f082510a7
commit
e639309a7a
2 changed files with 157 additions and 152 deletions
102
commands.go
102
commands.go
|
@ -492,64 +492,64 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout rcli.DockerConn, args .
|
|||
return nil
|
||||
}
|
||||
|
||||
func (srv *Server) CmdPush(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "push", "NAME", "Push an image or a repository to the registry")
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
local := cmd.Arg(0)
|
||||
// func (srv *Server) CmdPush(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error {
|
||||
// cmd := rcli.Subcmd(stdout, "push", "NAME", "Push an image or a repository to the registry")
|
||||
// if err := cmd.Parse(args); err != nil {
|
||||
// return nil
|
||||
// }
|
||||
// local := cmd.Arg(0)
|
||||
|
||||
if local == "" {
|
||||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
// if local == "" {
|
||||
// cmd.Usage()
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// If the login failed, abort
|
||||
if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" {
|
||||
if err := srv.CmdLogin(stdin, stdout, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" {
|
||||
return fmt.Errorf("Please login prior to push. ('docker login')")
|
||||
}
|
||||
}
|
||||
// // If the login failed, abort
|
||||
// if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" {
|
||||
// if err := srv.CmdLogin(stdin, stdout, args...); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" {
|
||||
// return fmt.Errorf("Please login prior to push. ('docker login')")
|
||||
// }
|
||||
// }
|
||||
|
||||
var remote string
|
||||
// var remote string
|
||||
|
||||
tmp := strings.SplitN(local, "/", 2)
|
||||
if len(tmp) == 1 {
|
||||
return fmt.Errorf(
|
||||
"Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)",
|
||||
srv.runtime.authConfig.Username, local)
|
||||
} else {
|
||||
remote = local
|
||||
}
|
||||
// tmp := strings.SplitN(local, "/", 2)
|
||||
// if len(tmp) == 1 {
|
||||
// return fmt.Errorf(
|
||||
// "Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)",
|
||||
// srv.runtime.authConfig.Username, local)
|
||||
// } else {
|
||||
// remote = local
|
||||
// }
|
||||
|
||||
Debugf("Pushing [%s] to [%s]\n", local, remote)
|
||||
// Debugf("Pushing [%s] to [%s]\n", local, remote)
|
||||
|
||||
// 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(local)
|
||||
if err != nil {
|
||||
Debugf("The push refers to a repository [%s] (len: %d)\n", local, len(srv.runtime.repositories.Repositories[local]))
|
||||
// If it fails, try to get the repository
|
||||
if localRepo, exists := srv.runtime.repositories.Repositories[local]; exists {
|
||||
if err := srv.runtime.graph.PushRepository(stdout, remote, localRepo, srv.runtime.authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
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(local)
|
||||
// if err != nil {
|
||||
// Debugf("The push refers to a repository [%s] (len: %d)\n", local, len(srv.runtime.repositories.Repositories[local]))
|
||||
// // If it fails, try to get the repository
|
||||
// if localRepo, exists := srv.runtime.repositories.Repositories[local]; exists {
|
||||
// if err := srv.runtime.graph.PushRepository(stdout, remote, localRepo, srv.runtime.authConfig); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
return err
|
||||
}
|
||||
err = srv.runtime.graph.PushImage(stdout, img, srv.runtime.authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// return err
|
||||
// }
|
||||
// err = srv.runtime.graph.PushImage(stdout, img, srv.runtime.authConfig)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "pull", "NAME", "Pull an image or a repository from the registry")
|
||||
|
|
207
registry.go
207
registry.go
|
@ -139,6 +139,79 @@ func (graph *Graph) getRemoteImage(stdout io.Writer, imgId, registry string, tok
|
|||
return img, ProgressReader(res.Body, int(res.ContentLength), stdout, "Downloading %v/%v (%v)"), nil
|
||||
}
|
||||
|
||||
func (graph *Graph) getRemoteTags(stdout io.Writer, registries []string, repository string, token []string) (map[string]string, error) {
|
||||
client := &http.Client{}
|
||||
for _, host := range registries {
|
||||
endpoint := "https://" + host + "/v1/repositories/users/" + repository + "/tags"
|
||||
req, err := http.NewRequest("GET", endpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header["X-Docker-Token"] = token
|
||||
res, err := client.Do(req)
|
||||
defer res.Body.Close()
|
||||
if err != nil || (res.StatusCode != 200 && res.StatusCode != 404) {
|
||||
Debugf("Registry isn't responding: trying another registry endpoint")
|
||||
continue
|
||||
} else if res.StatusCode == 404 {
|
||||
return nil, fmt.Errorf("Repository not found")
|
||||
}
|
||||
|
||||
var result *map[string]string
|
||||
|
||||
rawJson, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = json.Unmarshal(rawJson, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return *result, nil
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("Could not reach any registry endpoint")
|
||||
}
|
||||
|
||||
func (graph *Graph) getImageForTag(stdout io.Writer, tag, remote, registry string, token []string) (string, error) {
|
||||
client := &http.Client{}
|
||||
registryEndpoint := "https://" + registry + "/v1"
|
||||
var repositoryTarget string
|
||||
if strings.Index(remote, "/") == -1 {
|
||||
repositoryTarget = registryEndpoint + "/repositories/library/" +
|
||||
remote + "/tags/" + tag
|
||||
} else {
|
||||
repositoryTarget = registryEndpoint + "/repositories/users/" +
|
||||
remote + "/tags/" + tag
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", repositoryTarget, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header["X-Docker-Token"] = token
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error while retrieving repository info: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == 403 {
|
||||
return "", fmt.Errorf("You aren't authorized to access this resource")
|
||||
} else if res.StatusCode != 200 {
|
||||
return "", fmt.Errorf("HTTP code: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
var imgId string
|
||||
rawJson, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = json.Unmarshal(rawJson, &imgId); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return imgId, nil
|
||||
}
|
||||
|
||||
func (graph *Graph) PullImage(stdout io.Writer, imgId, registry string, token []string) error {
|
||||
history, err := graph.getRemoteHistory(imgId, registry, token)
|
||||
if err != nil {
|
||||
|
@ -161,56 +234,6 @@ func (graph *Graph) PullImage(stdout io.Writer, imgId, registry string, token []
|
|||
return nil
|
||||
}
|
||||
|
||||
// // FIXME: Handle the askedTag parameter
|
||||
// func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag, registry string, repositories *TagStore, authConfig *auth.AuthConfig) error {
|
||||
// client := &http.Client{}
|
||||
|
||||
// fmt.Fprintf(stdout, "Pulling repository %s\r\n", remote)
|
||||
|
||||
// var repositoryTarget string
|
||||
// // If we are asking for 'root' repository, lookup on the Library's registry
|
||||
// if strings.Index(remote, "/") == -1 {
|
||||
// repositoryTarget = registry + "/library/" + remote
|
||||
// } else {
|
||||
// repositoryTarget = registry + "/users/" + remote
|
||||
// }
|
||||
|
||||
// req, err := http.NewRequest("GET", repositoryTarget, nil)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// req.SetBasicAuth(authConfig.Username, authConfig.Password)
|
||||
// res, err := client.Do(req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// defer res.Body.Close()
|
||||
// if res.StatusCode != 200 {
|
||||
// return fmt.Errorf("HTTP code: %d", res.StatusCode)
|
||||
// }
|
||||
// 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 {
|
||||
// fmt.Fprintf(stdout, "Pulling tag %s:%s\r\n", remote, tag)
|
||||
// if err = graph.PullImage(stdout, rev, registry, authConfig); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if err = repositories.Set(remote, tag, rev, true); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if err = repositories.Save(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, repositories *TagStore, authConfig *auth.AuthConfig) error {
|
||||
client := &http.Client{}
|
||||
|
||||
|
@ -253,66 +276,48 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re
|
|||
}
|
||||
|
||||
// FIXME: If askedTag is empty, fetch all tags.
|
||||
var tagsList map[string]string
|
||||
if askedTag == "" {
|
||||
askedTag = "latest"
|
||||
}
|
||||
|
||||
for _, registry := range endpoints {
|
||||
registryEndpoint := "https://" + registry + "/v1"
|
||||
if strings.Index(remote, "/") == -1 {
|
||||
repositoryTarget = registryEndpoint + "/repositories/library/" +
|
||||
remote + "/tags/" + askedTag
|
||||
} else {
|
||||
repositoryTarget = registryEndpoint + "/repositories/users/" +
|
||||
remote + "/tags/" + askedTag
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("GET", repositoryTarget, nil)
|
||||
tagsList, err = graph.getRemoteTags(stdout, endpoints, remote, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header["X-Docker-Token"] = token
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Fprintf(stdout, "Error while retrieving repository info: %v ; " +
|
||||
"checking next endpoint")
|
||||
continue
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == 403 {
|
||||
if authConfig == nil {
|
||||
return fmt.Errorf("You need to be authenticated to access this resource")
|
||||
} else {
|
||||
return fmt.Errorf("You aren't authorized to access this resource")
|
||||
} else {
|
||||
tagsList = map[string]string{ askedTag : "" }
|
||||
}
|
||||
|
||||
for askedTag, imgId := range tagsList {
|
||||
success := false
|
||||
for _, registry := range endpoints {
|
||||
if imgId == "" {
|
||||
imgId, err = graph.getImageForTag(stdout, askedTag, remote, registry, token)
|
||||
if err != nil {
|
||||
fmt.Fprintf(stdout, "Error while retrieving image for tag: %v (%v) ; " +
|
||||
"checking next endpoint", askedTag, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else if res.StatusCode != 200 {
|
||||
return fmt.Errorf("HTTP code: %d", res.StatusCode)
|
||||
|
||||
if err := graph.PullImage(stdout, imgId, "https://" + registry + "/v1", token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = repositories.Set(remote, askedTag, imgId, true); err != nil {
|
||||
return err
|
||||
}
|
||||
success = true
|
||||
}
|
||||
|
||||
var imgId string
|
||||
rawJson, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
if !success {
|
||||
return fmt.Errorf("Could not find repository on any of the indexed registries.")
|
||||
}
|
||||
if err = json.Unmarshal(rawJson, &imgId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := graph.PullImage(stdout, imgId, registryEndpoint, token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = repositories.Set(remote, askedTag, imgId, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = repositories.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Could not find repository on any of the indexed registries.")
|
||||
|
||||
if err = repositories.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Push a local image to the registry with its history if needed
|
||||
|
|
Loading…
Reference in a new issue