Merge pull request #3896 from pluralsh/clean-blobstore-rebase

Remove blobstore from manifest builder
This commit is contained in:
Milos Gajdos 2023-05-19 15:05:16 +01:00 committed by GitHub
commit 983358f8e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 68 deletions

View file

@ -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,10 +22,9 @@ 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)
} }

View file

@ -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 {

View file

@ -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)