Skip to content

DEV-1041 rewrite operator examples page - #971

Merged
rb-kurrent merged 1 commit into
masterfrom
operator-examples
Jun 10, 2026
Merged

rb-kurrent merged 1 commit into
masterfrom
operator-examples

Conversation

@rb-kurrent

Copy link
Copy Markdown
Contributor

The operator examples page had several issues:

  • It wasn't opinionated enough. Users weren't given a strong idea of what we recommend they do.

  • It was all written with full manifests rather than diffs. This made the examples mostly runnable but gave the wrong impression about how much we recommend some common options. Even though each example was minimal, it still didn't give the reader a clear idea what specific details in the manifest contributed to the feature the example was describing.

  • It was just a loosely ordered pile of examples with no real narrative to guide the reader.

By contrast, this new rewrite trieds to meet every need:

  • It is strongly opinionated. You can't miss our recommendations because they're present in every full manifest.

  • It has diffs and full manifests for all the incremental steps. The reader can clearly see what edits are being made corresponding to each step.

  • There is a clear narrative covering 2/3 of the page, and the final 1/3 is miscellaneous examples.

  • A reader who ignores the narrative is presented with "This is step N of M." to cue them into the fact that they're skipping the narrative. Even so, each numbered example is useful to illustrate its specific concept, even if the narrative is ignored.

  • There's a ton of copy-pasta in the source document, and a script to check that the copy-pasta is free of errors after making edits.

Description

Page previews

@rb-kurrent
rb-kurrent requested a review from a team as a code owner June 10, 2026 17:17
@linear-code

linear-code Bot commented Jun 10, 2026

Copy link
Copy Markdown

DEV-1041

@qodo-code-review

qodo-code-review Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (3)

Grey Divider


Action required

1. Wrong .network.loadBalancers key 📘 Rule violation ≡ Correctness
Description
The LetsEncrypt documentation tells users to set .network.loadBalancers.enabled, but the
manifest/example YAML and surrounding docs use .network.loadBalancer.enabled (singular). Following
the current prose will send readers to an incorrect spec path and can misconfigure external access
to the cluster.
Code

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[R2280-2281]

+Configure `.network.loadBalancers.enabled: true` so your external clients can access your KurrentDB
+according to its `fqdnTemplate`.
Evidence
PR Compliance ID 4 requires clear, precise step-by-step instructions, but the LetsEncrypt narrative
explicitly directs users to configure loadBalancers (plural) while the example/diff immediately
below shows the correct key loadBalancer (singular). This mismatch within the same page
demonstrates the instruction is inaccurate and likely to cause readers to apply a non-working
configuration due to the wrong field name.

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2280-2281]
docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2278-2284]
docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2349-2354]
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The LetsEncrypt TLS documentation prose references an incorrect/non-existent field name `.network.loadBalancers.enabled` (plural), while the actual manifests/example YAML and other references use `.network.loadBalancer.enabled` (singular). Update the instructions so the field name is consistent and users configure the correct spec path.

## Issue Context
This occurs in the LetsEncrypt TLS example/step narrative immediately before the diff/example YAML and directly impacts whether external clients can access the cluster; it also violates the expectation (PR Compliance ID 4) that procedural instructions are clear and precise.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2278-2283]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. LetsEncrypt Issuer missing namespace 📘 Rule violation ≡ Correctness
Description
The LetsEncrypt Issuer example is a namespaced resource but omits metadata.namespace: kurrent,
and the instructions apply it without -n kurrent, so users will likely create the Issuer in their
current/default namespace. This mismatch causes certificate issuance to fail for Certificate
resources in the kurrent namespace and makes the setup steps non-copy/paste-safe.
Code

docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[R50-55]

```yaml
apiVersion: cert-manager.io/v1
-kind: ClusterIssuer
+kind: Issuer
metadata:
  name: letsencrypt
spec:
Evidence
PR Compliance ID 4 requires unambiguous, actionable instructions, but the LetsEncrypt manifest
defines an Issuer (namespaced) without specifying a namespace and the accompanying `kubectl apply
-f issuer.yaml command does not include -n kurrent`, making it unclear where the resource will be
created. Other examples in the same documentation explicitly set namespace: kurrent for Issuer
resources, indicating the LetsEncrypt Issuer should also be created in kurrent; without that, the
Issuer ends up in the user’s current/default namespace and will not be found by Certificates created
in kurrent, leading to a non-working configuration.

docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[50-55]
docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[50-79]
docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[94-102]
docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2290-2297]
docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[72-79]
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The LetsEncrypt `Issuer` example is namespaced but missing `metadata.namespace: kurrent`, and the docs apply it without `-n kurrent`, making the instructions ambiguous and likely to create the Issuer in the wrong namespace (default/current), which breaks certificate issuance for resources in `kurrent`.

## Issue Context
These docs describe certificate usage for KurrentDB deployments that use the `kurrent` namespace, and other `Issuer` examples on the same page (and related docs) explicitly set `namespace: kurrent`. The LetsEncrypt setup flow should be copy/paste-safe, so either the manifest should include the namespace or the command should specify `-n kurrent` (or both) to ensure the Issuer is created where the `Certificate` resources will reference it.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[50-70]
- docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[72-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Inconsistent From Zero To Prod casing 📘 Rule violation ⚙ Maintainability
Description
The section title uses From Zero to Prod while the step banners use From Zero To Prod, creating
inconsistent terminology within the same page. This reduces clarity for readers trying to follow the
series references.
Code

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[R209-217]

+## From Zero to Prod
+
+This section illustrates how to build up from the simplest possible "Hello, World" deployment in
+incremental steps.  Each step shows the diff that is applied in that step as well as the full
+manifest up to that point.
+
+### Configure a `StorageClass`
+
+*This is step 1 of 8 in the "From Zero To Prod" series of examples.*
Evidence
PR Compliance ID 4 requires reader-focused, clear instructional text. Using two different casings
for the same series name makes cross-references less clear and looks like a documentation error.

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[209-217]
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The page uses both `From Zero to Prod` and `From Zero To Prod` to refer to the same series, which is inconsistent.

## Issue Context
This appears in the main section heading and in the per-step banners, so readers will see both repeatedly.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[209-217]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Archiver cloud mismatch 🐞 Bug ≡ Correctness
Description
The Archiver Node example says it assumes Azure IRSA/workload identity but configures archiving as
StorageType: S3 with an S3: block, which is contradictory and will mislead users about which
credentials/backend they need.
Code

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[R1546-1577]

+- Deploy with suitable blob storage credentials (this example assumes [Azure IRSA][irsaazure])
+
+```diff
++---
++apiVersion: v1
++kind: ServiceAccount
++metadata:
++  name: my-irsa-service-account
++  namespace: kurrent
++  annotations:
++    azure.workload.identity/client-id: <USER_ASSIGNED_CLIENT_ID>
+ ---
+ apiVersion: kubernetes.kurrent.io/v1
+ kind: KurrentDB
+ metadata:
+   name: mydb
+   namespace: kurrent
+ spec:
+   replicas: 3
++  archiver:
++    enabled: true
+   ...
++  configuration:
++    Archive:
++      Enabled: true
++      RetainAtLeast:
++        Days: 0
++        LogicalBytes: 1073741824  # 1GiB
++      StorageType: S3
++      S3:
++        Region: us-west-1
++        Bucket: my-bucket
Evidence
The same example explicitly references Azure IRSA/workload identity and adds Azure identity
annotations, but the Archive configuration directly specifies S3 storage settings.

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[1546-1583]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The archiver example mixes Azure workload identity setup with an S3 archive configuration. This is internally inconsistent and can lead readers to configure the wrong backend/credentials.

## Issue Context
The diff adds an Azure workload identity ServiceAccount annotation and label, but the `Archive` configuration uses `StorageType: S3` and an `S3:` section.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[1546-1583]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Default doc path fragile 🐞 Bug ☼ Reliability
Description
check-diffs.py defaults to ./database-deployment.md, which fails when the script is run from the
repo root (common usage) because the markdown file lives alongside the script under the operations
directory.
Code

docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[R38-39]

+DEFAULT_DOC = "./database-deployment.md"
+
Evidence
The script hardcodes a CWD-relative default filename and opens it directly; the actual document is
stored under the operations directory, so the default only works if invoked from that directory.

docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[38-64]
docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[1-15]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`DEFAULT_DOC` is a relative path that depends on the current working directory. Running the script from outside `docs/server/kubernetes-operator/v1.6.0/operations/` will raise FileNotFoundError.

## Issue Context
The target markdown file is in the same directory as the script.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[38-64]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
6. Missing rec.full guard 🐞 Bug ☼ Reliability
Description
check_additional_examples() calls diff_plausible(rec.full, ...) without verifying rec.full is
set, so if parsing fails to capture the Recommended manifest the script will crash instead of
reporting a clean failure.
Code

docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[R325-342]

+def check_additional_examples(tree, rpt):
+    print("\n[4] Each Additional Example builds from Recommended "
+          "(skipping LetsEncrypt + Standalone RoR)")
+    _, rec = find_top(tree, "recommended")
+    _, add = find_top(tree, "additional examples")
+    if rec is None or add is None:
+        rpt.fail("could not locate both sections")
+        return
+    for title, leaf in add.items():
+        low = title.lower()
+        if "letsencrypt" in low or "standalone" in low:
+            print(f"  \033[33mSKIP\033[0m {title!r}")
+            continue
+        if leaf.full is None or leaf.diff is None:
+            rpt.fail(f"{title!r}: missing diff or full manifest")
+            continue
+        ok, info = diff_plausible(rec.full, leaf.diff, leaf.full)
+        if ok:
Evidence
The code checks only that the section exists, not that rec.full exists, before calling into
diff_plausible() which operates on the provided line lists.

docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[201-210]
docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[325-342]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Some checks assume `rec.full` is non-None and pass it into `diff_plausible()`. If the Recommended section is missing its yaml fence (or parsing misses it), the script will throw rather than report a helpful failure.

## Issue Context
`diff_plausible()` expects iterables of lines and immediately iterates/cleans them.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[201-210]
- docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py[325-342]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@github-actions

github-actions Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

Docs build

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Rewrite operator example deployments page with stepwise diffs + validator
📝 Documentation ✨ Enhancement 🕐 40+ Minutes

Grey Divider

Walkthroughs

Description
• Rewrites operator deployment examples into an opinionated, narrative “From Zero to Prod” flow.
• Adds per-step diff + full-manifest tabs to make each incremental change explicit.
• Introduces a consistency-check script to validate copied YAML/diff snippets stay in sync.
Diagram
graph TD
  A[["database-deployment.md"]] --> B["check-diffs.py"] --> C["Parse headings & fences"] --> D["Diff plausibility checks"] --> E{"Consistent?"}
  E -->|"Yes"| F["PASS report"] --> G["Exit 0"]
  E -->|"No"| H["FAIL report"] --> I["Exit 1"]
  subgraph Legend
    direction LR
    _doc[["Document"]] ~~~ _proc["Process"] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Generate examples from a single YAML source (templating/includes)
  • ➕ Eliminates copy/paste drift by construction
  • ➕ Makes updates easier across many examples
  • ➕ Could also generate both diff and full views automatically
  • ➖ Requires docs build/tooling changes and contributor onboarding
  • ➖ Harder for readers to directly copy a runnable manifest from the rendered page
  • ➖ May constrain the narrative structure to what the generator supports
2. Add a CI docs-lint step that runs the validator
  • ➕ Prevents broken examples from landing on main
  • ➕ Makes the consistency guarantee continuous rather than manual
  • ➖ Needs CI wiring and may increase pipeline runtime
  • ➖ May require ensuring dependencies/environment for docs paths
3. Use a stricter diff model (apply unified diff formally)
  • ➕ More deterministic than the current 'plausibility' interleaving matcher
  • ➕ Would catch ordering/duplicate-line ambiguities more precisely
  • ➖ Harder to author diffs for documentation purposes (must be exact)
  • ➖ More brittle to formatting-only edits that shouldn’t matter to readers

Recommendation: Keep the current approach: a strongly narrative docs page plus a lightweight validator is a pragmatic fit for documentation-authored examples. If this page becomes frequently edited, the next best incremental improvement would be wiring check-diffs.py into CI to prevent regressions automatically; full templating/generation is higher upfront cost and reduces the “copy/paste runnable manifest” ergonomics.

Grey Divider

File Changes

Tests (1)
check-diffs.py Add markdown/YAML consistency validator for operator examples +405/-0

Add markdown/YAML consistency validator for operator examples

• Introduces a Python script that parses database-deployment.md headings and fenced blocks into a section tree, then checks that step diffs can plausibly produce their corresponding full manifests. It also enforces that the “Recommended Production Settings” manifest matches the final “From Zero to Prod” step and adds special-case validation for the LetsEncrypt example.

docs/server/kubernetes-operator/v1.6.0/operations/check-diffs.py


Documentation (2)
database-deployment.md Rewrite Example Deployments into opinionated narrative with diffs +2274/-244

Rewrite Example Deployments into opinionated narrative with diffs

• Replaces the prior loosely ordered set of full-manifest examples with a recommended baseline manifest plus an 8-step “From Zero to Prod” narrative where each step includes both a diff and the cumulative full manifest. Adds an “Additional Examples” section with diffs relative to the recommended baseline (including replicas, archiving, scheduling constraints, custom config, and LetsEncrypt), and tightens wording around ExternalDNS and networking strategies.

docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md


managing-certificates.md Update cert-manager issuer examples to match new docs conventions +25/-22

Update cert-manager issuer examples to match new docs conventions

• Updates LetsEncrypt and self-signed examples to use namespaced Issuer (not ClusterIssuer), adds AzureDNS-oriented guidance/links, and aligns placeholder syntax from {...} to <...>. Also clarifies issuerRef.kind and related formatting for readability.

docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md


Grey Divider

Qodo Logo

@github-actions

Copy link
Copy Markdown

Docs build

Comment on lines +2280 to +2281
Configure `.network.loadBalancers.enabled: true` so your external clients can access your KurrentDB
according to its `fqdnTemplate`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Wrong .network.loadbalancers key 📘 Rule violation ≡ Correctness

The LetsEncrypt documentation tells users to set .network.loadBalancers.enabled, but the
manifest/example YAML and surrounding docs use .network.loadBalancer.enabled (singular). Following
the current prose will send readers to an incorrect spec path and can misconfigure external access
to the cluster.
Agent Prompt
## Issue description
The LetsEncrypt TLS documentation prose references an incorrect/non-existent field name `.network.loadBalancers.enabled` (plural), while the actual manifests/example YAML and other references use `.network.loadBalancer.enabled` (singular). Update the instructions so the field name is consistent and users configure the correct spec path.

## Issue Context
This occurs in the LetsEncrypt TLS example/step narrative immediately before the diff/example YAML and directly impacts whether external clients can access the cluster; it also violates the expectation (PR Compliance ID 4) that procedural instructions are clear and precise.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/database-deployment.md[2278-2283]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Comment on lines 50 to 55
```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
kind: Issuer
metadata:
name: letsencrypt
spec:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Letsencrypt issuer missing namespace 📘 Rule violation ≡ Correctness

The LetsEncrypt Issuer example is a namespaced resource but omits metadata.namespace: kurrent,
and the instructions apply it without -n kurrent, so users will likely create the Issuer in their
current/default namespace. This mismatch causes certificate issuance to fail for Certificate
resources in the kurrent namespace and makes the setup steps non-copy/paste-safe.
Agent Prompt
## Issue description
The LetsEncrypt `Issuer` example is namespaced but missing `metadata.namespace: kurrent`, and the docs apply it without `-n kurrent`, making the instructions ambiguous and likely to create the Issuer in the wrong namespace (default/current), which breaks certificate issuance for resources in `kurrent`.

## Issue Context
These docs describe certificate usage for KurrentDB deployments that use the `kurrent` namespace, and other `Issuer` examples on the same page (and related docs) explicitly set `namespace: kurrent`. The LetsEncrypt setup flow should be copy/paste-safe, so either the manifest should include the namespace or the command should specify `-n kurrent` (or both) to ensure the Issuer is created where the `Certificate` resources will reference it.

## Fix Focus Areas
- docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[50-70]
- docs/server/kubernetes-operator/v1.6.0/operations/managing-certificates.md[72-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

Deploying documentation with  Cloudflare Pages  Cloudflare Pages

Latest commit: eeadffa
Status: ✅  Deploy successful!
Preview URL: https://395ef559.documentation-21k.pages.dev
Branch Preview URL: https://operator-examples.documentation-21k.pages.dev

View logs

The operator examples page had several issues:

- It wasn't opinionated enough.  Users weren't given a strong idea of what we recommend they do.

- It was all written with full manifests rather than diffs.  This made the examples mostly runnable
  but gave the wrong impression about how much we recommend some common options.  Even though each
  example was minimal, it still didn't give the reader a clear idea what specific details in the
  manifest contributed to the feature the example was describing.

- It was just a loosely ordered pile of examples with no real narrative to guide the reader.

By contrast, this new rewrite trieds to meet every need:

- It is strongly opinionated.  You can't miss our recommendations because they're present in every
  full manifest.

- It has diffs and full manifests for all the incremental steps.  The reader can clearly see what
  edits are being made corresponding to each step.

- There is a clear narrative covering 2/3 of the page, and the final 1/3 is miscellaneous examples.

- A reader who ignores the narrative is presented with "_This is step N of M._" to cue them into
  the fact that they're skipping the narrative.  Even so, each numbered example is useful to
  illustrate its specific concept, even if the narrative is ignored.

- There's a ton of copy-pasta in the source document, and a script to check that the copy-pasta is
  free of errors after making edits.
@github-actions

Copy link
Copy Markdown

Docs Preview

  • Status: ⏳ Creating preview…

@github-actions

Copy link
Copy Markdown

Docs build

@rb-kurrent
rb-kurrent merged commit fa82f82 into master Jun 10, 2026
3 checks passed
@rb-kurrent
rb-kurrent deleted the operator-examples branch June 10, 2026 18:59
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.

2 participants