6856a6b1 |
package graph
import (
"fmt"
"io"
|
6f4d8470 |
"github.com/Sirupsen/logrus" |
bb9da6ba |
"github.com/docker/docker/cliconfig" |
0cd6c05d |
"github.com/docker/docker/pkg/streamformatter" |
6856a6b1 |
"github.com/docker/docker/registry"
)
|
d456401f |
type ImagePushConfig struct {
MetaHeaders map[string][]string |
bb9da6ba |
AuthConfig *cliconfig.AuthConfig |
d456401f |
Tag string
OutStream io.Writer
}
|
19515a7a |
type Pusher interface {
// Push tries to push the image configured at the creation of Pusher.
// Push returns an error if any, as well as a boolean that determines whether to retry Push on the next configured endpoint.
//
// TODO(tiborvass): have Push() take a reference to repository + tag, so that the pusher itself is repository-agnostic.
Push() (fallback bool, err error) |
6856a6b1 |
}
|
19515a7a |
func (s *TagStore) NewPusher(endpoint registry.APIEndpoint, localRepo Repository, repoInfo *registry.RepositoryInfo, imagePushConfig *ImagePushConfig, sf *streamformatter.StreamFormatter) (Pusher, error) {
switch endpoint.Version {
case registry.APIVersion2:
return &v2Pusher{ |
810d3b26 |
TagStore: s,
endpoint: endpoint,
localRepo: localRepo,
repoInfo: repoInfo,
config: imagePushConfig,
sf: sf,
layersSeen: make(map[string]bool), |
19515a7a |
}, nil
case registry.APIVersion1:
return &v1Pusher{
TagStore: s,
endpoint: endpoint,
localRepo: localRepo,
repoInfo: repoInfo,
config: imagePushConfig,
sf: sf,
}, nil
}
return nil, fmt.Errorf("unknown version %d for registry %s", endpoint.Version, endpoint.URL) |
629815b4 |
}
|
6856a6b1 |
// FIXME: Allow to interrupt current push when new push of same image is done. |
d456401f |
func (s *TagStore) Push(localName string, imagePushConfig *ImagePushConfig) error { |
19515a7a |
var sf = streamformatter.NewJSONStreamFormatter() |
6856a6b1 |
|
568f86eb |
// Resolve the Repository name from fqn to RepositoryInfo |
03d3d79b |
repoInfo, err := s.registryService.ResolveRepository(localName) |
568f86eb |
if err != nil { |
c79b9bab |
return err |
568f86eb |
}
|
29ea36a8 |
endpoints, err := s.registryService.LookupPushEndpoints(repoInfo.CanonicalName) |
db2d875b |
if err != nil { |
c79b9bab |
return err |
6856a6b1 |
}
|
db2d875b |
reposLen := 1 |
d456401f |
if imagePushConfig.Tag == "" { |
db2d875b |
reposLen = len(s.Repositories[repoInfo.LocalName]) |
750b41ce |
} |
d456401f |
imagePushConfig.OutStream.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", repoInfo.CanonicalName, reposLen))
|
db2d875b |
// If it fails, try to get the repository
localRepo, exists := s.Repositories[repoInfo.LocalName]
if !exists { |
c79b9bab |
return fmt.Errorf("Repository does not exist: %s", repoInfo.LocalName) |
db2d875b |
} |
d172f125 |
|
19515a7a |
var lastErr error
for _, endpoint := range endpoints {
logrus.Debugf("Trying to push %s to %s %s", repoInfo.CanonicalName, endpoint.URL, endpoint.Version)
pusher, err := s.NewPusher(endpoint, localRepo, repoInfo, imagePushConfig, sf)
if err != nil {
lastErr = err
continue |
d172f125 |
} |
19515a7a |
if fallback, err := pusher.Push(); err != nil {
if fallback {
lastErr = err
continue
}
logrus.Debugf("Not continuing with error: %v", err)
return err |
d172f125 |
}
|
19515a7a |
s.eventsService.Log("push", repoInfo.LocalName, "")
return nil |
6856a6b1 |
} |
db2d875b |
|
19515a7a |
if lastErr == nil {
lastErr = fmt.Errorf("no endpoints found for %s", repoInfo.CanonicalName)
}
return lastErr |
6856a6b1 |
} |