From 4bcc443e6ccd7b50bd33defebc61382222e7d117 Mon Sep 17 00:00:00 2001 From: Gladkov Alexey Date: Wed, 1 Jun 2016 19:17:07 +0200 Subject: [PATCH] Fix image size calculation in importer After upgrading docker/distibution V1Compatibility no longer contains Size. For this reason, the image size calculation is wrong. A new way to calculate the size repeats the way that dockerregistry calculates the size. --- pkg/image/api/helper.go | 2 ++ pkg/image/importer/importer.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/pkg/image/api/helper.go b/pkg/image/api/helper.go index 4e9281edcd07..0c6b59ed4629 100644 --- a/pkg/image/api/helper.go +++ b/pkg/image/api/helper.go @@ -363,6 +363,8 @@ func ImageWithMetadata(image *Image) error { image.DockerImageLayers[i].Name = layer.DockerBlobSum } if len(manifest.History) == len(image.DockerImageLayers) { + // This code does not work since hub.docker.com has been updated. + // The V1Compatibility no longer contains Size. image.DockerImageLayers[0].Size = v1Metadata.Size var size = DockerV1CompatibilityImageSize{} for i, obj := range manifest.History[1:] { diff --git a/pkg/image/importer/importer.go b/pkg/image/importer/importer.go index f11030b5703c..b0423e93efa2 100644 --- a/pkg/image/importer/importer.go +++ b/pkg/image/importer/importer.go @@ -282,6 +282,27 @@ func applyErrorToRepository(repository *importRepository, err error) { } } +func calculateImageSize(ctx gocontext.Context, repo distribution.Repository, image *api.Image) error { + bs := repo.Blobs(ctx) + + layerSet := sets.NewString() + size := int64(0) + for i := range image.DockerImageLayers { + layer := &image.DockerImageLayers[i] + desc, err := bs.Stat(ctx, digest.Digest(layer.Name)) + if err != nil { + return err + } + layer.Size = desc.Size + if !layerSet.Has(layer.Name) { + size += desc.Size + layerSet.Insert(layer.Name) + } + } + image.DockerImageMetadata.Size = size + return nil +} + // importRepositoryFromDocker loads the tags and images requested in the passed importRepository, obeying the // optional rate limiter. Errors are set onto the individual tags and digest objects. func importRepositoryFromDocker(ctx gocontext.Context, retriever RepositoryRetriever, repository *importRepository, limiter flowcontrol.RateLimiter) { @@ -397,6 +418,12 @@ func importRepositoryFromDocker(ctx gocontext.Context, retriever RepositoryRetri importDigest.Err = err continue } + if importDigest.Image.DockerImageMetadata.Size == 0 { + if err := calculateImageSize(ctx, repo, importDigest.Image); err != nil { + importDigest.Err = err + continue + } + } } for i := range repository.Tags { @@ -430,6 +457,12 @@ func importRepositoryFromDocker(ctx gocontext.Context, retriever RepositoryRetri importTag.Err = err continue } + if importTag.Image.DockerImageMetadata.Size == 0 { + if err := calculateImageSize(ctx, repo, importTag.Image); err != nil { + importTag.Err = err + continue + } + } } }