forked from TrueCloudLab/distribution
2de3f1a62a
The schema2 manifest builder fills in this part of the manifest based on the descriptor it gets back from BlobIngester's Put method. It passes the correct media type to Put, but Put ends up replacing this value with application/octet-stream in its return value. This commit works around the issue in the manifest builder. Arguably Put should not be changing the media type in its return value, but this commit is a targeted fix to keep it very low-risk for possible inclusion in Docker 1.11. Fixes #1621 (but maybe we should open a separate issue for the media type behavior in the distribution client, and the unnecessary stat). Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package schema2
|
|
|
|
import (
|
|
"github.com/docker/distribution"
|
|
"github.com/docker/distribution/context"
|
|
"github.com/docker/distribution/digest"
|
|
)
|
|
|
|
// builder is a type for constructing manifests.
|
|
type builder struct {
|
|
// bs is a BlobService used to publish the configuration blob.
|
|
bs distribution.BlobService
|
|
|
|
// configJSON references
|
|
configJSON []byte
|
|
|
|
// layers is a list of layer descriptors that gets built by successive
|
|
// calls to AppendReference.
|
|
layers []distribution.Descriptor
|
|
}
|
|
|
|
// NewManifestBuilder is used to build new manifests for the current schema
|
|
// version. It takes a BlobService so it can publish the configuration blob
|
|
// as part of the Build process.
|
|
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribution.ManifestBuilder {
|
|
mb := &builder{
|
|
bs: bs,
|
|
configJSON: make([]byte, len(configJSON)),
|
|
}
|
|
copy(mb.configJSON, configJSON)
|
|
|
|
return mb
|
|
}
|
|
|
|
// Build produces a final manifest from the given references.
|
|
func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
|
m := Manifest{
|
|
Versioned: SchemaVersion,
|
|
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
|
}
|
|
copy(m.Layers, mb.layers)
|
|
|
|
configDigest := digest.FromBytes(mb.configJSON)
|
|
|
|
var err error
|
|
m.Config, err = mb.bs.Stat(ctx, configDigest)
|
|
switch err {
|
|
case nil:
|
|
return FromStruct(m)
|
|
case distribution.ErrBlobUnknown:
|
|
// nop
|
|
default:
|
|
return nil, err
|
|
}
|
|
|
|
// Add config to the blob store
|
|
m.Config, err = mb.bs.Put(ctx, MediaTypeConfig, mb.configJSON)
|
|
// Override MediaType, since Put always replaces the specified media
|
|
// type with application/octet-stream in the descriptor it returns.
|
|
m.Config.MediaType = MediaTypeConfig
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return FromStruct(m)
|
|
}
|
|
|
|
// AppendReference adds a reference to the current ManifestBuilder.
|
|
func (mb *builder) AppendReference(d distribution.Describable) error {
|
|
mb.layers = append(mb.layers, d.Descriptor())
|
|
return nil
|
|
}
|
|
|
|
// References returns the current references added to this builder.
|
|
func (mb *builder) References() []distribution.Descriptor {
|
|
return mb.layers
|
|
}
|