Skip to content

🐛 fix(olm): give every owned CRD an alm-examples entry - #311

Merged
konih merged 1 commit into
mainfrom
lane/dist-oh-01-alm-examples
Aug 18, 2026
Merged

🐛 fix(olm): give every owned CRD an alm-examples entry#311
konih merged 1 commit into
mainfrom
lane/dist-oh-01-alm-examples

Conversation

@konih

@konih konih commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Why

The upstream OperatorHub hosted validator warns provided API should have an example annotation for every owned CRD that has no entry in metadata.annotations["alm-examples"]. Nine of the eleven owned kinds had none, so the OpenShift console and operatorhub.io "Create instance" flow handed users a blank YAML editor for all nine.

What changed

All 11 owned CRDs now carry an alm-examples entry in config/olm/template/manifests/kollect.clusterserviceversion.yaml:

KollectClusterInventory, KollectClusterScope, KollectClusterTarget, KollectConnectionTest, KollectDatabaseSink, KollectEventSink, KollectInventory, KollectProfile, KollectScope, KollectSnapshotSink, KollectTarget.

Every example was validated two ways:

  • server-side dry-run against a kind cluster with --validate=strict, so no field is misspelled or unknown to the CRD schema;
  • against the operator's own Go spec validators, so the examples are semantically valid input, not merely schema-shaped.

The assertions this replaces were vacuous

hack/test/dist_olm_bundle_test.sh previously asserted alm-examples coverage with two greps:

grep -Fq 'kind: KollectProfile' "${csv}"
grep -Fq 'kind: KollectTarget'  "${csv}"

Both search for the unquoted kind: KollectProfile form, which only ever matched the plain-YAML spec.customresourcedefinitions.owned list (line 349 of the CSV) — never the JSON inside the annotation, where the kind appears as "kind": "KollectProfile". Deleting the entire alm-examples annotation left both greps passing. They never tested alm-examples at all.

They are replaced by a set-comparison gate (check_alm_examples) that:

  • extracts the kind set from the alm-examples JSON and the kind set from spec.customresourcedefinitions.owned, and requires them to be equal — so a newly owned CRD cannot ship without an example;
  • asserts both extracted sets are non-empty, so a mistyped yq/jq path fails loudly instead of comparing two empty sets and passing vacuously;
  • rejects duplicate kinds, so a repeated entry cannot mask a missing one;
  • checks the annotation is valid JSON and is a JSON array;
  • runs against both the template (the file an author edits) and the generated bundle CSV (what upstream actually validates) — generation is a sed pass, so a template-only assertion would not prove the annotation survives it.

jq is now asserted as a hard requirement alongside yq, so a missing tool fails the gate rather than silently skipping it.

Verification

The independent reviewer confirmed the new gate is non-vacuous with 10 perturbations plus a positive control — removing the annotation, emptying it, corrupting the JSON, duplicating a kind, dropping a single kind, and breaking each extraction path all fail the gate; the unmodified tree passes.

Local gate matrix on the rebased head: all hack/test/dist_*.sh, task verify, task lint, task test, and pre-commit green. A DRY_RUN=1 bundle generation produces a CSV whose alm-examples contains exactly 11 entries, 11 distinct kinds, matching the 11 owned CRDs exactly.

The CSV declared 11 owned CRDs but shipped only 2 alm-examples, so the
OperatorHub hosted validator warned "provided API should have an example
annotation" for the other 9, and the OpenShift console offered a blank YAML
editor for most of the operator surface.

Add the 9 missing examples, reusing config/samples/ specs where one exists,
and make dist_olm_bundle_test.sh compare the alm-examples kind set against
spec.customresourcedefinitions.owned on both the template and the generated
bundle CSV. Both sides are asserted non-empty so a mistyped yq/jq path cannot
pass vacuously, and duplicate kinds cannot mask a missing one.

The two grep assertions this replaces matched the plain-YAML owned list, not
the JSON annotation, so they never tested alm-examples at all.

All 11 examples pass kubectl apply --dry-run=server --validate=strict against
a cluster with config/crd/bases installed, and the set is mutually consistent
under the scope admission floor.
@konih
konih merged commit 8a6eb3b into main Aug 18, 2026
33 checks passed
@konih
konih deleted the lane/dist-oh-01-alm-examples branch August 18, 2026 13:21
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant