The complete library is arranged around area specific Context
objects,
which bundle all the settings and supported
extensions
of the Open Component Model.
Extension points are implemented by handlers that can be registered at dedicated
context objects or at the default runtime environment.
The context then provides all the methods required to access elements
managed in the dedicated area.
The examples shown here provide an overview of the library. A more detailed annotated tour through various aspects of the library with ready-to work examples can be for here.
In the comparison scenario there is an example for an end-to-end scenario, from providing a component version by a software provider, over its publishing up to the consumption in an air-gapped environment, and the final deployment in this environment. Especially the deployment part just wants to illustrate the basic workflow using a Helm chart based example. It is not intended to be used as productive environment.
For working with OCM repositories an appropriate context, which can be used to retrieve OCM repositories, can be accessed with:
import "ocm.software/ocm/api/ocm"
func MyFirstOCMApplication() {
octx := ocm.DefaultContext()
...
}
If a decoupled environment with dedicated special settings is required, the
builder methods of the ocm package (With...
) can be used to compose
a context.
With ocm.New()
a fresh ocm
context is created using the default settings.
It is possible to create any number of such contexts.
The context can then be used to gain access to (OCM) repositories, which provide access to hosted components and component versions.
To access a repository, a repository specification
is required. Every repository type extension supported by this library
uses its own package under ocm.software/ocm/api/ocm/extensions/repositories
.
To access an OCM repository based on an OCI registry the package
ocm.software/ocm/api/ocm/extensions/repositories/ocireg
contains the appropriate language binding for the OCI registry mappings.
Those packages typically have the method NewRepositorySpec
to create
an appropriate specification object for a concrete instance.
repoSpec := ocireg.NewRepositorySpec("ghcr.io/mandelsoft/ocm", nil)
repo, err := octx.RepositoryForSpec(repoSpec)
if err != nil {
return err
}
defer repo.Close()
Once a repository object is available it can be used to access component versions.
compvers, err := repo.LookupComponentVersion(componentName, componentVersion)
if err != nil {
return err
}
defer compvers.Close()
The component version now provides access to the described content, the component descriptor, resources, sources, component references, and signatures.
The component descriptor is accessible by a standardized Go representation, which is independent of the actually used serialization format. If can be encoded again in the original or any other supported scheme versions.
cd := compvers.GetDescriptor()
data, err := compdesc.Encode(cd)
if err != nil {
return err
}
Any resource (or source) can be accessed by getting the appropriate resource object by its resource identity in the context of the component version.
res, err := compvers.GetResource(metav1.NewIdentity(resourceName))
if err != nil {
return err
}
fmt.Printf("resource %s:\n type: %s\n", resourceName, res.Meta().Type)
The content of a described resource can be accessed using the appropriate access method described as part of the resource specification (another extension point of the model). It is described by an access specification. Supported methods can be directly be requested using the resource object.
meth, err := res.AccessMethod()
if err != nil {
return err
}
defer meth.Close()
fmt.Printf(" mime: %s\n", meth.MimeType())
The access method then provides access to the technical blob content. Here a stream access or a byte array access is possible.
data, err = meth.Get()
if err != nil {
return err
}
fmt.Printf(" content:\n%s\n", utils.IndentLines(string(data), " ",))
Besides this simple example, there are more usage scenarios, which typically require more configuration:
- creating content and credential handling
- dealing with configuration
- creating OCM content in temporary CTFs and publishing it
In folder comparison-scenario
there is
an example for an end-to-end scenario,
from building a component version to publishing, consuming and deploying
it in a separate environment. It shows the usage of the OCM library to
implement all the required process steps.
It builds a component version for the podinfo helm chart. There are two scenarios:
- provisioning
- building a component version with a helm based deployment description
- signing it and
- publishing it
- consumption in a separate repository environment
- transferring the component version into a separate repository environment.
- using the deployment description to localize the helm chart value - preparing values to refer to the podinfo OCI image available in the local environment.
- finally deploying it with helm.