Skip to content

perdasilva/rv1

Repository files navigation

rv1

A standalone Go library for rendering OLM registry+v1 bundles to plain Kubernetes manifests.

Extracted from operator-framework/operator-controller/internal/rukpak/render and compatible with operator-framework/operator-lifecycle-manager rendering behavior.

rv1 demo

Install

go get github.com/perdasilva/rv1

Usage

package main

import (
	"fmt"
	"os"

	"github.com/perdasilva/rv1"
)

func main() {
	// Load a bundle from a directory on disk
	source := rv1.FromFS(os.DirFS("path/to/bundle"))
	bundle, err := source.GetBundle()
	if err != nil {
		panic(err)
	}

	// Build a renderer and render the bundle
	renderer := rv1.NewRendererBuilder().Build()
	objects, err := renderer.Render(bundle, "my-namespace",
		rv1.WithTargetNamespaces("watch-ns"),
	)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Rendered %d objects\n", len(objects))
}

The builder supports certificate providers for webhook TLS and deployment customization:

renderer := rv1.NewRendererBuilder().
    WithCertificateProvider(rv1.CertManagerProvider{}).
    WithDeploymentConfig(&rv1.DeploymentConfig{
        NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
    }).
    Build()

CLI

The rv1 CLI renders bundles from the command line. It reads a bundle tar stream from stdin:

go install github.com/perdasilva/rv1/cmd/rv1@latest

# Render from a container image using docker
docker export $(docker create quay.io/my/bundle:v1 /bin/true) | rv1 render --install-namespace my-ns

# Or using crane
crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace my-ns

# Render with watch namespaces
crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace my-ns --watch-namespace ns1

# Render with a config file
crane export quay.io/my/bundle:v1 - | rv1 render --config render.yaml

Config file format (render.yaml):

certificateProvider:
  type: cert-manager  # or: openshift-service-ca, secret, none
deploymentConfig:
  nodeSelector:
    kubernetes.io/os: linux

The secret provider generates a kubernetes.io/tls Secret with optional cert/key data:

certificateProvider:
  type: secret
  secret:
    cert: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    key: |
      -----BEGIN PRIVATE KEY-----
      ...
      -----END PRIVATE KEY-----

If cert and key are omitted, an empty Secret is rendered so you can populate it externally (Vault, cert-manager ExternalSecret, etc.).

OLMv0 Compatibility

The library includes opt-in support for rendering behaviors from the original operator-lifecycle-manager (OLMv0).

Provided API ClusterRoles

Use WithProvidedAPIsClusterRoles() to generate aggregated admin/edit/view ClusterRoles for each owned CRD, matching OLMv0 behavior:

renderer := rv1.NewRendererBuilder().Build()
objs, err := renderer.Render(bundle, "my-namespace",
    rv1.WithProvidedAPIsClusterRoles(),
)

This generates 4 ClusterRoles per owned CRD:

  • <name>-<version>-admin — full access (*)
  • <name>-<version>-edit — write access (create, update, patch, delete)
  • <name>-<version>-view — read access (get, list, watch)
  • <name>-<version>-crd-view — read access to the CRD definition itself

These roles use Kubernetes aggregated ClusterRoles so they're automatically included in the built-in admin/edit/view roles.

Namespace Modes

The --watch-namespace flag controls which namespaces the operator watches. The behavior depends on the bundle's supported install modes:

AllNamespaces (default)

When the bundle supports AllNamespaces, omitting --watch-namespace watches all namespaces:

crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace ops

OwnNamespace

Watch only the install namespace — set --watch-namespace to the same value as --install-namespace:

crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace ops --watch-namespace ops

SingleNamespace

Watch a single namespace different from the install namespace:

crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace ops --watch-namespace target-ns

MultiNamespace

Watch multiple namespaces by repeating the flag:

crane export quay.io/my/bundle:v1 - | rv1 render --install-namespace ops --watch-namespace ns1 --watch-namespace ns2

Upstream Relationship

This library extracts and consolidates the registry+v1 bundle rendering logic from two operator-framework projects:

  • operator-controller — the OLMv1 rendering pipeline (internal/rukpak/render), which provides the core BundleRenderer, validators, and resource generators
  • operator-lifecycle-manager — the OLMv0 rendering behaviors, available as opt-in options (e.g., provided API ClusterRoles)

The goal is upstream fidelity — rendering output matches the upstream implementations for the same inputs. The library includes regression tests with golden-file fixtures to verify this.

Development

Requires Go 1.25+. Dev tools are managed via bingo and built automatically on first use.

make build     # build the rv1 CLI binary
make test      # run all unit tests
make lint      # run golangci-lint
make fmt       # run gofmt and goimports
make vet       # run go vet
make verify    # full quality gate (fmt + vet + lint + test)
make clean     # remove build artifacts

See CONTRIBUTING.md for the full contributor guide.

License

Apache-2.0

About

OLM registry+v1 bundle to plain manifest renderer

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors