mirror of
https://github.com/regclient/regclient.git
synced 2025-07-29 09:01:11 +03:00
Blob type linting and docs
Signed-off-by: Brandon Mitchell <git@bmitch.net>
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
// Package blob is the underlying type for pushing and pulling blobs
|
||||||
package blob
|
package blob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -14,7 +15,7 @@ type Blob interface {
|
|||||||
RawBody() ([]byte, error)
|
RawBody() ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobConfig struct {
|
type blobConfig struct {
|
||||||
desc ociv1.Descriptor
|
desc ociv1.Descriptor
|
||||||
header http.Header
|
header http.Header
|
||||||
image ociv1.Image
|
image ociv1.Image
|
||||||
@ -23,36 +24,46 @@ type BlobConfig struct {
|
|||||||
resp *http.Response
|
resp *http.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
type Opts func(*BlobConfig)
|
type Opts func(*blobConfig)
|
||||||
|
|
||||||
|
// WithDesc specifies the descriptor associated with the blob
|
||||||
func WithDesc(d ociv1.Descriptor) Opts {
|
func WithDesc(d ociv1.Descriptor) Opts {
|
||||||
return func(bc *BlobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.desc = d
|
bc.desc = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithHeader defines the headers received when pulling a blob
|
||||||
func WithHeader(header http.Header) Opts {
|
func WithHeader(header http.Header) Opts {
|
||||||
return func(bc *BlobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.header = header
|
bc.header = header
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithReader defines the reader for a new blob
|
||||||
func WithReader(rc io.Reader) Opts {
|
func WithReader(rc io.Reader) Opts {
|
||||||
return func(bc *BlobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.rdr = rc
|
bc.rdr = rc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithRef specifies the reference where the blob was pulled from
|
||||||
func WithRef(r ref.Ref) Opts {
|
func WithRef(r ref.Ref) Opts {
|
||||||
return func(bc *BlobConfig) {
|
return func(bc *blobConfig) {
|
||||||
bc.r = r
|
bc.r = r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithResp includes the http response, which is used to extract the headers and reader
|
||||||
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 {
|
||||||
bc.header = resp.Header
|
bc.header = resp.Header
|
||||||
|
@ -137,7 +137,7 @@ func TestCommon(t *testing.T) {
|
|||||||
t.Errorf("rawbody: %v", err)
|
t.Errorf("rawbody: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bytes.Compare(bb, tt.eBytes) != 0 {
|
if !bytes.Equal(bb, tt.eBytes) {
|
||||||
t.Errorf("rawbody, expected %s, received %s", string(tt.eBytes), string(bb))
|
t.Errorf("rawbody, expected %s, received %s", string(tt.eBytes), string(bb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ func TestReader(t *testing.T) {
|
|||||||
if pos != 0 {
|
if pos != 0 {
|
||||||
t.Errorf("seek pos, expected 0, received %d", pos)
|
t.Errorf("seek pos, expected 0, received %d", pos)
|
||||||
}
|
}
|
||||||
bb, err = io.ReadAll(b)
|
_, err = io.ReadAll(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("readall: %v", err)
|
t.Errorf("readall: %v", err)
|
||||||
return
|
return
|
||||||
@ -251,7 +251,7 @@ func TestReader(t *testing.T) {
|
|||||||
t.Errorf("config rawbody: %v", err)
|
t.Errorf("config rawbody: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bytes.Compare(exBlob, ocb) != 0 {
|
if !bytes.Equal(exBlob, ocb) {
|
||||||
t.Errorf("config bytes, expected %s, received %s", string(exBlob), string(ocb))
|
t.Errorf("config bytes, expected %s, received %s", string(exBlob), string(ocb))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -267,7 +267,7 @@ func TestReader(t *testing.T) {
|
|||||||
t.Errorf("rawbody: %v", err)
|
t.Errorf("rawbody: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bytes.Compare(exBlob, bb) != 0 {
|
if !bytes.Equal(exBlob, bb) {
|
||||||
t.Errorf("config bytes, expected %s, received %s", string(exBlob), string(bb))
|
t.Errorf("config bytes, expected %s, received %s", string(exBlob), string(bb))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -23,7 +23,7 @@ type ociConfig struct {
|
|||||||
|
|
||||||
// NewOCIConfig creates a new BlobOCIConfig from an OCI Image
|
// NewOCIConfig creates a new BlobOCIConfig from an OCI Image
|
||||||
func NewOCIConfig(opts ...Opts) OCIConfig {
|
func NewOCIConfig(opts ...Opts) OCIConfig {
|
||||||
bc := BlobConfig{}
|
bc := blobConfig{}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(&bc)
|
opt(&bc)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ type reader struct {
|
|||||||
|
|
||||||
// NewReader creates a new reader
|
// NewReader creates a new reader
|
||||||
func NewReader(opts ...Opts) Reader {
|
func NewReader(opts ...Opts) Reader {
|
||||||
bc := BlobConfig{}
|
bc := blobConfig{}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(&bc)
|
opt(&bc)
|
||||||
}
|
}
|
||||||
@ -102,13 +102,13 @@ func (b *reader) Read(p []byte) (int, error) {
|
|||||||
if b.desc.Size == 0 {
|
if b.desc.Size == 0 {
|
||||||
b.desc.Size = b.readBytes
|
b.desc.Size = b.readBytes
|
||||||
} else if b.readBytes != b.desc.Size {
|
} else if b.readBytes != b.desc.Size {
|
||||||
err = fmt.Errorf("Expected size mismatch [expected %d, received %d]: %w", b.desc.Size, b.readBytes, err)
|
err = fmt.Errorf("expected size mismatch [expected %d, received %d]: %w", b.desc.Size, b.readBytes, err)
|
||||||
}
|
}
|
||||||
// check/save digest
|
// check/save digest
|
||||||
if b.desc.Digest == "" {
|
if b.desc.Digest == "" {
|
||||||
b.desc.Digest = b.digester.Digest()
|
b.desc.Digest = b.digester.Digest()
|
||||||
} else if b.desc.Digest != b.digester.Digest() {
|
} else if b.desc.Digest != b.digester.Digest() {
|
||||||
err = fmt.Errorf("Expected digest mismatch [expected %s, calculated %s]: %w", b.desc.Digest.String(), b.digester.Digest().String(), err)
|
err = fmt.Errorf("expected digest mismatch [expected %s, calculated %s]: %w", b.desc.Digest.String(), b.digester.Digest().String(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return size, err
|
return size, err
|
||||||
@ -121,7 +121,7 @@ func (b *reader) Seek(offset int64, whence int) (int64, error) {
|
|||||||
}
|
}
|
||||||
// cannot do an arbitrary seek and still digest without a lot more complication
|
// cannot do an arbitrary seek and still digest without a lot more complication
|
||||||
if offset != 0 || whence != io.SeekStart {
|
if offset != 0 || whence != io.SeekStart {
|
||||||
return b.readBytes, fmt.Errorf("Unable to seek to arbitrary position")
|
return b.readBytes, fmt.Errorf("unable to seek to arbitrary position")
|
||||||
}
|
}
|
||||||
rdrSeek, ok := b.origRdr.(io.Seeker)
|
rdrSeek, ok := b.origRdr.(io.Seeker)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -144,19 +144,19 @@ func (b *reader) Seek(offset int64, whence int) (int64, error) {
|
|||||||
// ToOCIConfig converts a blobReader to a BlobOCIConfig
|
// ToOCIConfig converts a blobReader to a BlobOCIConfig
|
||||||
func (b *reader) ToOCIConfig() (OCIConfig, error) {
|
func (b *reader) ToOCIConfig() (OCIConfig, error) {
|
||||||
if !b.blobSet {
|
if !b.blobSet {
|
||||||
return nil, fmt.Errorf("Blob is not defined")
|
return nil, fmt.Errorf("blob is not defined")
|
||||||
}
|
}
|
||||||
if b.readBytes != 0 {
|
if b.readBytes != 0 {
|
||||||
return nil, fmt.Errorf("Unable to convert after read has been performed")
|
return nil, fmt.Errorf("unable to convert after read has been performed")
|
||||||
}
|
}
|
||||||
blobBody, err := ioutil.ReadAll(b)
|
blobBody, err := ioutil.ReadAll(b)
|
||||||
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
|
var ociImage ociv1.Image
|
||||||
err = json.Unmarshal(blobBody, &ociImage)
|
err = json.Unmarshal(blobBody, &ociImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing image config for %s: %w", b.r.CommonName(), err)
|
return nil, fmt.Errorf("error parsing image config for %s: %w", b.r.CommonName(), err)
|
||||||
}
|
}
|
||||||
// return the resulting blobOCIConfig, reuse blobCommon, setting rawBody read above, and the unmarshaled OCI image config
|
// return the resulting blobOCIConfig, reuse blobCommon, setting rawBody read above, and the unmarshaled OCI image config
|
||||||
return &ociConfig{common: b.common, rawBody: blobBody, Image: ociImage}, nil
|
return &ociConfig{common: b.common, rawBody: blobBody, Image: ociImage}, nil
|
||||||
|
Reference in New Issue
Block a user