зеркало из https://github.com/microsoft/docker.git
Allow push of a single tag
Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <guillaume@charmes.net> (github: creack)
This commit is contained in:
Родитель
f6f059d99a
Коммит
e648a186d6
|
@ -1000,7 +1000,7 @@ func (cli *DockerCli) CmdImport(args ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *DockerCli) CmdPush(args ...string) error {
|
func (cli *DockerCli) CmdPush(args ...string) error {
|
||||||
cmd := cli.Subcmd("push", "NAME", "Push an image or a repository to the registry")
|
cmd := cli.Subcmd("push", "NAME[:TAG]", "Push an image or a repository to the registry")
|
||||||
if err := cmd.Parse(args); err != nil {
|
if err := cmd.Parse(args); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1013,8 +1013,10 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
||||||
|
|
||||||
cli.LoadConfigFile()
|
cli.LoadConfigFile()
|
||||||
|
|
||||||
|
remote, tag := utils.ParseRepositoryTag(name)
|
||||||
|
|
||||||
// Resolve the Repository name from fqn to hostname + name
|
// Resolve the Repository name from fqn to hostname + name
|
||||||
hostname, _, err := registry.ResolveRepositoryName(name)
|
hostname, _, err := registry.ResolveRepositoryName(remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1033,6 +1035,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
v.Set("tag", tag)
|
||||||
push := func(authConfig registry.AuthConfig) error {
|
push := func(authConfig registry.AuthConfig) error {
|
||||||
buf, err := json.Marshal(authConfig)
|
buf, err := json.Marshal(authConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1042,7 +1045,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
||||||
base64.URLEncoding.EncodeToString(buf),
|
base64.URLEncoding.EncodeToString(buf),
|
||||||
}
|
}
|
||||||
|
|
||||||
return cli.stream("POST", "/images/"+name+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
|
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
|
||||||
"X-Registry-Auth": registryAuthHeader,
|
"X-Registry-Auth": registryAuthHeader,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,6 +517,7 @@ func postImagesPush(eng *engine.Engine, version version.Version, w http.Response
|
||||||
job := eng.Job("push", vars["name"])
|
job := eng.Job("push", vars["name"])
|
||||||
job.SetenvJson("metaHeaders", metaHeaders)
|
job.SetenvJson("metaHeaders", metaHeaders)
|
||||||
job.SetenvJson("authConfig", authConfig)
|
job.SetenvJson("authConfig", authConfig)
|
||||||
|
job.Setenv("tag", r.Form.Get("tag"))
|
||||||
if version.GreaterThan("1.0") {
|
if version.GreaterThan("1.0") {
|
||||||
job.SetenvBool("json", true)
|
job.SetenvBool("json", true)
|
||||||
streamJSON(job, w, true)
|
streamJSON(job, w, true)
|
||||||
|
|
|
@ -1401,7 +1401,7 @@ func (srv *Server) ImagePull(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the all the images to be uploaded in the correct order
|
// Retrieve the all the images to be uploaded in the correct order
|
||||||
func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[string][]string, error) {
|
func (srv *Server) getImageList(localRepo map[string]string, requestedTag string) ([]string, map[string][]string, error) {
|
||||||
var (
|
var (
|
||||||
imageList []string
|
imageList []string
|
||||||
imagesSeen map[string]bool = make(map[string]bool)
|
imagesSeen map[string]bool = make(map[string]bool)
|
||||||
|
@ -1409,6 +1409,9 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[stri
|
||||||
)
|
)
|
||||||
|
|
||||||
for tag, id := range localRepo {
|
for tag, id := range localRepo {
|
||||||
|
if requestedTag != "" && requestedTag != tag {
|
||||||
|
continue
|
||||||
|
}
|
||||||
var imageListForThisTag []string
|
var imageListForThisTag []string
|
||||||
|
|
||||||
tagsByImage[id] = append(tagsByImage[id], tag)
|
tagsByImage[id] = append(tagsByImage[id], tag)
|
||||||
|
@ -1435,25 +1438,29 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[stri
|
||||||
// append to main image list
|
// append to main image list
|
||||||
imageList = append(imageList, imageListForThisTag...)
|
imageList = append(imageList, imageListForThisTag...)
|
||||||
}
|
}
|
||||||
|
if len(imageList) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("No images found for the requested repository / tag")
|
||||||
|
}
|
||||||
utils.Debugf("Image list: %v", imageList)
|
utils.Debugf("Image list: %v", imageList)
|
||||||
utils.Debugf("Tags by image: %v", tagsByImage)
|
utils.Debugf("Tags by image: %v", tagsByImage)
|
||||||
|
|
||||||
return imageList, tagsByImage, nil
|
return imageList, tagsByImage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, sf *utils.StreamFormatter) error {
|
func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, tag string, sf *utils.StreamFormatter) error {
|
||||||
out = utils.NewWriteFlusher(out)
|
out = utils.NewWriteFlusher(out)
|
||||||
utils.Debugf("Local repo: %s", localRepo)
|
utils.Debugf("Local repo: %s", localRepo)
|
||||||
imgList, tagsByImage, err := srv.getImageList(localRepo)
|
imgList, tagsByImage, err := srv.getImageList(localRepo, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write(sf.FormatStatus("", "Sending image list"))
|
out.Write(sf.FormatStatus("", "Sending image list"))
|
||||||
|
|
||||||
var repoData *registry.RepositoryData
|
var (
|
||||||
var imageIndex []*registry.ImgData
|
repoData *registry.RepositoryData
|
||||||
|
imageIndex []*registry.ImgData
|
||||||
|
)
|
||||||
|
|
||||||
for _, imgId := range imgList {
|
for _, imgId := range imgList {
|
||||||
if tags, exists := tagsByImage[imgId]; exists {
|
if tags, exists := tagsByImage[imgId]; exists {
|
||||||
|
@ -1488,8 +1495,12 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nTag := 1
|
||||||
|
if tag == "" {
|
||||||
|
nTag = len(localRepo)
|
||||||
|
}
|
||||||
for _, ep := range repoData.Endpoints {
|
for _, ep := range repoData.Endpoints {
|
||||||
out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, len(localRepo)))
|
out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, nTag))
|
||||||
|
|
||||||
for _, imgId := range imgList {
|
for _, imgId := range imgList {
|
||||||
if r.LookupRemoteImage(imgId, ep, repoData.Tokens) {
|
if r.LookupRemoteImage(imgId, ep, repoData.Tokens) {
|
||||||
|
@ -1575,6 +1586,7 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status {
|
||||||
metaHeaders map[string][]string
|
metaHeaders map[string][]string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tag := job.Getenv("tag")
|
||||||
job.GetenvJson("authConfig", authConfig)
|
job.GetenvJson("authConfig", authConfig)
|
||||||
job.GetenvJson("metaHeaders", metaHeaders)
|
job.GetenvJson("metaHeaders", metaHeaders)
|
||||||
if _, err := srv.poolAdd("push", localName); err != nil {
|
if _, err := srv.poolAdd("push", localName); err != nil {
|
||||||
|
@ -1600,11 +1612,14 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reposLen := len(srv.runtime.Repositories().Repositories[localName])
|
reposLen := 1
|
||||||
|
if tag == "" {
|
||||||
|
reposLen = len(srv.runtime.Repositories().Repositories[localName])
|
||||||
|
}
|
||||||
job.Stdout.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
|
job.Stdout.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
|
||||||
// If it fails, try to get the repository
|
// If it fails, try to get the repository
|
||||||
if localRepo, exists := srv.runtime.Repositories().Repositories[localName]; exists {
|
if localRepo, exists := srv.runtime.Repositories().Repositories[localName]; exists {
|
||||||
if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, sf); err != nil {
|
if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, tag, sf); err != nil {
|
||||||
return job.Error(err)
|
return job.Error(err)
|
||||||
}
|
}
|
||||||
return engine.StatusOK
|
return engine.StatusOK
|
||||||
|
|
Загрузка…
Ссылка в новой задаче