Fix replication bug

Fixes #7875, fixes #7968

Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
Wenkai Yin 2019-06-05 18:13:33 +08:00
parent d8b76c482a
commit 5fef7585c7
2 changed files with 27 additions and 11 deletions

View File

@ -25,6 +25,7 @@ import (
"time" "time"
"errors" "errors"
"github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema1"
"github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/manifest/schema2"
"github.com/goharbor/harbor/src/common" "github.com/goharbor/harbor/src/common"
@ -682,14 +683,17 @@ func getTagDetail(client *registry.Repository, tag string) (*tagDetail, error) {
Name: tag, Name: tag,
} }
digest, _, payload, err := client.PullManifest(tag, []string{schema2.MediaTypeManifest}) digest, mediaType, payload, err := client.PullManifest(tag, []string{schema2.MediaTypeManifest})
if err != nil { if err != nil {
return detail, err return detail, err
} }
detail.Digest = digest detail.Digest = digest
manifest := &schema2.DeserializedManifest{} if strings.Contains(mediaType, "application/json") {
if err = manifest.UnmarshalJSON(payload); err != nil { mediaType = schema1.MediaTypeManifest
}
manifest, _, err := registry.UnMarshal(mediaType, payload)
if err != nil {
return detail, err return detail, err
} }
@ -699,7 +703,21 @@ func getTagDetail(client *registry.Repository, tag string) (*tagDetail, error) {
detail.Size += ref.Size detail.Size += ref.Size
} }
_, reader, err := client.PullBlob(manifest.Target().Digest.String()) // if the media type of the manifest isn't v2, doesn't parse image config
// and return directly
// this impacts that some detail information(os, arch, ...) of old images
// cannot be got
if mediaType != schema2.MediaTypeManifest {
log.Debugf("the media type of the manifest is %s, not v2, skip", mediaType)
return detail, nil
}
v2Manifest, ok := manifest.(*schema2.DeserializedManifest)
if !ok {
log.Debug("the manifest cannot be convert to DeserializedManifest, skip")
return detail, nil
}
_, reader, err := client.PullBlob(v2Manifest.Target().Digest.String())
if err != nil { if err != nil {
return detail, err return detail, err
} }

View File

@ -211,18 +211,15 @@ func (t *transfer) copyContent(content distribution.Descriptor, srcRepo, dstRepo
case schema2.MediaTypeManifest: case schema2.MediaTypeManifest:
// as using digest as the reference, so set the override to true directly // as using digest as the reference, so set the override to true directly
return t.copyImage(srcRepo, digest, dstRepo, digest, true) return t.copyImage(srcRepo, digest, dstRepo, digest, true)
// copy layer or image config
case schema2.MediaTypeLayer, schema2.MediaTypeImageConfig:
return t.copyBlob(srcRepo, dstRepo, digest)
// handle foreign layer // handle foreign layer
case schema2.MediaTypeForeignLayer: case schema2.MediaTypeForeignLayer:
t.logger.Infof("the layer %s is a foreign layer, skip", digest) t.logger.Infof("the layer %s is a foreign layer, skip", digest)
return nil return nil
// others // copy layer or image config
// the media type of the layer or config can be "application/octet-stream",
// schema1.MediaTypeManifestLayer, schema2.MediaTypeLayer, schema2.MediaTypeImageConfig
default: default:
err := fmt.Errorf("unsupported media type: %s", content.MediaType) return t.copyBlob(srcRepo, dstRepo, digest)
t.logger.Error(err.Error())
return err
} }
} }
@ -288,6 +285,7 @@ func (t *transfer) handleManifest(manifest distribution.Manifest, repository, di
} }
// manifest // manifest
if mediaType == schema1.MediaTypeManifest || if mediaType == schema1.MediaTypeManifest ||
mediaType == schema1.MediaTypeSignedManifest ||
mediaType == schema2.MediaTypeManifest { mediaType == schema2.MediaTypeManifest {
return manifest, digest, nil return manifest, digest, nil
} }