Merge pull request #3896 from pluralsh/clean-blobstore-rebase
Remove blobstore from manifest builder
This commit is contained in:
commit
983358f8e2
3 changed files with 24 additions and 68 deletions
|
@ -4,16 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/opencontainers/go-digest"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// builder is a type for constructing manifests.
|
// builder is a type for constructing manifests.
|
||||||
type builder struct {
|
type builder struct {
|
||||||
// bs is a BlobService used to publish the configuration blob.
|
// configDescriptor is used to describe configuration
|
||||||
bs distribution.BlobService
|
configDescriptor distribution.Descriptor
|
||||||
|
|
||||||
// configMediaType is media type used to describe configuration
|
|
||||||
configMediaType string
|
|
||||||
|
|
||||||
// configJSON references
|
// configJSON references
|
||||||
configJSON []byte
|
configJSON []byte
|
||||||
|
@ -26,11 +22,10 @@ type builder struct {
|
||||||
// NewManifestBuilder is used to build new manifests for the current schema
|
// NewManifestBuilder is used to build new manifests for the current schema
|
||||||
// version. It takes a BlobService so it can publish the configuration blob
|
// version. It takes a BlobService so it can publish the configuration blob
|
||||||
// as part of the Build process.
|
// as part of the Build process.
|
||||||
func NewManifestBuilder(bs distribution.BlobService, configMediaType string, configJSON []byte) distribution.ManifestBuilder {
|
func NewManifestBuilder(configDescriptor distribution.Descriptor, configJSON []byte) distribution.ManifestBuilder {
|
||||||
mb := &builder{
|
mb := &builder{
|
||||||
bs: bs,
|
configDescriptor: configDescriptor,
|
||||||
configMediaType: configMediaType,
|
configJSON: make([]byte, len(configJSON)),
|
||||||
configJSON: make([]byte, len(configJSON)),
|
|
||||||
}
|
}
|
||||||
copy(mb.configJSON, configJSON)
|
copy(mb.configJSON, configJSON)
|
||||||
|
|
||||||
|
@ -45,30 +40,7 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
}
|
}
|
||||||
copy(m.Layers, mb.dependencies)
|
copy(m.Layers, mb.dependencies)
|
||||||
|
|
||||||
configDigest := digest.FromBytes(mb.configJSON)
|
m.Config = mb.configDescriptor
|
||||||
|
|
||||||
var err error
|
|
||||||
m.Config, err = mb.bs.Stat(ctx, configDigest)
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
// Override MediaType, since Put always replaces the specified media
|
|
||||||
// type with application/octet-stream in the descriptor it returns.
|
|
||||||
m.Config.MediaType = mb.configMediaType
|
|
||||||
return FromStruct(m)
|
|
||||||
case distribution.ErrBlobUnknown:
|
|
||||||
// nop
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add config to the blob store
|
|
||||||
m.Config, err = mb.bs.Put(ctx, mb.configMediaType, mb.configJSON)
|
|
||||||
// Override MediaType, since Put always replaces the specified media
|
|
||||||
// type with application/octet-stream in the descriptor it returns.
|
|
||||||
m.Config.MediaType = mb.configMediaType
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return FromStruct(m)
|
return FromStruct(m)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,28 +9,6 @@ import (
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockBlobService struct {
|
|
||||||
descriptors map[digest.Digest]distribution.Descriptor
|
|
||||||
distribution.BlobService
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bs *mockBlobService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
|
||||||
if descriptor, ok := bs.descriptors[dgst]; ok {
|
|
||||||
return descriptor, nil
|
|
||||||
}
|
|
||||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bs *mockBlobService) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
|
||||||
d := distribution.Descriptor{
|
|
||||||
MediaType: "application/octet-stream",
|
|
||||||
Digest: digest.FromBytes(p),
|
|
||||||
Size: int64(len(p)),
|
|
||||||
}
|
|
||||||
bs.descriptors[d.Digest] = d
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuilder(t *testing.T) {
|
func TestBuilder(t *testing.T) {
|
||||||
imgJSON := []byte(`{
|
imgJSON := []byte(`{
|
||||||
"architecture": "amd64",
|
"architecture": "amd64",
|
||||||
|
@ -150,8 +128,13 @@ func TestBuilder(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
|
d := distribution.Descriptor{
|
||||||
builder := NewManifestBuilder(bs, MediaTypeImageConfig, imgJSON)
|
Digest: digest.FromBytes(imgJSON),
|
||||||
|
Size: int64(len(imgJSON)),
|
||||||
|
MediaType: MediaTypeImageConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := NewManifestBuilder(d, imgJSON)
|
||||||
|
|
||||||
for _, d := range descriptors {
|
for _, d := range descriptors {
|
||||||
if err := builder.AppendReference(d); err != nil {
|
if err := builder.AppendReference(d); err != nil {
|
||||||
|
@ -164,12 +147,6 @@ func TestBuilder(t *testing.T) {
|
||||||
t.Fatalf("Build returned error: %v", err)
|
t.Fatalf("Build returned error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the config was put in the blob store
|
|
||||||
_, err = bs.Stat(context.Background(), configDigest)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("config was not put in the blob store")
|
|
||||||
}
|
|
||||||
|
|
||||||
manifest := built.(*DeserializedManifest).Manifest
|
manifest := built.(*DeserializedManifest).Manifest
|
||||||
|
|
||||||
if manifest.Versioned.SchemaVersion != 2 {
|
if manifest.Versioned.SchemaVersion != 2 {
|
||||||
|
|
|
@ -44,7 +44,7 @@ func MakeManifestList(blobstatter distribution.BlobStatter, manifestDigests []di
|
||||||
//
|
//
|
||||||
// Deprecated: Docker Image Manifest v2, Schema 1 is deprecated since 2015.
|
// Deprecated: Docker Image Manifest v2, Schema 1 is deprecated since 2015.
|
||||||
// Use Docker Image Manifest v2, Schema 2, or the OCI Image Specification.
|
// Use Docker Image Manifest v2, Schema 2, or the OCI Image Specification.
|
||||||
func MakeSchema1Manifest(digests []digest.Digest) (distribution.Manifest, error) {
|
func MakeSchema1Manifest(digests []digest.Digest) (*schema1.SignedManifest, error) {
|
||||||
mfst := schema1.Manifest{
|
mfst := schema1.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: manifest.Versioned{
|
||||||
SchemaVersion: 1,
|
SchemaVersion: 1,
|
||||||
|
@ -76,9 +76,16 @@ func MakeSchema1Manifest(digests []digest.Digest) (distribution.Manifest, error)
|
||||||
func MakeSchema2Manifest(repository distribution.Repository, digests []digest.Digest) (distribution.Manifest, error) {
|
func MakeSchema2Manifest(repository distribution.Repository, digests []digest.Digest) (distribution.Manifest, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
blobStore := repository.Blobs(ctx)
|
blobStore := repository.Blobs(ctx)
|
||||||
builder := schema2.NewManifestBuilder(blobStore, schema2.MediaTypeImageConfig, []byte{})
|
|
||||||
for _, d := range digests {
|
var configJSON []byte
|
||||||
builder.AppendReference(distribution.Descriptor{Digest: d})
|
|
||||||
|
d, err := blobStore.Put(ctx, schema2.MediaTypeImageConfig, configJSON)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected error storing content in blobstore: %v", err)
|
||||||
|
}
|
||||||
|
builder := schema2.NewManifestBuilder(d, configJSON)
|
||||||
|
for _, digest := range digests {
|
||||||
|
builder.AppendReference(distribution.Descriptor{Digest: digest})
|
||||||
}
|
}
|
||||||
|
|
||||||
mfst, err := builder.Build(ctx)
|
mfst, err := builder.Build(ctx)
|
||||||
|
|
Loading…
Reference in a new issue