Building a Catalog
Manifest format
We refer to a directory of files with one ClusterServiceVersion as a “bundle”. A bundle typically includes a ClusterServiceVersion and the CRDs that define the owned APIs of the CSV in its manifest directory, though additional objects may be included. It also includes an annotations file in its metadata folder which defines some higher level aggregate data that helps to describe the format and package information about how the bundle should be added into an index of bundles.
# example bundle
etcd
├── manifests
│ ├── etcdcluster.crd.yaml
│ └── etcdoperator.clusterserviceversion.yaml
└── metadata
└── annotations.yaml
When loading manifests into the database, the following invariants are validated:
* The bundle must have at least one channel defined in the annotations. * Every bundle has exactly one ClusterServiceVersion. * If a ClusterServiceVersion `owns` a CRD, that CRD must exist in the bundle.
Bundle directories are identified solely by the fact that they contain a ClusterServiceVersion, which provides an amount of freedom for layout of manifests.
Check out the operator bundle design proposal for more detail on the bundle format.
Bundle images
Using OCI spec container images as a method of storing the manifest and metadata contents of individual bundles, opm
interacts directly with these images to generate and incrementally update the database. Once you have your manifests defined and have created a directory in the format defined above, building the image is as simple as defining a Dockerfile and building that image:
FROM scratch
# We are pushing an operator-registry bundle
# that has both metadata and manifests.
LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1
LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/
LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/
LABEL operators.operatorframework.io.bundle.package.v1=test-operator
LABEL operators.operatorframework.io.bundle.channels.v1=beta,stable
LABEL operators.operatorframework.io.bundle.channel.default.v1=stable
ADD test/*.yaml /manifests
ADD test/metadata/annotations.yaml /metadata/annotations.yaml
podman build -t quay.io/my-container-registry-namespace/my-manifest-bundle:latest -f bundle.Dockerfile .
Once you have built the container, you can publish it like any other container image:
podman push quay.io/my-container-registry-namespace/my-manifest-bundle:latest
Of course, this build step can be done with any other OCI spec container tools like docker
, buildah
, libpod
, etc.
Building an index of Operators using opm
Index images are additive, so you can add a new version of your operator bundle when you publish a new version:
opm index add --bundles quay.io/my-container-registry-namespace/my-manifest-bundle:0.0.2 --from-index quay.io/my-container-registry-namespace/my-index:1.0.0 --tag quay.io/my-container-registry-namespace/my-index:1.0.1
For more detail on using opm
to generate index images, take a look at the documentation.
Where should I go next?
- Use the catalog of operators locally: Test your catalog locally
- Using a Catalog with OLM: Make your operator available for OLM in a cluster