repocpi

package
v0.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2024 License: Apache-2.0 Imports: 32 Imported by: 0

README

Context Programming Interface for Repositories

Package repocpi contains the implementation support for repository backends. It offers three methods to create component version, component and repository objects based on three simple implementation interfaces.

The basic provisioning model is layered:

Implamentation Layers

  • on layer 1 there is the user facing API defined in package [github.com/open-component-model/ocm/pkg/contexts/ocm].

  • on layer 2 (this package) there is a backend agnostic implementation of standard functionality based on layer 3. This is divided into two parts

    a) the view objects provided by the Dup() calls of the layer 1 API. All dups are internally based on a single base object. These objects are called bridge. They act as base object for the views and as abstraction for the implementation objects providing generic implementations potentially based on the implementation functionality. (see bridge design pattern https://refactoring.guru/design-patterns/bridge)

    b) the bridge object as base for all dup views is used to implement some common functionality like the view management. The bridge object is closed, when the last view disappears. This bridge object then calls the final storage backend implementation interface.

  • the storage backend implementations based on the implementation interfaces provided by layer 2.

The implementation interfaces and the functions to create API objects are:

  • interface [ComponentVersionAccessImpl] is used to create an ocm.ComponentVersionAccess object using the function [NewComponentVersionAccess].
  • interface [ComponentAccessImpl] is used to create an ocm.ComponentAccess object using the function [NewComponentAccess].
  • interface [RepositoryImpl] is used to create an ocm.ComponentAccess object using the function [NewRepository].

Component version implementations provide basic access to component versions and their descriptors. They keep a reference to component implementations, which are again based on repository implementations. The task of repository implementations is to provide component objects. Their implementations are responsible to provide component version objects.

Simplified Respository Implementation Interface

Besides this basic implementation interfaces with separated objects for a repository, component and component version, there is support for a simplified implementation interface (StorageBackendImpl). This is a single interface bundling all required functionality to implement the objects for the three concerned elements. With NewStorageBackend it is possible to instantiate a new kind of repository based on this single interface. The required objects for components and component versions are generically provided based on the methods provided by this interface.

Comparison of Implementation Models

The simplified implementation model does not provide access to the implementation objects for components and component versions. Therefore, it is not possible to keep state for those elements.

Storage Backend Implementations requiring such state, like the OCI implementation based on the OCI abstraction provided by the OCI context, therefore use dedicated implementations for repository, component and component version objects. This model provides complete control over the lifecycle of those elements.

If a storage backend implementation is stateless or just keeps state at the repository level, the simplified implementation model can be chosen.

Documentation

Overview

Package repocpi contains the implementation support for repository backends. It offers three methods to create component version, component and repository objects based on three simple implementation interfaces.

The basic provisioning model is layered:

  • on layer 1 there is the user facing API defined in package github.com/open-component-model/ocm/pkg/contexts/ocm.

  • on layer 2 (this package) there is a backend agnostic implementation of standard functionality based on layer 3. This is divided into two parts

    a) the view objects provided by the Dup() calls of the layer 1 API. All dups are internally based on a single base object. These objects are called bridge. They act as base object for the views and as abstraction for the implementation objects providing generic implementations potentially based on the implementation functionality. (see bridge design pattern https://refactoring.guru/design-patterns/bridge)

    b) the bridge object as base for all dup views is used to implement some common functionality like the view management. The bridge object is closed, when the last view disappears. This bridge object then calls the final storage backend implementation interface.

  • the storage backend implementations based on the implementation interfaces provided by layer 2.

The implementation interfaces and the functions to create API objects are:

Component version implementations provide basic access to component versions and their descriptors. They keep a reference to component implementations, which are again based on repository implementations. The task of repository implementations is to provide component objects. Their implementations are responsible to provide component version objects.

Besides this basic implementation interface with separated object for a repository, component and component version, there is support for a simplified implementation interface (StorageBackendImpl). This is a single interface bundling all required functionality to implement the objects for the three concerned elements. With NewStorageBackend it is possible to instantiate a new kind of repository based on this single interface. The required objects for components and component versions are generically provided based on the methods provided by this interface.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrClosed      = resource.ErrClosed
	ErrTempVersion = fmt.Errorf("temporary component version cannot be updated")
)

Functions

func NewComponentAccess

func NewComponentAccess(impl ComponentAccessImpl, kind string, main bool, closer ...io.Closer) (cpi.ComponentAccess, error)

func NewComponentVersionAccess

func NewComponentVersionAccess(name, version string, impl ComponentVersionAccessImpl, lazy, persistent, direct bool, closer ...io.Closer) (cpi.ComponentVersionAccess, error)

func NewNoneRefRepositoryView

func NewNoneRefRepositoryView(i RepositoryBridge) cpi.Repository

NewNoneRefRepositoryView provides a repository reflecting the state of the view manager without holding an additional reference.

func NewRepository

func NewRepository(impl RepositoryImpl, kind string, closer ...io.Closer) cpi.Repository

func NewStorageBackend

func NewStorageBackend(kind string, impl StorageBackendImpl) cpi.Repository

NewStorageBackend provides a complete repository view with repository, component and component version objects based on the implementation of the sole interface StorageBackendImpl. No further implementations are required besides a dedicated specification object, the dependent object types are generically provided based on the methods of this interface. The kind parameter is used to denote the kind of repository in ids and log messages.

Types

type BlobCache

type BlobCache interface {
	// AddBlobFor stores blobs for added blobs not yet accessible
	// by generated access method until version is finally added.
	AddBlobFor(acc BlobCacheKey, blob BlobCacheEntry) error

	// GetBlobFor retrieves the original blob access for
	// a given access specification.
	GetBlobFor(acc BlobCacheKey) BlobCacheEntry

	RemoveBlobFor(acc BlobCacheKey)
	Clear() error
}

func NewBlobCache

func NewBlobCache() BlobCache

type BlobCacheEntry

type BlobCacheEntry = blobaccess.BlobAccess

type BlobCacheKey

type BlobCacheKey = interface{}

type BlobContainer

type BlobContainer interface {
	GetBlob(name string) (cpi.DataAccess, error)

	// GetStorageContext creates a storage context for blobs
	// that is used to feed blob handlers for specific blob storage methods.
	// If no handler accepts the blob, the AddBlobFor method will
	// be used to store the blob
	GetStorageContext() cpi.StorageContext

	// AddBlob stores a local blob together with the component and
	// potentially provides a global reference according to the OCI distribution spec
	// if the blob described an oci artifact.
	// The resulting access information (global and local) is provided as
	// an access method specification usable in a component descriptor.
	// This is the direct technical storage, without caring about any handler.
	AddBlob(blob cpi.BlobAccess, refName string, global cpi.AccessSpec) (cpi.AccessSpec, error)
}

BlobContainer is the interface for an element capable to store blobs.

type ComponentAccessBridge

type ComponentAccessBridge interface {
	resource.ResourceImplementation[cpi.ComponentAccess]

	GetContext() cpi.Context
	IsReadOnly() bool
	GetName() string

	IsOwned(access cpi.ComponentVersionAccess) bool

	ListVersions() ([]string, error)
	LookupVersion(version string) (cpi.ComponentVersionAccess, error)
	HasVersion(vers string) (bool, error)
	NewVersion(version string, overrides ...bool) (cpi.ComponentVersionAccess, error)

	Close() error
	AddVersion(cv cpi.ComponentVersionAccess, opts *cpi.AddVersionOptions) (ferr error)
}

func GetComponentAccessBridge

func GetComponentAccessBridge(n cpi.ComponentAccess) (ComponentAccessBridge, error)

type ComponentAccessImpl

type ComponentAccessImpl interface {
	SetBridge(bridge ComponentAccessBridge)
	GetParentBridge() RepositoryViewManager

	GetContext() cpi.Context
	GetName() string
	IsReadOnly() bool

	ListVersions() ([]string, error)
	HasVersion(vers string) (bool, error)
	LookupVersion(version string) (*ComponentVersionAccessInfo, error)
	NewVersion(version string, overrides ...bool) (*ComponentVersionAccessInfo, error)

	io.Closer
}

ComponentAccessImpl is the provider implementation interface for component versions.

func GetComponentAccessImplementation

func GetComponentAccessImplementation(n cpi.ComponentAccess) (ComponentAccessImpl, error)

type ComponentAccessInfo

type ComponentAccessInfo struct {
	Impl ComponentAccessImpl
	Kind string
	Main bool
}

type ComponentAccessViewManager

type ComponentAccessViewManager = resource.ViewManager[cpi.ComponentAccess] // here you have to use an alias

type ComponentVersionAccessBridge

type ComponentVersionAccessBridge interface {
	resource.ResourceImplementation[cpi.ComponentVersionAccess]
	common.VersionedElement
	io.Closer

	GetContext() cpi.Context
	Repository() cpi.Repository

	GetImplementation() ComponentVersionAccessImpl

	EnablePersistence() bool
	DiscardChanges()
	IsPersistent() bool

	GetDescriptor() *compdesc.ComponentDescriptor

	AccessMethod(cpi.AccessSpec, refmgmt.ExtendedAllocatable) (cpi.AccessMethod, error)

	// GetStorageContext creates a storage context for blobs
	// that is used to feed blob handlers for specific blob storage methods.
	// If no handler accepts the blob, the AddBlob method will
	// be used to store the blob
	GetStorageContext() cpi.StorageContext

	// AddBlob stores a local blob together with the component and
	// potentially provides a global reference.
	// The resulting access information (global and local) is provided as
	// an access method specification usable in a component descriptor.
	// This is the direct technical storage, without caring about any handler.
	AddBlob(blob cpi.BlobAccess, arttype, refName string, global cpi.AccessSpec, final bool, opts *cpi.BlobUploadOptions) (cpi.AccessSpec, error)

	IsReadOnly() bool
	SetReadOnly()

	// ShouldUpdate checks, whether an update is indicated
	// by the state of object, considering persistence, lazy, discard
	// and update mode state
	ShouldUpdate(final bool) bool

	// GetBlobCache retieves the blob cache used to store preliminary
	// blob accesses for freshly generated local access specs not directly
	// usable until a component version is finally added to the repository.
	GetBlobCache() BlobCache

	// UseDirectAccess returns true if composition should be directly
	// forwarded to the repository backend.,
	UseDirectAccess() bool

	// Update persists the current state of the component version to the
	// underlying repository backend.
	Update(final bool) error
}

type ComponentVersionAccessImpl

type ComponentVersionAccessImpl interface {
	GetContext() cpi.Context
	SetBridge(bridge ComponentVersionAccessBridge)
	GetParentBridge() ComponentAccessBridge

	Repository() cpi.Repository

	IsReadOnly() bool
	SetReadOnly()

	GetDescriptor() *compdesc.ComponentDescriptor
	SetDescriptor(*compdesc.ComponentDescriptor) error

	AccessMethod(acc cpi.AccessSpec, cv refmgmt.ExtendedAllocatable) (cpi.AccessMethod, error)

	BlobContainer
	io.Closer
}

ComponentVersionAccessImpl is the provider implementation interface for component versions.

type ComponentVersionAccessInfo

type ComponentVersionAccessInfo struct {
	Impl       ComponentVersionAccessImpl
	Lazy       bool
	Persistent bool
}

type ComponentVersionAccessViewManager

type ComponentVersionAccessViewManager = resource.ViewManager[cpi.ComponentVersionAccess]

type Repository added in v0.13.0

type Repository = internal.Repository

type RepositoryBridge

type RepositoryBridge interface {
	resource.ResourceImplementation[cpi.Repository]

	GetContext() cpi.Context

	IsReadOnly() bool
	SetReadOnly()

	GetSpecification() cpi.RepositorySpec
	ComponentLister() cpi.ComponentLister

	ExistsComponentVersion(name string, version string) (bool, error)
	LookupComponentVersion(name string, version string) (cpi.ComponentVersionAccess, error)
	LookupComponent(name string) (cpi.ComponentAccess, error)

	io.Closer
}

func GetRepositoryBridge

func GetRepositoryBridge(n cpi.Repository) (RepositoryBridge, error)

type RepositoryImpl

type RepositoryImpl interface {
	SetBridge(bridge RepositoryBridge)

	GetContext() cpi.Context

	IsReadOnly() bool
	SetReadOnly()

	GetSpecification() cpi.RepositorySpec
	ComponentLister() cpi.ComponentLister

	ExistsComponentVersion(name string, version string) (bool, error)
	LookupComponent(name string) (*ComponentAccessInfo, error)

	io.Closer
}

func GetRepositoryImplementation

func GetRepositoryImplementation(n cpi.Repository) (RepositoryImpl, error)

type RepositoryViewManager

type RepositoryViewManager = resource.ViewManager[cpi.Repository] // here you have to use an alias

type StorageBackendImpl

type StorageBackendImpl interface {
	io.Closer
	GetContext() cpi.Context
	GetSpecification() cpi.RepositorySpec

	// IsReadOnly returns readonly mode for repo,
	// if key is given for the dedicated component version access.
	IsReadOnly(key ...common.NameVersion) bool

	// SetReadOnly sets readonly mode for repo,
	// if key is given for the dedicated component version access.
	SetReadOnly(key ...common.NameVersion)

	ComponentLister() cpi.ComponentLister
	HasComponent(name string) (bool, error)
	HasComponentVersion(key common.NameVersion) (bool, error)

	ListVersions(comp string) ([]string, error)
	HasVersion(vers string) (bool, error)

	GetDescriptor(key common.NameVersion) (*compdesc.ComponentDescriptor, error)
	SetDescriptor(key common.NameVersion, descriptor *compdesc.ComponentDescriptor) error
	AccessMethod(key common.NameVersion, acc cpi.AccessSpec, cv refmgmt.ExtendedAllocatable) (cpi.AccessMethod, error)
	GetStorageContext(key common.NameVersion) cpi.StorageContext
	GetBlob(key common.NameVersion, name string) (cpi.DataAccess, error)
	AddBlob(key common.NameVersion, blob cpi.BlobAccess, refName string, global cpi.AccessSpec) (cpi.AccessSpec, error)
}

StorageBackendImpl is an interface which can be implemented to provide a complete repository view with repository, component and component version objects, which are generically implemented based on the methods of this interface.

A repository interface based on this implementation interface can be created using the function NewStorageBackend.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL