Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image/mirror: Upconvert v1 schemas to v2 schemas by default #362

Merged
merged 1 commit into from
Apr 2, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 55 additions & 0 deletions pkg/cli/image/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,16 @@ func PutManifestInCompatibleSchema(
} else {
klog.V(5).Infof("Put manifest %s", ref)
}
switch t := srcManifest.(type) {
case *schema1.SignedManifest:
manifest, err := convertToSchema2(ctx, blobs, t)
if err != nil {
klog.V(2).Infof("Unable to convert manifest to schema2: %v", err)
return toManifests.Put(ctx, t, distribution.WithTag(tag))
}
return toManifests.Put(ctx, manifest, options...)
}

toDigest, err := toManifests.Put(ctx, srcManifest, options...)
if err == nil {
return toDigest, nil
Expand Down Expand Up @@ -483,6 +493,51 @@ func PutManifestInCompatibleSchema(
return toManifests.Put(ctx, schema1Manifest, distribution.WithTag(tag))
}

// convertToSchema2 attempts to build a v2 manifest from a v1 manifest, which requires reading blobs to get layer sizes.
// Requires the destination layers already exist in the target repository.
func convertToSchema2(ctx context.Context, blobs distribution.BlobService, srcManifest *schema1.SignedManifest) (distribution.Manifest, error) {
if klog.V(6) {
klog.Infof("Up converting v1 schema image:\n%#v", srcManifest.Manifest)
}

config, layers, err := ManifestToImageConfig(ctx, srcManifest, blobs, ManifestLocation{})
if err != nil {
return nil, err
}
if klog.V(6) {
klog.Infof("Resulting schema: %#v", config)
}
// create synthetic history
// TODO: create restored history?
if len(config.History) == 0 {
for i := len(config.History); i < len(layers); i++ {
config.History = append(config.History, dockerv1client.DockerConfigHistory{
Created: config.Created,
})
}
}

configJSON, err := json.Marshal(config)
if err != nil {
return nil, err
}
if klog.V(6) {
klog.Infof("Resulting config.json:\n%s", string(configJSON))
}
b := schema2.NewManifestBuilder(blobs, schema2.MediaTypeImageConfig, configJSON)
for _, layer := range layers {
desc, err := blobs.Stat(ctx, layer.Digest)
if err != nil {
return nil, err
}
desc.MediaType = schema2.MediaTypeLayer
if err := b.AppendReference(desc); err != nil {
return nil, err
}
}
return b.Build(ctx)
}

// TDOO: remove when quay.io switches to v2 schema
func convertToSchema1(ctx context.Context, blobs distribution.BlobService, configJSON []byte, schema2Manifest *schema2.DeserializedManifest, ref reference.Named) (distribution.Manifest, error) {
if configJSON == nil {
Expand Down