mirror of
https://github.com/regclient/regclient.git
synced 2025-07-30 20:03:04 +03:00
Refactor blob like manifests, add SetConfig
Signed-off-by: Brandon Mitchell <git@bmitch.net>
This commit is contained in:
2
blob.go
2
blob.go
@ -59,7 +59,7 @@ func (rc *RegClient) BlobCopy(ctx context.Context, refSrc ref.Ref, refTgt ref.Re
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer blobIO.Close()
|
defer blobIO.Close()
|
||||||
if _, _, err := rc.BlobPut(ctx, refTgt, d, blobIO, blobIO.Length()); err != nil {
|
if _, _, err := rc.BlobPut(ctx, refTgt, d, blobIO, blobIO.GetDescriptor().Size); err != nil {
|
||||||
rc.log.WithFields(logrus.Fields{
|
rc.log.WithFields(logrus.Fields{
|
||||||
"err": err,
|
"err": err,
|
||||||
"src": refSrc.Reference,
|
"src": refSrc.Reference,
|
||||||
|
@ -208,7 +208,7 @@ func TestBlobGet(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer br.Close()
|
defer br.Close()
|
||||||
if br.Length() != int64(blobLen) {
|
if br.GetDescriptor().Size != int64(blobLen) {
|
||||||
t.Errorf("Failed comparing blob length")
|
t.Errorf("Failed comparing blob length")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -48,13 +48,13 @@ func TestBlob(t *testing.T) {
|
|||||||
t.Errorf("manifest get: %v", err)
|
t.Errorf("manifest get: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cd, err := m.GetConfigDigest()
|
cd, err := m.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("config digest: %v", err)
|
t.Errorf("config digest: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// blob head
|
// blob head
|
||||||
bh, err := o.BlobHead(ctx, r, cd)
|
bh, err := o.BlobHead(ctx, r, cd.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob head: %v", err)
|
t.Errorf("blob head: %v", err)
|
||||||
return
|
return
|
||||||
@ -64,7 +64,7 @@ func TestBlob(t *testing.T) {
|
|||||||
t.Errorf("blob head close: %v", err)
|
t.Errorf("blob head close: %v", err)
|
||||||
}
|
}
|
||||||
// blob get
|
// blob get
|
||||||
bg, err := o.BlobGet(ctx, r, cd)
|
bg, err := o.BlobGet(ctx, r, cd.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob get: %v", err)
|
t.Errorf("blob get: %v", err)
|
||||||
return
|
return
|
||||||
@ -74,14 +74,14 @@ func TestBlob(t *testing.T) {
|
|||||||
t.Errorf("blob readall: %v", err)
|
t.Errorf("blob readall: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bg.Digest() != cd {
|
if bg.GetDescriptor().Digest != cd.Digest {
|
||||||
t.Errorf("blob digest mismatch, expected %s, received %s", cd.String(), bg.Digest().String())
|
t.Errorf("blob digest mismatch, expected %s, received %s", cd.Digest.String(), bg.GetDescriptor().Digest.String())
|
||||||
}
|
}
|
||||||
err = bg.Close()
|
err = bg.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob get close: %v", err)
|
t.Errorf("blob get close: %v", err)
|
||||||
}
|
}
|
||||||
bFS, err := os.ReadFile(fmt.Sprintf("testdata/regctl/blobs/%s/%s", cd.Algorithm().String(), cd.Encoded()))
|
bFS, err := os.ReadFile(fmt.Sprintf("testdata/regctl/blobs/%s/%s", cd.Digest.Algorithm().String(), cd.Digest.Encoded()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob read file: %v", err)
|
t.Errorf("blob read file: %v", err)
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ func TestBlob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// toOCIConfig
|
// toOCIConfig
|
||||||
bg, err = o.BlobGet(ctx, r, cd)
|
bg, err = o.BlobGet(ctx, r, cd.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob get 2: %v", err)
|
t.Errorf("blob get 2: %v", err)
|
||||||
return
|
return
|
||||||
@ -99,15 +99,15 @@ func TestBlob(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("to oci config: %v", err)
|
t.Errorf("to oci config: %v", err)
|
||||||
}
|
}
|
||||||
if ociConf.Digest() != cd {
|
if ociConf.GetDescriptor().Digest != cd.Digest {
|
||||||
t.Errorf("config digest mismatch, expected %s, received %s", cd.String(), ociConf.Digest().String())
|
t.Errorf("config digest mismatch, expected %s, received %s", cd.Digest.String(), ociConf.GetDescriptor().Digest.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// blob put (to memfs)
|
// blob put (to memfs)
|
||||||
fm := rwfs.MemNew()
|
fm := rwfs.MemNew()
|
||||||
om := New(WithFS(fm))
|
om := New(WithFS(fm))
|
||||||
bRdr := bytes.NewReader(bBytes)
|
bRdr := bytes.NewReader(bBytes)
|
||||||
bpd, bpl, err := om.BlobPut(ctx, r, cd, bRdr, int64(len(bBytes)))
|
bpd, bpl, err := om.BlobPut(ctx, r, cd.Digest, bRdr, int64(len(bBytes)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob put: %v", err)
|
t.Errorf("blob put: %v", err)
|
||||||
return
|
return
|
||||||
@ -115,10 +115,10 @@ func TestBlob(t *testing.T) {
|
|||||||
if bpl != int64(len(bBytes)) {
|
if bpl != int64(len(bBytes)) {
|
||||||
t.Errorf("blob put length, expected %d, received %d", len(bBytes), bpl)
|
t.Errorf("blob put length, expected %d, received %d", len(bBytes), bpl)
|
||||||
}
|
}
|
||||||
if bpd != cd {
|
if bpd != cd.Digest {
|
||||||
t.Errorf("blob put digest, expected %s, received %s", cd, bpd)
|
t.Errorf("blob put digest, expected %s, received %s", cd.Digest, bpd)
|
||||||
}
|
}
|
||||||
fd, err := fm.Open(fmt.Sprintf("testdata/regctl/blobs/%s/%s", cd.Algorithm().String(), cd.Encoded()))
|
fd, err := fm.Open(fmt.Sprintf("testdata/regctl/blobs/%s/%s", cd.Digest.Algorithm().String(), cd.Digest.Encoded()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("blob put open file: %v", err)
|
t.Errorf("blob put open file: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ func TestBlobGet(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer br.Close()
|
defer br.Close()
|
||||||
if br.Length() != int64(blobLen) {
|
if br.GetDescriptor().Size != int64(blobLen) {
|
||||||
t.Errorf("Failed comparing blob length")
|
t.Errorf("Failed comparing blob length")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -16,12 +16,13 @@ type Blob interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type blobConfig struct {
|
type blobConfig struct {
|
||||||
desc ociv1.Descriptor
|
desc ociv1.Descriptor
|
||||||
header http.Header
|
header http.Header
|
||||||
image ociv1.Image
|
image *ociv1.Image
|
||||||
r ref.Ref
|
r ref.Ref
|
||||||
rdr io.Reader
|
rdr io.Reader
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
|
rawBody []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Opts func(*blobConfig)
|
type Opts func(*blobConfig)
|
||||||
@ -43,7 +44,14 @@ func WithHeader(header http.Header) Opts {
|
|||||||
// WithImage provides the OCI Image config needed for config blobs
|
// WithImage provides the OCI Image config needed for config blobs
|
||||||
func WithImage(image ociv1.Image) Opts {
|
func WithImage(image ociv1.Image) Opts {
|
||||||
return func(bc *blobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.image = image
|
bc.image = &image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRawBody defines the raw blob contents for OCIConfig
|
||||||
|
func WithRawBody(raw []byte) Opts {
|
||||||
|
return func(bc *blobConfig) {
|
||||||
|
bc.rawBody = raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +73,7 @@ func WithRef(r ref.Ref) Opts {
|
|||||||
func WithResp(resp *http.Response) Opts {
|
func WithResp(resp *http.Response) Opts {
|
||||||
return func(bc *blobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.resp = resp
|
bc.resp = resp
|
||||||
if bc.header == nil {
|
if bc.header == nil && resp != nil {
|
||||||
bc.header = resp.Header
|
bc.header = resp.Header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package blob
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -63,6 +64,11 @@ var (
|
|||||||
ContentLength: exLen,
|
ContentLength: exLen,
|
||||||
Body: io.NopCloser(bytes.NewReader(exBlob)),
|
Body: io.NopCloser(bytes.NewReader(exBlob)),
|
||||||
}
|
}
|
||||||
|
exDesc = ociv1.Descriptor{
|
||||||
|
MediaType: exMT,
|
||||||
|
Digest: exDigest,
|
||||||
|
Size: exLen,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommon(t *testing.T) {
|
func TestCommon(t *testing.T) {
|
||||||
@ -141,14 +147,14 @@ func TestCommon(t *testing.T) {
|
|||||||
t.Errorf("rawbody, expected %s, received %s", string(tt.eBytes), string(bb))
|
t.Errorf("rawbody, expected %s, received %s", string(tt.eBytes), string(bb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tt.eDigest != "" && b.Digest() != tt.eDigest {
|
if tt.eDigest != "" && b.GetDescriptor().Digest != tt.eDigest {
|
||||||
t.Errorf("digest, expected %s, received %s", tt.eDigest, b.Digest())
|
t.Errorf("digest, expected %s, received %s", tt.eDigest, b.GetDescriptor().Digest)
|
||||||
}
|
}
|
||||||
if tt.eLen > 0 && b.Length() != tt.eLen {
|
if tt.eLen > 0 && b.GetDescriptor().Size != tt.eLen {
|
||||||
t.Errorf("length, expected %d, received %d", tt.eLen, b.Length())
|
t.Errorf("length, expected %d, received %d", tt.eLen, b.GetDescriptor().Size)
|
||||||
}
|
}
|
||||||
if tt.eMT != "" && b.MediaType() != tt.eMT {
|
if tt.eMT != "" && b.GetDescriptor().MediaType != tt.eMT {
|
||||||
t.Errorf("media type, expected %s, received %s", tt.eMT, b.MediaType())
|
t.Errorf("media type, expected %s, received %s", tt.eMT, b.GetDescriptor().MediaType)
|
||||||
}
|
}
|
||||||
if tt.eHeaders != nil {
|
if tt.eHeaders != nil {
|
||||||
bHeader := b.RawHeaders()
|
bHeader := b.RawHeaders()
|
||||||
@ -160,6 +166,10 @@ func TestCommon(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err := b.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed closing blob: %v", err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,11 +228,11 @@ func TestReader(t *testing.T) {
|
|||||||
t.Errorf("readall: %v", err)
|
t.Errorf("readall: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b.Digest() != exDigest {
|
if b.GetDescriptor().Digest != exDigest {
|
||||||
t.Errorf("digest mismatch, expected %s, received %s", exDigest, b.Digest())
|
t.Errorf("digest mismatch, expected %s, received %s", exDigest, b.GetDescriptor().Digest)
|
||||||
}
|
}
|
||||||
if b.Length() != exLen {
|
if b.GetDescriptor().Size != exLen {
|
||||||
t.Errorf("length mismatch, expected %d, received %d", exLen, b.Length())
|
t.Errorf("length mismatch, expected %d, received %d", exLen, b.GetDescriptor().Size)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -243,8 +253,8 @@ func TestReader(t *testing.T) {
|
|||||||
t.Errorf("ToOCIConfig: %v", err)
|
t.Errorf("ToOCIConfig: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if exDigest != oc.Digest() {
|
if exDigest != oc.GetDescriptor().Digest {
|
||||||
t.Errorf("digest, expected %s, received %s", exDigest, oc.Digest())
|
t.Errorf("digest, expected %s, received %s", exDigest, oc.GetDescriptor().Digest)
|
||||||
}
|
}
|
||||||
ocb, err := oc.RawBody()
|
ocb, err := oc.RawBody()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -273,6 +283,102 @@ func TestReader(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOCI(t *testing.T) {
|
||||||
|
ociConfig := ociv1.Image{}
|
||||||
|
err := json.Unmarshal(exBlob, &ociConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to unmarshal exBlob: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
opts []Opts
|
||||||
|
wantRaw []byte
|
||||||
|
wantDesc ociv1.Descriptor
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "RawBody",
|
||||||
|
opts: []Opts{
|
||||||
|
WithRawBody(exBlob),
|
||||||
|
WithDesc(exDesc),
|
||||||
|
},
|
||||||
|
wantDesc: exDesc,
|
||||||
|
wantRaw: exBlob,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Config with Default Desc",
|
||||||
|
opts: []Opts{
|
||||||
|
WithImage(ociConfig),
|
||||||
|
},
|
||||||
|
wantDesc: ociv1.Descriptor{MediaType: types.MediaTypeOCI1ImageConfig},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Config with Docker Desc",
|
||||||
|
opts: []Opts{
|
||||||
|
WithImage(ociConfig),
|
||||||
|
WithDesc(exDesc),
|
||||||
|
},
|
||||||
|
wantDesc: ociv1.Descriptor{MediaType: exMT},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
oc := NewOCIConfig(tt.opts...)
|
||||||
|
|
||||||
|
if tt.wantDesc.Digest != "" && tt.wantDesc.Digest != oc.GetDescriptor().Digest {
|
||||||
|
t.Errorf("digest, expected %s, received %s", tt.wantDesc.Digest, oc.GetDescriptor().Digest)
|
||||||
|
}
|
||||||
|
if tt.wantDesc.MediaType != "" && tt.wantDesc.MediaType != oc.GetDescriptor().MediaType {
|
||||||
|
t.Errorf("media type, expected %s, received %s", tt.wantDesc.MediaType, oc.GetDescriptor().MediaType)
|
||||||
|
}
|
||||||
|
if tt.wantDesc.Size > 0 && tt.wantDesc.Size != oc.GetDescriptor().Size {
|
||||||
|
t.Errorf("size, expected %d, received %d", tt.wantDesc.Size, oc.GetDescriptor().Size)
|
||||||
|
}
|
||||||
|
if len(tt.wantRaw) > 0 {
|
||||||
|
raw, err := oc.RawBody()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("config rawbody: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !bytes.Equal(tt.wantRaw, raw) {
|
||||||
|
t.Errorf("config bytes, expected %s, received %s", string(tt.wantRaw), string(raw))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
t.Run("ModConfig", func(t *testing.T) {
|
||||||
|
// create blob
|
||||||
|
oc := NewOCIConfig(
|
||||||
|
WithRawBody(exBlob),
|
||||||
|
WithDesc(ociv1.Descriptor{
|
||||||
|
MediaType: exMT,
|
||||||
|
Digest: exDigest,
|
||||||
|
Size: exLen,
|
||||||
|
}),
|
||||||
|
WithRef(exRef),
|
||||||
|
)
|
||||||
|
ociC := oc.GetConfig()
|
||||||
|
ociC.History = append(ociC.History, ociv1.History{Comment: "test", EmptyLayer: true})
|
||||||
|
oc.SetConfig(ociC)
|
||||||
|
// ensure digest and raw body change
|
||||||
|
if exDigest == oc.GetDescriptor().Digest {
|
||||||
|
t.Errorf("digest did not change, received %s", oc.GetDescriptor().Digest)
|
||||||
|
}
|
||||||
|
if exMT != oc.GetDescriptor().MediaType {
|
||||||
|
t.Errorf("media type changed, expected %s, received %s", exMT, oc.GetDescriptor().MediaType)
|
||||||
|
}
|
||||||
|
raw, err := oc.RawBody()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("config rawbody: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bytes.Equal(exBlob, raw) {
|
||||||
|
t.Errorf("config bytes unchanged, received %s", string(raw))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func cmpSliceString(a, b []string) bool {
|
func cmpSliceString(a, b []string) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
|
@ -10,11 +10,13 @@ import (
|
|||||||
|
|
||||||
// Common interface is provided by all Blob implementations
|
// Common interface is provided by all Blob implementations
|
||||||
type Common interface {
|
type Common interface {
|
||||||
Digest() digest.Digest
|
GetDescriptor() ociv1.Descriptor
|
||||||
Length() int64
|
|
||||||
MediaType() string
|
|
||||||
Response() *http.Response
|
Response() *http.Response
|
||||||
RawHeaders() http.Header
|
RawHeaders() http.Header
|
||||||
|
|
||||||
|
Digest() digest.Digest // TODO: deprecate
|
||||||
|
Length() int64 // TODO: deprecate
|
||||||
|
MediaType() string // TODO: deprecate
|
||||||
}
|
}
|
||||||
|
|
||||||
type common struct {
|
type common struct {
|
||||||
@ -25,6 +27,11 @@ type common struct {
|
|||||||
resp *http.Response
|
resp *http.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDescriptor returns the descriptor associated with the blob
|
||||||
|
func (b *common) GetDescriptor() ociv1.Descriptor {
|
||||||
|
return b.desc
|
||||||
|
}
|
||||||
|
|
||||||
// Digest returns the provided or calculated digest of the blob
|
// Digest returns the provided or calculated digest of the blob
|
||||||
func (b *common) Digest() digest.Digest {
|
func (b *common) Digest() digest.Digest {
|
||||||
return b.desc.Digest
|
return b.desc.Digest
|
||||||
|
@ -4,13 +4,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/regclient/regclient/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OCIConfig wraps an OCI Config struct extracted from a Blob
|
// OCIConfig wraps an OCI Config struct extracted from a Blob
|
||||||
type OCIConfig interface {
|
type OCIConfig interface {
|
||||||
Blob
|
Blob
|
||||||
GetConfig() ociv1.Image
|
GetConfig() ociv1.Image
|
||||||
|
SetConfig(ociv1.Image)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ociConfig includes an OCI Config struct extracted from a Blob
|
// ociConfig includes an OCI Config struct extracted from a Blob
|
||||||
@ -27,21 +30,47 @@ func NewOCIConfig(opts ...Opts) OCIConfig {
|
|||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(&bc)
|
opt(&bc)
|
||||||
}
|
}
|
||||||
|
if bc.image != nil && len(bc.rawBody) == 0 {
|
||||||
|
var err error
|
||||||
|
bc.rawBody, err = json.Marshal(bc.image)
|
||||||
|
if err != nil {
|
||||||
|
bc.rawBody = []byte{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(bc.rawBody) > 0 {
|
||||||
|
if bc.image == nil {
|
||||||
|
bc.image = &ociv1.Image{}
|
||||||
|
err := json.Unmarshal(bc.rawBody, bc.image)
|
||||||
|
if err != nil {
|
||||||
|
bc.image = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// force descriptor to match raw body, even if we generated the raw body
|
||||||
|
bc.desc.Digest = digest.FromBytes(bc.rawBody)
|
||||||
|
bc.desc.Size = int64(len(bc.rawBody))
|
||||||
|
if bc.desc.MediaType == "" {
|
||||||
|
bc.desc.MediaType = types.MediaTypeOCI1ImageConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c := common{
|
c := common{
|
||||||
blobSet: true,
|
|
||||||
desc: bc.desc,
|
desc: bc.desc,
|
||||||
r: bc.r,
|
r: bc.r,
|
||||||
rawHeader: bc.header,
|
rawHeader: bc.header,
|
||||||
resp: bc.resp,
|
resp: bc.resp,
|
||||||
}
|
}
|
||||||
b := ociConfig{
|
b := ociConfig{
|
||||||
common: c,
|
common: c,
|
||||||
Image: bc.image,
|
rawBody: bc.rawBody,
|
||||||
|
}
|
||||||
|
if bc.image != nil {
|
||||||
|
b.Image = *bc.image
|
||||||
|
b.blobSet = true
|
||||||
}
|
}
|
||||||
return &b
|
return &b
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig returns the original body from the request
|
// GetConfig returns OCI config
|
||||||
func (b *ociConfig) GetConfig() ociv1.Image {
|
func (b *ociConfig) GetConfig() ociv1.Image {
|
||||||
return b.Image
|
return b.Image
|
||||||
}
|
}
|
||||||
@ -57,3 +86,15 @@ func (b *ociConfig) RawBody() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return b.rawBody, err
|
return b.rawBody, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetConfig updates the config, including raw body and descriptor
|
||||||
|
func (b *ociConfig) SetConfig(c ociv1.Image) {
|
||||||
|
b.Image = c
|
||||||
|
b.rawBody, _ = json.Marshal(b.Image)
|
||||||
|
if b.desc.MediaType == "" {
|
||||||
|
b.desc.MediaType = types.MediaTypeOCI1ImageConfig
|
||||||
|
}
|
||||||
|
b.desc.Digest = digest.FromBytes(b.rawBody)
|
||||||
|
b.desc.Size = int64(len(b.rawBody))
|
||||||
|
b.blobSet = true
|
||||||
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package blob
|
package blob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader is an unprocessed Blob with an available ReadCloser for reading the Blob
|
// Reader is an unprocessed Blob with an available ReadCloser for reading the Blob
|
||||||
@ -153,11 +151,11 @@ func (b *reader) ToOCIConfig() (OCIConfig, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading image config for %s: %w", b.r.CommonName(), err)
|
return nil, fmt.Errorf("error reading image config for %s: %w", b.r.CommonName(), err)
|
||||||
}
|
}
|
||||||
var ociImage ociv1.Image
|
return NewOCIConfig(
|
||||||
err = json.Unmarshal(blobBody, &ociImage)
|
WithDesc(b.desc),
|
||||||
if err != nil {
|
WithHeader(b.rawHeader),
|
||||||
return nil, fmt.Errorf("error parsing image config for %s: %w", b.r.CommonName(), err)
|
WithRawBody(blobBody),
|
||||||
}
|
WithRef(b.r),
|
||||||
// return the resulting blobOCIConfig, reuse blobCommon, setting rawBody read above, and the unmarshaled OCI image config
|
WithResp(b.resp),
|
||||||
return &ociConfig{common: b.common, rawBody: blobBody, Image: ociImage}, nil
|
), nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user