mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #13374 from RichardScothern/v2-mirror
V2 mirror support
This commit is contained in:
commit
2daede5a9c
2 changed files with 109 additions and 6 deletions
111
graph/pull.go
111
graph/pull.go
|
@ -55,6 +55,25 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf
|
||||||
}
|
}
|
||||||
defer s.poolRemove("pull", utils.ImageReference(repoInfo.LocalName, tag))
|
defer s.poolRemove("pull", utils.ImageReference(repoInfo.LocalName, tag))
|
||||||
|
|
||||||
|
logName := repoInfo.LocalName
|
||||||
|
if tag != "" {
|
||||||
|
logName = utils.ImageReference(logName, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt pulling official content from a provided v2 mirror
|
||||||
|
if repoInfo.Index.Official {
|
||||||
|
v2mirrorEndpoint, v2mirrorRepoInfo, err := configureV2Mirror(repoInfo, s.registryService)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("Error configuring mirrors: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v2mirrorEndpoint != nil {
|
||||||
|
logrus.Debugf("Attempting to pull from v2 mirror: %s", v2mirrorEndpoint.URL)
|
||||||
|
return s.pullFromV2Mirror(v2mirrorEndpoint, v2mirrorRepoInfo, imagePullConfig, tag, sf, logName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logrus.Debugf("pulling image from host %q with remote name %q", repoInfo.Index.Name, repoInfo.RemoteName)
|
logrus.Debugf("pulling image from host %q with remote name %q", repoInfo.Index.Name, repoInfo.RemoteName)
|
||||||
|
|
||||||
endpoint, err := repoInfo.GetEndpoint(imagePullConfig.MetaHeaders)
|
endpoint, err := repoInfo.GetEndpoint(imagePullConfig.MetaHeaders)
|
||||||
|
@ -73,11 +92,6 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logName := repoInfo.LocalName
|
|
||||||
if tag != "" {
|
|
||||||
logName = utils.ImageReference(logName, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(repoInfo.Index.Mirrors) == 0 && (repoInfo.Index.Official || endpoint.Version == registry.APIVersion2) {
|
if len(repoInfo.Index.Mirrors) == 0 && (repoInfo.Index.Official || endpoint.Version == registry.APIVersion2) {
|
||||||
if repoInfo.Official {
|
if repoInfo.Official {
|
||||||
s.trustService.UpdateBase()
|
s.trustService.UpdateBase()
|
||||||
|
@ -106,6 +120,91 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf
|
||||||
s.eventsService.Log("pull", logName, "")
|
s.eventsService.Log("pull", logName, "")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeMirrorRepoInfo(repoInfo *registry.RepositoryInfo, mirror string) *registry.RepositoryInfo {
|
||||||
|
mirrorRepo := ®istry.RepositoryInfo{
|
||||||
|
RemoteName: repoInfo.RemoteName,
|
||||||
|
LocalName: repoInfo.LocalName,
|
||||||
|
CanonicalName: repoInfo.CanonicalName,
|
||||||
|
Official: false,
|
||||||
|
|
||||||
|
Index: ®istry.IndexInfo{
|
||||||
|
Official: false,
|
||||||
|
Secure: repoInfo.Index.Secure,
|
||||||
|
Name: mirror,
|
||||||
|
Mirrors: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return mirrorRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureV2Mirror(repoInfo *registry.RepositoryInfo, s *registry.Service) (*registry.Endpoint, *registry.RepositoryInfo, error) {
|
||||||
|
mirrors := repoInfo.Index.Mirrors
|
||||||
|
|
||||||
|
if len(mirrors) == 0 {
|
||||||
|
// no mirrors configured
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v1MirrorCount := 0
|
||||||
|
var v2MirrorEndpoint *registry.Endpoint
|
||||||
|
var v2MirrorRepoInfo *registry.RepositoryInfo
|
||||||
|
var lastErr error
|
||||||
|
for _, mirror := range mirrors {
|
||||||
|
mirrorRepoInfo := makeMirrorRepoInfo(repoInfo, mirror)
|
||||||
|
endpoint, err := registry.NewEndpoint(mirrorRepoInfo.Index, nil)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("Unable to create endpoint for %s: %s", mirror, err)
|
||||||
|
lastErr = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if endpoint.Version == 2 {
|
||||||
|
if v2MirrorEndpoint == nil {
|
||||||
|
v2MirrorEndpoint = endpoint
|
||||||
|
v2MirrorRepoInfo = mirrorRepoInfo
|
||||||
|
} else {
|
||||||
|
// > 1 v2 mirrors given
|
||||||
|
return nil, nil, fmt.Errorf("multiple v2 mirrors configured")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v1MirrorCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v1MirrorCount == len(mirrors) {
|
||||||
|
// OK, but mirrors are v1
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
if v2MirrorEndpoint != nil && v1MirrorCount == 0 {
|
||||||
|
// OK, 1 v2 mirror specified
|
||||||
|
return v2MirrorEndpoint, v2MirrorRepoInfo, nil
|
||||||
|
}
|
||||||
|
if v2MirrorEndpoint != nil && v1MirrorCount > 0 {
|
||||||
|
lastErr = fmt.Errorf("v1 and v2 mirrors configured")
|
||||||
|
}
|
||||||
|
return nil, nil, lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TagStore) pullFromV2Mirror(mirrorEndpoint *registry.Endpoint, repoInfo *registry.RepositoryInfo,
|
||||||
|
imagePullConfig *ImagePullConfig, tag string, sf *streamformatter.StreamFormatter, logName string) error {
|
||||||
|
|
||||||
|
tr := transport.NewTransport(
|
||||||
|
registry.NewTransport(registry.ReceiveTimeout, mirrorEndpoint.IsSecure),
|
||||||
|
registry.DockerHeaders(imagePullConfig.MetaHeaders)...,
|
||||||
|
)
|
||||||
|
client := registry.HTTPClient(tr)
|
||||||
|
mirrorSession, err := registry.NewSession(client, &cliconfig.AuthConfig{}, mirrorEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("Pulling v2 repository with local name %q from %s", repoInfo.LocalName, mirrorEndpoint.URL)
|
||||||
|
if err := s.pullV2Repository(mirrorSession, imagePullConfig.OutStream, repoInfo, tag, sf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.eventsService.Log("pull", logName, "")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, repoInfo *registry.RepositoryInfo, askedTag string, sf *streamformatter.StreamFormatter) error {
|
func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, repoInfo *registry.RepositoryInfo, askedTag string, sf *streamformatter.StreamFormatter) error {
|
||||||
|
@ -185,6 +284,8 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, repoInfo *
|
||||||
var lastErr, err error
|
var lastErr, err error
|
||||||
var isDownloaded bool
|
var isDownloaded bool
|
||||||
for _, ep := range repoInfo.Index.Mirrors {
|
for _, ep := range repoInfo.Index.Mirrors {
|
||||||
|
// Ensure endpoint is v1
|
||||||
|
ep = ep + "v1/"
|
||||||
out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, repoInfo.CanonicalName, ep), nil))
|
out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, repoInfo.CanonicalName, ep), nil))
|
||||||
if isDownloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
if isDownloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||||
// Don't report errors when pulling from mirrors.
|
// Don't report errors when pulling from mirrors.
|
||||||
|
|
|
@ -189,7 +189,7 @@ func ValidateMirror(val string) (string, error) {
|
||||||
return "", fmt.Errorf("Unsupported path/query/fragment at end of the URI")
|
return "", fmt.Errorf("Unsupported path/query/fragment at end of the URI")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s://%s/v1/", uri.Scheme, uri.Host), nil
|
return fmt.Sprintf("%s://%s/", uri.Scheme, uri.Host), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateIndexName validates an index name.
|
// ValidateIndexName validates an index name.
|
||||||
|
@ -358,7 +358,9 @@ func (config *ServiceConfig) NewRepositoryInfo(reposName string) (*RepositoryInf
|
||||||
// *TODO: Decouple index name from hostname (via registry configuration?)
|
// *TODO: Decouple index name from hostname (via registry configuration?)
|
||||||
repoInfo.LocalName = repoInfo.Index.Name + "/" + repoInfo.RemoteName
|
repoInfo.LocalName = repoInfo.Index.Name + "/" + repoInfo.RemoteName
|
||||||
repoInfo.CanonicalName = repoInfo.LocalName
|
repoInfo.CanonicalName = repoInfo.LocalName
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return repoInfo, nil
|
return repoInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue