Skip to content

Commit

Permalink
Rework accmeth model to live without backing repository (#566)
Browse files Browse the repository at this point in the history
* method to blobaccess

* fix localblob refs to cv

* work

* disconnect for local acc meth implementations

* rework final update on close

* cleanup blob interface + prepare commit

* fix close error in transfer
  • Loading branch information
mandelsoft authored Nov 8, 2023
1 parent dcaa66f commit 2f62868
Show file tree
Hide file tree
Showing 62 changed files with 1,008 additions and 502 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ COMPONENTS ?= ocmcli helminstaller demoplugin ecrplugin helmdemo subchartsdemo
build: ${SOURCES}
mkdir -p bin
go build ./pkg/...
go build ./examples/...
CGO_ENABLED=0 go build -ldflags $(BUILD_FLAGS) -o bin/ocm ./cmds/ocm
CGO_ENABLED=0 go build -ldflags $(BUILD_FLAGS) -o bin/helminstaller ./cmds/helminstaller
CGO_ENABLED=0 go build -ldflags $(BUILD_FLAGS) -o bin/demo ./cmds/demoplugin
Expand Down
6 changes: 3 additions & 3 deletions cmds/demoplugin/uploaders/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (

"github.com/open-component-model/ocm/cmds/demoplugin/accessmethods"
"github.com/open-component-model/ocm/pkg/common"
"github.com/open-component-model/ocm/pkg/common/accessio"
"github.com/open-component-model/ocm/pkg/contexts/ocm/plugin/ppi"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/iotools"
"github.com/open-component-model/ocm/pkg/runtime"
)

type writer = accessio.DigestWriter
type writer = iotools.DigestWriter

type Writer struct {
*writer
Expand All @@ -32,7 +32,7 @@ type Writer struct {

func NewWriter(file *os.File, path string, media string, rename bool, name, version string) *Writer {
return &Writer{
writer: accessio.NewDefaultDigestWriter(file),
writer: iotools.NewDefaultDigestWriter(file),
file: file,
path: path,
rename: rename,
Expand Down
18 changes: 15 additions & 3 deletions pkg/blobaccess/bpi/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ func BaseAccessForDataAccessAndMeta(mime string, acc DataAccess, dig digest.Dige

////////////////////////////////////////////////////////////////////////////////

// StaticBlobAccess is a BlobAccess which does not
// require finalization, therefore it can be used
// as BlobAccessProvider, also.
type StaticBlobAccess interface {
BlobAccess
BlobAccessProvider
}

type staticBlobAccess struct {
blobAccess
}
Expand All @@ -187,21 +195,25 @@ func (s *staticBlobAccess) Dup() (BlobAccess, error) {
return s, nil
}

func (s *staticBlobAccess) BlobAccess() (BlobAccess, error) {
return s, nil
}

func (s *staticBlobAccess) Close() error {
return nil
}

// ForStaticDataAccess is used for a data access using no closer.
// They don't require a finalization and can be used
// as long as they exist. Therefore, no ref counting
// is required.
func ForStaticDataAccess(mime string, acc DataAccess) BlobAccess {
// is required and they can be used as BlobAccessProvider, also.
func ForStaticDataAccess(mime string, acc DataAccess) StaticBlobAccess {
return &staticBlobAccess{
blobAccess: blobAccess{mimeType: mime, _dataAccess: acc, digest: BLOB_UNKNOWN_DIGEST, size: BLOB_UNKNOWN_SIZE},
}
}

func ForStaticDataAccessAndMeta(mime string, acc DataAccess, dig digest.Digest, size int64) BlobAccess {
func ForStaticDataAccessAndMeta(mime string, acc DataAccess, dig digest.Digest, size int64) StaticBlobAccess {
return &staticBlobAccess{
blobAccess: blobAccess{mimeType: mime, _dataAccess: acc, digest: dig, size: size},
}
Expand Down
35 changes: 35 additions & 0 deletions pkg/blobaccess/cached.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package blobaccess

import (
"io"

"github.com/mandelsoft/vfs/pkg/vfs"

"github.com/open-component-model/ocm/pkg/utils"
)

func ForCachedBlobAccess(blob BlobAccess, fss ...vfs.FileSystem) (BlobAccess, error) {
fs := utils.FileSystem(fss...)

r, err := blob.Reader()
if err != nil {
return nil, err
}
defer r.Close()

file, err := vfs.TempFile(fs, "", "cachedBlob*")
if err != nil {
return nil, err
}
_, err = io.Copy(file, r)
if err != nil {
return nil, err
}
file.Close()

return ForTemporaryFilePath(blob.MimeType(), file.Name(), fs), nil
}
23 changes: 23 additions & 0 deletions pkg/blobaccess/digest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package blobaccess

import (
"github.com/opencontainers/go-digest"
)

func Digest(access DataAccess) (digest.Digest, error) {
reader, err := access.Reader()
if err != nil {
return "", err
}
defer reader.Close()

dig, err := digest.FromReader(reader)
if err != nil {
return "", err
}
return dig, nil
}
4 changes: 4 additions & 0 deletions pkg/blobaccess/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ type annotatedBlobAccessView[T DataAccess] struct {
annotation T
}

func (a *annotatedBlobAccessView[T]) Close() error {
return a._blobAccess.Close()
}

func (a *annotatedBlobAccessView[T]) Dup() (BlobAccess, error) {
b, err := a._blobAccess.Dup()
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions pkg/common/accessio/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/open-component-model/ocm/pkg/blobaccess"
"github.com/open-component-model/ocm/pkg/common"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/iotools"
"github.com/open-component-model/ocm/pkg/refmgmt"
)

Expand Down Expand Up @@ -209,7 +210,7 @@ func (c *blobCache) AddBlob(blob blobaccess.BlobAccess) (int64, digest.Digest, e
}
defer c.Unref()

var digester *DigestReader
var digester *iotools.DigestReader

if blob.DigestKnown() {
c.lock.RLock()
Expand All @@ -231,7 +232,7 @@ func (c *blobCache) AddBlob(blob blobaccess.BlobAccess) (int64, digest.Digest, e

reader := io.Reader(br)
if !blob.DigestKnown() {
digester = NewDefaultDigestReader(reader)
digester = iotools.NewDefaultDigestReader(reader)
reader = digester
}

Expand Down
113 changes: 21 additions & 92 deletions pkg/common/accessio/digestreader.go
Original file line number Diff line number Diff line change
@@ -1,119 +1,48 @@
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package accessio

import (
"crypto"
"hash"
"io"

"github.com/opencontainers/go-digest"

"github.com/open-component-model/ocm/pkg/blobaccess"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/iotools"
)

// wow. digest does support a map with supported digesters. Unfortunately this one does not
// contain all the crypto hashes AND this map is private NAD there is no function to add entries,
// so that it cannot be extended from outside the package. I love GO.
// Therefore, we have to fake it a little to support digests with other crypto hashes.
// Deprecated: use iotools.DigestReader.
type DigestReader = iotools.DigestReader

type DigestReader struct {
reader io.Reader
alg digest.Algorithm
hash hash.Hash
count int64
// Deprecated: use iotools.NewDefaultDigestReader.
func NewDefaultDigestReader(r io.Reader) *iotools.DigestReader {
return iotools.NewDigestReaderWith(digest.Canonical, r)
}

func (r *DigestReader) Size() int64 {
return r.count
// Deprecated: use iotools.NewDigestReaderWith.
func NewDigestReaderWith(algorithm digest.Algorithm, r io.Reader) *iotools.DigestReader {
return iotools.NewDigestReaderWith(algorithm, r)
}

func (r *DigestReader) Digest() digest.Digest {
return digest.NewDigest(r.alg, r.hash)
// Deprecated: use iotools.NewDigestReaderWithHash.
func NewDigestReaderWithHash(hash crypto.Hash, r io.Reader) *iotools.DigestReader {
return iotools.NewDigestReaderWithHash(hash, r)
}

func (r *DigestReader) Read(buf []byte) (int, error) {
c, err := r.reader.Read(buf)
if c > 0 {
r.count += int64(c)
r.hash.Write(buf[:c])
}
return c, err
}

func NewDefaultDigestReader(r io.Reader) *DigestReader {
return NewDigestReaderWith(digest.Canonical, r)
}

func NewDigestReaderWith(algorithm digest.Algorithm, r io.Reader) *DigestReader {
digester := algorithm.Digester()
return &DigestReader{
reader: r,
hash: digester.Hash(),
alg: algorithm,
count: 0,
}
// Deprecated: use iotools.VerifyingReader.
func VerifyingReader(r io.ReadCloser, digest digest.Digest) io.ReadCloser {
return iotools.VerifyingReader(r, digest)
}

func NewDigestReaderWithHash(hash crypto.Hash, r io.Reader) *DigestReader {
return &DigestReader{
reader: r,
hash: hash.New(),
alg: digest.Algorithm(hash.String()), // fake a non-supported digest algorithm
count: 0,
}
// Deprecated: use iotools.VerifyingReaderWithHash.
func VerifyingReaderWithHash(r io.ReadCloser, hash crypto.Hash, digest string) io.ReadCloser {
return iotools.VerifyingReaderWithHash(r, hash, digest)
}

// Deprecated: use blobaccess.Digest.
func Digest(access blobaccess.DataAccess) (digest.Digest, error) {
reader, err := access.Reader()
if err != nil {
return "", err
}
defer reader.Close()

dig, err := digest.FromReader(reader)
if err != nil {
return "", err
}
return dig, nil
}

type verifiedReader struct {
closer io.Closer
*DigestReader
hash string
digest string
}

func (v *verifiedReader) Close() error {
err := v.closer.Close()
if err != nil {
return err
}
dig := v.DigestReader.Digest()
if dig.Hex() != v.digest {
return errors.Newf("%s digest mismatch: expected %s, found %s", v.hash, v.digest, dig.Hex())
}
return nil
}

func VerifyingReader(r io.ReadCloser, digest digest.Digest) io.ReadCloser {
return &verifiedReader{
closer: r,
DigestReader: NewDigestReaderWith(digest.Algorithm(), r),
hash: digest.Algorithm().String(),
digest: digest.Hex(),
}
}

func VerifyingReaderWithHash(r io.ReadCloser, hash crypto.Hash, digest string) io.ReadCloser {
return &verifiedReader{
closer: r,
DigestReader: NewDigestReaderWithHash(hash, r),
hash: hash.String(),
digest: digest,
}
return blobaccess.Digest(access)
}
48 changes: 11 additions & 37 deletions pkg/common/accessio/digestwriter.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -8,45 +8,19 @@ import (
"io"

"github.com/opencontainers/go-digest"
)

type writer io.WriteCloser

type DigestWriter struct {
writer
digester digest.Digester
count int64
}

func (r *DigestWriter) Size() int64 {
return r.count
}

func (r *DigestWriter) Digest() digest.Digest {
return r.digester.Digest()
}
"github.com/open-component-model/ocm/pkg/iotools"
)

func (r *DigestWriter) Write(buf []byte) (int, error) {
c, err := r.writer.Write(buf)
if c > 0 {
r.count += int64(c)
r.digester.Hash().Write(buf[:c])
}
return c, err
}
// Deprecated: use iotools.DigestWriter.
type DigestWriter = iotools.DigestWriter

func NewDefaultDigestWriter(w io.WriteCloser) *DigestWriter {
return &DigestWriter{
writer: w,
digester: digest.Canonical.Digester(),
count: 0,
}
// Deprecated: use iotools.NewDefaultDigestWriter.
func NewDefaultDigestWriter(w io.WriteCloser) *iotools.DigestWriter {
return iotools.NewDefaultDigestWriter(w)
}

func NewDigestWriterWith(algorithm digest.Algorithm, w io.WriteCloser) *DigestWriter {
return &DigestWriter{
writer: w,
digester: algorithm.Digester(),
count: 0,
}
// Deprecated: use iotools.NewDigestWriterWith.
func NewDigestWriterWith(algorithm digest.Algorithm, w io.WriteCloser) *iotools.DigestWriter {
return iotools.NewDigestWriterWith(algorithm, w)
}
3 changes: 2 additions & 1 deletion pkg/common/accessio/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/open-component-model/ocm/pkg/blobaccess"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/iotools"
)

type Writer interface {
Expand All @@ -34,7 +35,7 @@ func NewReaderWriter(r io.ReadCloser) DataWriter {

func (d *readerWriter) WriteTo(w Writer) (size int64, dig digest.Digest, err error) {
defer errors.PropagateError(&err, d.reader.Close)
dr := NewDefaultDigestReader(d.reader)
dr := iotools.NewDefaultDigestReader(d.reader)
_, err = io.Copy(w, dr)
if err != nil {
return BLOB_UNKNOWN_SIZE, BLOB_UNKNOWN_DIGEST, err
Expand Down
Loading

0 comments on commit 2f62868

Please sign in to comment.