Skip to content

OLS-3130: Operator-managed OKP / Solr hybrid RAG via RHOKP sidecar#1653

Open
blublinsky wants to merge 1 commit into
openshift:mainfrom
blublinsky:okp-support
Open

OLS-3130: Operator-managed OKP / Solr hybrid RAG via RHOKP sidecar#1653
blublinsky wants to merge 1 commit into
openshift:mainfrom
blublinsky:okp-support

Conversation

@blublinsky

@blublinsky blublinsky commented May 21, 2026

Copy link
Copy Markdown
Contributor

Description

Summary

Operator-only PR for OLS-3130: enable OKP (Offline Knowledge Portal) / Solr hybrid RAG for OpenShift Lightspeed by default.

When spec.ols.byokRAGOnly is false (default), the operator:

  • deploys an RHOKP sidecar on the app-server pod
  • writes solr_hybrid into the generated olsconfig.yaml
  • sets OCP_CLUSTER_VERSION on the app-server container so the service can serve documentation for the cluster’s OpenShift version

Set spec.ols.byokRAGOnly: true to disable OKP (no RHOKP sidecar, no solr_hybrid, no built-in OpenShift documentation retrieval).

OKP is operator-managed — there is no spec.ols.solrHybrid (or similar) CR field.

Service dependency: align with lightspeed-service#2992 / OLS-3313 (OCP product docs via Solr hybrid only; BYOK FAISS via spec.ols.rag).

Out of scope (follow-up PRs)

  • OLM bundle / CSV regeneration (make bundle) — required before customer release
  • RHOKP image in related_images.json and CSV --rhokp-image arg (use --rhokp-image for local/make deploy until then)
  • E2E coverage with RHOKP sidecar

CR / API

  • Document OKP as operator-managed on OLSSpec (godoc + CRD base comments only; no new CR fields)
  • Clarify byokRAGOnly and BYOK-focused wording on spec.ols.rag / RAGSpec
  • CRD base updated (config/crd/bases/); bundle manifests not regenerated in this PR

App server deployment

  • RHOKP sidecar (rhokp) when !byokRAGOnly
  • Port layout (shared pod network):
    • MCP server: 8080 (http://localhost:8080/mcp in OLS config)
    • RHOKP Apache HTTP (Solr proxy): 9080 (remapped from image default 8080)
    • RHOKP Apache HTTPS: 9443 (remapped from image default 8443)
    • OLS app server HTTPS: 8443 (unchanged)
  • Startup script remaps Apache Listen directives in httpd.conf / ssl.conf before mel start (ssl.conf must remain present for TLS cert setup)
  • Probes: /solr/portal-rag/admin/ping on port 9080; startup probe tuned for cold Solr load (~6 min budget)
  • RHOKP resources: 2 CPU, 2 GiB RAM, 75 GiB ephemeral; writable root filesystem
  • Operator flag --rhokp-image (default: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest in code; not in bundle yet)

OLS config generation

  • solr_hybrid with operator defaults (solr_http_base: http://localhost:9080, hybrid retrieval tuning)
  • reference_content.indexes: BYOK only from spec.ols.rag (no built-in OCP FAISS index; no byok_index)
  • OCP product documentation via solr_hybrid / RHOKP only
  • Built-in OpenShift MCP server URL remains http://localhost:8080/mcp

Local dev

  • make dev-setup applies config/dev/metrics-reader-token.yaml to stop metrics-reader token reconcile loops under make run

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up dependent library

Related Tickets & Documents

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

Unit tests

make test

Manual / cluster (recommended before merge)

  1. Deploy operator with --rhokp-image pointing at a known-good RHOKP image.
  2. Create OLSConfig with default settings (byokRAGOnly unset/false).
  3. Verify app-server pod has rhokp sidecar and MCP sidecar; no port bind conflicts.
  4. Confirm generated olsconfig ConfigMap contains:
    • solr_hybrid.solr_http_base: http://localhost:9080
    • mcp_servers entry url: http://localhost:8080/mcp
    • no built-in OCP FAISS entry under reference_content.indexes (BYOK entries only when spec.ols.rag is set)
  5. From app-server container: curl http://localhost:9080/solr/portal-rag/admin/ping → 200 after RHOKP startup.
  6. Exercise OCP documentation query via Lightspeed UI or API.
  7. Set spec.ols.byokRAGOnly: true → RHOKP sidecar removed, no solr_hybrid in config.

Container validation (done locally)

  • RHOKP Apache port remap (9080/9443) with MCP simulated on 8080: Solr ping and hybrid-search return 200.

Summary by CodeRabbit

  • New Features

    • Added support for the RHOKP Solr sidecar, including configurable image selection, startup port remapping, and health probes.
    • Operator-managed Solr hybrid RAG is now the default when OKP is enabled, with BYOK-only behavior controlled by byokRAGOnly.
  • Bug Fixes

    • Updated deployment/config generation so RHOKP and Solr hybrid settings are omitted when byokRAGOnly is true.
  • Documentation

    • Refreshed app-server and CRD documentation and integration tables to reflect the updated BYOK vs OKP/Solr hybrid behavior.
  • Chores

    • Improved local development setup with namespaced metrics-reader manifests and updated git ignore rules.

@openshift-ci openshift-ci Bot requested review from bparees and xrajesh May 21, 2026 18:13
@blublinsky

Copy link
Copy Markdown
Contributor Author

/retest

1 similar comment
@blublinsky

Copy link
Copy Markdown
Contributor Author

/retest

@blublinsky blublinsky force-pushed the okp-support branch 6 times, most recently from b6e8679 to 09d7a94 Compare May 26, 2026 12:19
@xrajesh

xrajesh commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

/hold
until 1.1.1 release is done @blublinsky

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 7, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

Adds RHOKP sidecar support and Solr hybrid RAG configuration gated by byokRAGOnly, with new config types, CLI/image plumbing, deployment generation, tests, and updated operator documentation.

Changes

RHOKP and Solr hybrid RAG

Layer / File(s) Summary
Contracts and defaults
api/v1alpha1/olsconfig_types.go, internal/controller/utils/*.go, internal/controller/reconciler/interface.go, internal/controller/olsconfig_helpers.go, cmd/main.go
Adds RHOKP image/options plumbing, Solr hybrid config types, new constants, default test reconciler wiring, and the GetRHOOKPImage() interface path.
CLI and manifest wiring
cmd/main.go, config/default/deployment-patch.yaml, hack/image_placeholders.json, config/dev/metrics-reader-token.yaml, Makefile, .gitignore
Adds the --rhokp-image flag, deployment patch placeholders, a dev metrics-reader token Secret, namespace-scoped setup/teardown commands, and ignore rules.
Config generation
internal/controller/appserver/assets.go, internal/controller/appserver/reconciler_test.go, internal/controller/appserver/assets_test.go
Changes olsconfig.yaml generation to keep BYOK indexes only, conditionally emit solr_hybrid, and updates the matching tests.
Deployment assembly
internal/controller/appserver/deployment.go, internal/controller/appserver/rhokp.go, internal/controller/appserver/suite_test.go, internal/controller/appserver/deployment_test.go, internal/controller/appserver/rhokp_test.go
Builds shared app-server env handling, appends the optional RHOKP sidecar, defines RHOKP startup/probe/env helpers, and updates deployment tests and helpers.
Documentation updates
.ai/spec/how/config-generation.md, .ai/spec/how/deployment-generation.md, .ai/spec/what/app-server.md, .ai/spec/what/crd-api.md
Revises the documented config, deployment, and CRD surfaces for operator-managed OKP, RHOKP resources, and byokRAGOnly behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant cmd_main as cmd/main.go
  participant reconciler as OLSConfigReconciler
  participant assets as buildOLSConfig
  participant deploy as GenerateOLSDeployment

  cmd_main->>cmd_main: read --rhokp-image
  cmd_main->>reconciler: set RHOOKPImage option
  reconciler->>assets: buildOLSConfig(cr)
  assets->>assets: emit reference indexes + solr_hybrid
  reconciler->>deploy: GenerateOLSDeployment(cr)
  deploy->>deploy: add RHOKP sidecar when !byokRAGOnly
Loading

Suggested reviewers: bparees, xrajesh

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: operator-managed OKP/Solr hybrid RAG via the RHOKP sidecar.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@blublinsky

Copy link
Copy Markdown
Contributor Author

/hold cancel

@openshift-ci openshift-ci Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 2, 2026
@blublinsky blublinsky changed the title Add Solr hybrid RAG via RHOKP sidecar OLS-3130: Operator-managed OKP / Solr hybrid RAG via RHOKP sidecar Jul 2, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 2, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 2, 2026

Copy link
Copy Markdown

@blublinsky: This pull request references OLS-3130 which is a valid jira issue.

Details

In response to this:

Description

Summary

Operator-only PR for OLS-3130: enable OKP (Offline Knowledge Portal) / Solr hybrid RAG for OpenShift Lightspeed by default.

When spec.ols.byokRAGOnly is false (default), the operator:

  • deploys an RHOKP sidecar on the app-server pod
  • writes ols_config.solr_hybrid into olsconfig.yaml
  • sets OCP_CLUSTER_VERSION on the app-server container for Solr version filtering
  • sets byok_index: true on all reference indexes

Set spec.ols.byokRAGOnly: true to disable OKP entirely (no RHOKP sidecar, no solr_hybrid, no built-in OCP documentation retrieval).

There is no spec.ols.solrHybrid CR field — OKP is operator-managed, not user-configured.

Out of scope (follow-up PRs)

  • OLM bundle / CSV regeneration (make bundle)
  • RHOKP image in related_images.json (use --rhokp-image for now)
  • Removal of transitional OCP FAISS index from reference_content
  • E2E coverage with RHOKP sidecar

CR / API

  • Document OKP as operator-managed on OLSSpec (godoc only)
  • Remove spec.ols.solrHybrid / SolrHybridSettings / solrDirectRag from the API
  • byokRAGOnly disables OKP sidecar, solr_hybrid config, and OCP_CLUSTER_VERSION
  • CRD base updated (config/crd/bases/); bundle manifests not regenerated in this PR

App server deployment

  • RHOKP sidecar (rhokp) when !byokRAGOnly
  • Port layout (shared pod network):
  • MCP server: 8080 (http://localhost:8080/mcp in OLS config)
  • RHOKP Apache HTTP (Solr proxy): 9080 (remapped from image default 8080)
  • RHOKP Apache HTTPS: 9443 (remapped from image default 8443)
  • OLS app server HTTPS: 8443 (unchanged)
  • Startup script remaps Apache Listen directives in httpd.conf / ssl.conf before mel start (ssl.conf must remain present for TLS cert setup)
  • Probes: /solr/portal-rag/admin/ping on port 9080; startup probe tuned for cold Solr load (~6 min budget)
  • Optional ACCESS_KEY from user-created secret rhokp-access-key
  • RHOKP resources: 2 CPU, 2 GiB RAM, 75 GiB ephemeral; writable root filesystem
  • Operator flag --rhokp-image (default: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest in code; not in bundle yet)

OLS config generation

  • solr_hybrid.solr_http_base: http://localhost:9080 plus operator defaults for hybrid retrieval tuning
  • Built-in OpenShift MCP server URL remains http://localhost:8080/mcp
  • Transitional: keeps OCP (and BYOK) FAISS entries in reference_content with byok_index: true until lightspeed-service is ready for Solr-only readiness

Local dev

  • make dev-setup applies config/dev/metrics-reader-token.yaml to stop metrics-reader token reconcile loops under make run

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up dependent library

Related Tickets & Documents

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

Unit tests

make test

Manual / cluster (recommended before merge)

  1. Deploy operator with --rhokp-image pointing at a known-good RHOKP image.
  2. Create OLSConfig with default settings (byokRAGOnly unset/false).
  3. Verify app-server pod has rhokp sidecar and MCP sidecar; no port bind conflicts.
  4. Confirm generated olsconfig ConfigMap contains:
  • solr_hybrid.solr_http_base: http://localhost:9080
  • mcp_servers entry url: http://localhost:8080/mcp
  1. From app-server container: curl http://localhost:9080/solr/portal-rag/admin/ping → 200 after RHOKP startup.
  2. Exercise OCP documentation query via Lightspeed UI or API.
  3. Set spec.ols.byokRAGOnly: true → RHOKP sidecar removed, no solr_hybrid in config.

Container validation (done locally)

  • RHOKP Apache port remap (9080/9443) with MCP simulated on 8080: Solr ping and hybrid-search return 200.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (9)
.ai/spec/how/config-generation.md (1)

71-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reference index example uses incorrect key names.

The reference_content.indexes example shows path:, index_id:, origin:, but the actual generated keys (per ReferenceIndex json tags) are product_docs_index_path, product_docs_index_id, product_docs_origin. Every other section of this doc uses literal generated key names — this block is inconsistent and could mislead a reader debugging real config output.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.ai/spec/how/config-generation.md around lines 71 - 83, The
reference_content.indexes example uses placeholder key names that don’t match
the generated config fields. Update the example to use the actual ReferenceIndex
JSON tag names from the generated output, namely product_docs_index_path,
product_docs_index_id, and product_docs_origin, and keep the rest of the block
aligned with the concrete generated keys used elsewhere in config-generation.md.
internal/controller/appserver/assets.go (1)

296-310: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Merge the two consecutive identical-condition if blocks.

Lines 298 and 306 both guard on !cr.Spec.OLSConfig.ByokRAGOnly. Splitting them obscures that the ByokIndex flag applies to all reference indexes (including user BYOK entries added earlier), not just the OCP index just appended. Combine them into a single block with a comment explaining why all entries get flagged.

♻️ Proposed refactor
 	if !cr.Spec.OLSConfig.ByokRAGOnly {
 		ocpReferenceIndex := utils.ReferenceIndex{
 			ProductDocsIndexPath: "/app-root/vector_db/ocp_product_docs/" + r.GetOpenShiftMajor() + "." + r.GetOpenshiftMinor(),
 			ProductDocsIndexId:   "ocp-product-docs-" + r.GetOpenShiftMajor() + "_" + r.GetOpenshiftMinor(),
 			ProductDocsOrigin:    "Red Hat OpenShift " + r.GetOpenShiftMajor() + "." + r.GetOpenshiftMinor() + " documentation",
 		}
 		referenceIndexes = append(referenceIndexes, ocpReferenceIndex)
-	}
-	if !cr.Spec.OLSConfig.ByokRAGOnly {
+
+		// lightspeed-service requires byok_index on every FAISS index (BYOK and OCP) when solr_hybrid is active.
 		for i := range referenceIndexes {
 			referenceIndexes[i].ByokIndex = true
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/assets.go` around lines 296 - 310, The
appserver reference index setup has two separate `if
!cr.Spec.OLSConfig.ByokRAGOnly` blocks in `assets.go`, which hides that
`ByokIndex` must be applied to every entry in `referenceIndexes`, not just the
newly added OCP index. Merge the OCP index append and the `ByokIndex` loop into
one conditional block in `referenceIndexes` handling, and add a short comment
clarifying that the flag is set for all reference indexes, including any user
BYOK entries already present.
internal/controller/appserver/assets_test.go (1)

129-133: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Self-referential SolrHybrid assertions don't test actual default values.

These three assertions compare the generated config's SolrHybrid against buildSolrHybridSettings() — the very function under test — so they'll pass even if the function's field values silently regress. The test at Line 618-635 in this same file already does this correctly by asserting against explicit utils.SolrHybridXXXDefault constants; apply the same pattern here instead of calling the production function as the expected value.

As per path instructions, "Reject tests that only mirror implementation without asserting behavior or reconciliation outcomes."

Also applies to: 1595-1615, 1629-1646

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/assets_test.go` around lines 129 - 133, The
SolrHybrid assertions are self-referential because they use
buildSolrHybridSettings() as the expected value, so the test can’t catch
regressions in default fields. Update the affected assertions in assets_test.go
to compare the generated config against explicit utility default constants,
following the existing pattern used elsewhere in this file with
utils.SolrHybridXXXDefault values instead of calling buildSolrHybridSettings()
as the expectation.

Source: Path instructions

internal/controller/utils/constants.go (2)

485-486: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Floating :latest tag as a coded default image.

RHOOKPImageDefault pins to :latest. The comment notes it's meant to be overridden via --rhokp-image until the image is productized, but if the flag is ever omitted the operator will silently pull whatever latest resolves to at runtime, which is a reproducibility/drift risk for a "default".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/utils/constants.go` around lines 485 - 486, The default
image constant RHOOKPImageDefault is using a floating :latest tag, which can
drift at runtime if --rhokp-image is not provided. Update the default in
constants.go to use a fixed, immutable image reference instead of latest, and
keep the surrounding RHOKP-related logic consistent so callers of
RHOOKPImageDefault and any image selection code continue to work with the pinned
value.

372-403: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Naming inconsistency: RHOOKP (double-O) vs. product name RHOKP.

Every new identifier here (RHOOKPHTTPPort, RHOOKPContainerName, RHOOKPImageDefault, etc.) spells the acronym with two O's, but the actual literal values, the PR title, and the commit message all use RHOKP (single O) — Red Hat's official product name for the Offline Knowledge Portal. For example, Line 458 assigns RHOOKPContainerName = "rhokp", mismatching the identifier and its own value. This typo is replicated across types.go, interface.go, and olsconfig_helpers.go (and likely rhokp.go/cmd/main.go in later cohorts). Worth a global rename now before this spreads further into the codebase and CLI/flag surface.

♻️ Example rename (repeat across all affected files)
-	RHOOKPHTTPPort = 9080
-	RHOOKPHTTPSPort = 9443
+	RHOKPHTTPPort = 9080
+	RHOKPHTTPSPort = 9443
...
-	RHOOKPContainerName = "rhokp"
+	RHOKPContainerName = "rhokp"

Also applies to: 457-458, 485-486

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/utils/constants.go` around lines 372 - 403, The new
constants and related identifiers use an inconsistent acronym spelling, with
RHOOKP appearing instead of the product-correct RHOKP. Rename the affected
symbols in this constants block and across the referenced usages so the
identifier names consistently match the official product name, including items
like RHOOKPHTTPPort, RHOOKPContainerName, and RHOOKPImageDefault-style
constants. Update all references in the related helpers and interface/type files
together to avoid breaking the public surface or leaving mixed naming behind.
internal/controller/appserver/deployment.go (1)

543-543: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comment no longer matches the gating condition.

The comment says the RHOKP sidecar is added "if Solr hybrid RAG is configured," but the actual condition (line 596) is !cr.Spec.OLSConfig.ByokRAGOnly — there's no separate "Solr hybrid RAG configured" toggle. Minor doc drift that could confuse future readers.

📝 Suggested comment fix
-	// 3. RHOKP Solr sidecar (if Solr hybrid RAG is configured)
+	// 3. RHOKP Solr sidecar (added unless ByokRAGOnly is true)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/deployment.go` at line 543, Update the comment
near the RHOKP Solr sidecar logic in deployment.go so it matches the actual
gating in the deployment path driven by `cr.Spec.OLSConfig.ByokRAGOnly`. The
current “if Solr hybrid RAG is configured” wording is misleading; rephrase it to
describe the real condition used by the surrounding deployment code, keeping the
comment aligned with the `RHOKP` sidecar handling and the `ByokRAGOnly` check.
internal/controller/appserver/deployment_test.go (1)

650-741: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider moving RHOKP sidecar tests out of the "Proxy settings" Context.

These two new It blocks aren't related to proxy configuration; placing them inside Context("Proxy settings", ...) means each one incurs the unrelated BeforeEach/AfterEach setup/teardown of the provider secret, additional-ca/proxy CA configmap, and OpenShift certs configmap. A dedicated Context("RHOKP sidecar", ...) (or top-level Describe) would make intent clearer and avoid unnecessary fixture churn.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/deployment_test.go` around lines 650 - 741, The
new RHOKP sidecar specs are misplaced inside the Proxy settings context in
deployment_test.go, so move the two It blocks that validate
GenerateOLSDeployment, RHOOKPContainerName, and OCPClusterVersionEnvVar into a
dedicated RHOKP sidecar Context or top-level Describe. Keep the proxy-related
tests under the existing Proxy settings context, and place the RHOKP assertions
with their own setup so they no longer inherit the provider secret,
additional-ca, proxy CA, and OpenShift cert fixture setup/teardown.
internal/controller/appserver/rhokp.go (2)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Confusing comment: "mel" is unclear.

The doc comment twice references "mel" (before mel start, mel's httpd pre-init), which doesn't read as intended English and obscures the important port-remap rationale documented here.

✏️ Suggested comment fix
-// rhokpStartupScript remaps RHOKP Apache HTTP/HTTPS listen ports before mel start so MCP (8080)
+// rhokpStartupScript remaps RHOKP Apache HTTP/HTTPS listen ports before startup so MCP (8080)
 // and the app server (8443) can keep the stock ports in the shared pod network namespace.
-// ssl.conf must remain present — mel's httpd pre-init reads it for TLS cert setup.
+// ssl.conf must remain present — the RHOKP image's httpd pre-init reads it for TLS cert setup.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/rhokp.go` around lines 11 - 13, The doc comment
on rhokpStartupScript uses “mel” in two places, which is unclear and makes the
port-remap rationale harder to understand. Update the comment text in
rhokpStartupScript to use the intended product/process name consistently and
read naturally, while preserving the explanation that the startup script remaps
Apache HTTP/HTTPS ports so MCP and the app server can keep their stock ports and
ssl.conf must remain present for TLS cert setup.

14-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent RHOKP casing across helpers in the same file.

rhokpStartupScript, rhokpContainerCommand, and rhokpContainerArgs use lowercase "rhokp" while generateRHOOKPEnv (and all imported utils.RHOOKP* constants) use "RHOOKP" (double O). This inconsistency within a single file is easy to mistype and confusing during future maintenance.

✏️ Suggested rename for consistency
-func rhokpStartupScript() string {
+func rhookpStartupScript() string {
 ...
-func rhokpContainerCommand() []string {
+func rhookpContainerCommand() []string {
 ...
-func rhokpContainerArgs() []string {
+func rhookpContainerArgs() []string {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/rhokp.go` around lines 14 - 52, Rename the
helper functions in this file to use the same RHOKP casing as the existing
utils.RHOOKP* constants and generateRHOOKPEnv, since the current mix of rhokp
and RHOOKP is inconsistent. Update the identifiers rhokpStartupScript,
rhokpContainerCommand, and rhokpContainerArgs to the same RHOKP-style naming
used elsewhere, and make sure any internal calls between these helpers are
updated together so the file stays consistent and easy to maintain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/controller/appserver/rhokp.go`:
- Around line 15-25: The command built in the rhokp helper is matching numeric
prefixes too broadly in its sed replacements. Update the formatting in the
function that returns the shell command so the replacements for the Listen and
_default_ directives are anchored to the full line by adding an end-of-line
boundary, preventing accidental rewrites of values like 80800 or 84430. Use the
existing rhokp command construction symbols and the related utils port/conf path
constants to locate the affected replacements.

In `@internal/controller/appserver/suite_test.go`:
- Around line 196-217: The helper functions deploymentContainerCount and
expectedAppServerEnv are closing over the package-level cr instead of the
per-test cr used inside the App server deployment tests. Update these helpers to
accept the relevant OLSConfig/CR as an explicit argument, and change all call
sites in deployment_test.go to pass the local cr from each BeforeEach/It block
so ByokRAGOnly is evaluated against the correct test state.

---

Nitpick comments:
In @.ai/spec/how/config-generation.md:
- Around line 71-83: The reference_content.indexes example uses placeholder key
names that don’t match the generated config fields. Update the example to use
the actual ReferenceIndex JSON tag names from the generated output, namely
product_docs_index_path, product_docs_index_id, and product_docs_origin, and
keep the rest of the block aligned with the concrete generated keys used
elsewhere in config-generation.md.

In `@internal/controller/appserver/assets_test.go`:
- Around line 129-133: The SolrHybrid assertions are self-referential because
they use buildSolrHybridSettings() as the expected value, so the test can’t
catch regressions in default fields. Update the affected assertions in
assets_test.go to compare the generated config against explicit utility default
constants, following the existing pattern used elsewhere in this file with
utils.SolrHybridXXXDefault values instead of calling buildSolrHybridSettings()
as the expectation.

In `@internal/controller/appserver/assets.go`:
- Around line 296-310: The appserver reference index setup has two separate `if
!cr.Spec.OLSConfig.ByokRAGOnly` blocks in `assets.go`, which hides that
`ByokIndex` must be applied to every entry in `referenceIndexes`, not just the
newly added OCP index. Merge the OCP index append and the `ByokIndex` loop into
one conditional block in `referenceIndexes` handling, and add a short comment
clarifying that the flag is set for all reference indexes, including any user
BYOK entries already present.

In `@internal/controller/appserver/deployment_test.go`:
- Around line 650-741: The new RHOKP sidecar specs are misplaced inside the
Proxy settings context in deployment_test.go, so move the two It blocks that
validate GenerateOLSDeployment, RHOOKPContainerName, and OCPClusterVersionEnvVar
into a dedicated RHOKP sidecar Context or top-level Describe. Keep the
proxy-related tests under the existing Proxy settings context, and place the
RHOKP assertions with their own setup so they no longer inherit the provider
secret, additional-ca, proxy CA, and OpenShift cert fixture setup/teardown.

In `@internal/controller/appserver/deployment.go`:
- Line 543: Update the comment near the RHOKP Solr sidecar logic in
deployment.go so it matches the actual gating in the deployment path driven by
`cr.Spec.OLSConfig.ByokRAGOnly`. The current “if Solr hybrid RAG is configured”
wording is misleading; rephrase it to describe the real condition used by the
surrounding deployment code, keeping the comment aligned with the `RHOKP`
sidecar handling and the `ByokRAGOnly` check.

In `@internal/controller/appserver/rhokp.go`:
- Around line 11-13: The doc comment on rhokpStartupScript uses “mel” in two
places, which is unclear and makes the port-remap rationale harder to
understand. Update the comment text in rhokpStartupScript to use the intended
product/process name consistently and read naturally, while preserving the
explanation that the startup script remaps Apache HTTP/HTTPS ports so MCP and
the app server can keep their stock ports and ssl.conf must remain present for
TLS cert setup.
- Around line 14-52: Rename the helper functions in this file to use the same
RHOKP casing as the existing utils.RHOOKP* constants and generateRHOOKPEnv,
since the current mix of rhokp and RHOOKP is inconsistent. Update the
identifiers rhokpStartupScript, rhokpContainerCommand, and rhokpContainerArgs to
the same RHOKP-style naming used elsewhere, and make sure any internal calls
between these helpers are updated together so the file stays consistent and easy
to maintain.

In `@internal/controller/utils/constants.go`:
- Around line 485-486: The default image constant RHOOKPImageDefault is using a
floating :latest tag, which can drift at runtime if --rhokp-image is not
provided. Update the default in constants.go to use a fixed, immutable image
reference instead of latest, and keep the surrounding RHOKP-related logic
consistent so callers of RHOOKPImageDefault and any image selection code
continue to work with the pinned value.
- Around line 372-403: The new constants and related identifiers use an
inconsistent acronym spelling, with RHOOKP appearing instead of the
product-correct RHOKP. Rename the affected symbols in this constants block and
across the referenced usages so the identifier names consistently match the
official product name, including items like RHOOKPHTTPPort, RHOOKPContainerName,
and RHOOKPImageDefault-style constants. Update all references in the related
helpers and interface/type files together to avoid breaking the public surface
or leaving mixed naming behind.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 89d46389-0839-4011-a1b1-74ba3b11fd02

📥 Commits

Reviewing files that changed from the base of the PR and between 7ed4504 and c2efc93.

⛔ Files ignored due to path filters (2)
  • api/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated.deepcopy.go
  • config/crd/bases/ols.openshift.io_olsconfigs.yaml is excluded by !config/crd/bases/**
📒 Files selected for processing (26)
  • .ai/spec/how/config-generation.md
  • .ai/spec/how/deployment-generation.md
  • .ai/spec/what/app-server.md
  • .ai/spec/what/crd-api.md
  • .gitignore
  • Makefile
  • api/v1alpha1/olsconfig_types.go
  • cmd/main.go
  • config/default/deployment-patch.yaml
  • config/dev/metrics-reader-token.yaml
  • hack/image_placeholders.json
  • internal/controller/appserver/assets.go
  • internal/controller/appserver/assets_test.go
  • internal/controller/appserver/deployment.go
  • internal/controller/appserver/deployment_test.go
  • internal/controller/appserver/reconciler_test.go
  • internal/controller/appserver/rhokp.go
  • internal/controller/appserver/rhokp_test.go
  • internal/controller/appserver/suite_test.go
  • internal/controller/olsconfig_helpers.go
  • internal/controller/reconciler/interface.go
  • internal/controller/utils/constants.go
  • internal/controller/utils/resource_defaults_test.go
  • internal/controller/utils/testing.go
  • internal/controller/utils/types.go
  • internal/controller/utils/utils.go

Comment on lines +15 to +25
return fmt.Sprintf(
`sed -i 's/^Listen %d/Listen %d/' %s && `+
`sed -i 's/^Listen 0.0.0.0:%d https/Listen 0.0.0.0:%d https/' %s && `+
`sed -i 's/_default_:%d/_default_:%d/' %s && `+
`exec %s %s`,
utils.RHOOKPImageHTTPPort, utils.RHOOKPHTTPPort, utils.RHOOKPHTTPDConfPath,
utils.RHOOKPImageHTTPSPort, utils.RHOOKPHTTPSPort, utils.RHOOKPHTTPDSSLConfPath,
utils.RHOOKPImageHTTPSPort, utils.RHOOKPHTTPSPort, utils.RHOOKPHTTPDSSLConfPath,
utils.RHOOKPContainerEntrypoint,
utils.RHOOKPMainCommand,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Red Hat OKP RHOKP image default httpd.conf Listen port configuration

💡 Result:

The Red Hat Offline Knowledge Portal (RHOKP), which is built upon the Red Hat UBI 9 httpd 2.4 container image, uses port 8080 as its default HTTP listening port and port 8443 as its default HTTPS listening port [1][2][3]. This configuration is standard for Red Hat's Apache HTTP Server container images (such as those in the SCLorg/httpd-container ecosystem) to ensure compatibility with OpenShift Container Platform security constraints, which typically restrict containers from binding to reserved ports below 1024 [4][5][6][7]. While older versions of some httpd images historically defaulted to port 80, modern RHEL-based httpd images have shifted to port 8080 to support non-root execution [8]. When deploying RHOKP or similar httpd-based workloads in OpenShift, you must configure your Services and Routes to map traffic to these target ports [9][10]. For example, when launching the RHOKP container, the standard port mapping is 8080:8080 and 8443:8443 [1][3][11].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and search RHOKP-related references.
git ls-files | rg '^internal/controller/appserver/|rhokp|RHOOKP|RHOKP|httpd\.conf|ssl\.conf|Listen '

echo '--- outline: internal/controller/appserver/rhokp.go ---'
ast-grep outline internal/controller/appserver/rhokp.go --view expanded || true

echo '--- surrounding file lines ---'
cat -n internal/controller/appserver/rhokp.go | sed -n '1,120p'

echo '--- search for RHOKP constants and command usage ---'
rg -n "RHOOKP|RHOKP|httpd\.conf|ssl\.conf|Listen 8080|Listen 8443|_default_" internal/controller cmd docs bundle -S || true

Repository: openshift/lightspeed-operator

Length of output: 13740


🌐 Web query:

RHOKP image httpd.conf Listen 8080 8443 ssl.conf _default_ exact directives

💡 Result:

In Apache HTTP Server configurations, the Listen directive tells the server to accept incoming connections on specific ports [1]. When running services on non-standard ports, such as 8080 for HTTP and 8443 for HTTPS, the following directives are typically used [1][2]: Listen 8080 Listen 8443 Regarding the default directive, it is used within a VirtualHost block to define a default configuration for requests that do not match any other specific ServerName or ServerAlias directive [3][4]. A common configuration pattern for SSL in ssl.conf is: # SSL and VirtualHost settings here In the context of Red Hat OpenShift, these ports (8080 and 8443) are frequently used because they are non-privileged, allowing containers to bind to them without requiring root privileges [5][6]. While "RHOKP" is not a standard acronym for a core Red Hat product (Red Hat OpenShift is commonly abbreviated as OCP), the use of these specific ports is a standard best practice for deploying Apache httpd within OpenShift containers [5][7]. Configuration files are generally managed via /etc/httpd/conf/httpd.conf for core settings and /etc/httpd/conf.d/ssl.conf for SSL-specific virtual host configurations [8][9][10].

Citations:


Anchor the sed replacements to the full directive. The current ports are 8080/8443, but these patterns still match numeric prefixes; add an end-of-line boundary ($) so a future Listen 80800 or _default_:84430 line can’t be rewritten accidentally.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/rhokp.go` around lines 15 - 25, The command
built in the rhokp helper is matching numeric prefixes too broadly in its sed
replacements. Update the formatting in the function that returns the shell
command so the replacements for the Listen and _default_ directives are anchored
to the full line by adding an end-of-line boundary, preventing accidental
rewrites of values like 80800 or 84430. Use the existing rhokp command
construction symbols and the related utils port/conf path constants to locate
the affected replacements.

Comment on lines +196 to +217
func deploymentContainerCount(base int) int {
if !cr.Spec.OLSConfig.ByokRAGOnly {
return base + 1
}
return base
}

func expectedAppServerEnv() []corev1.EnvVar {
env := []corev1.EnvVar{
{
Name: "OLS_CONFIG_FILE",
Value: filepath.Join(utils.OLSConfigMountRoot, utils.OLSConfigFilename),
},
}
if !cr.Spec.OLSConfig.ByokRAGOnly {
env = append(env, corev1.EnvVar{
Name: utils.OCPClusterVersionEnvVar,
Value: testReconcilerInstance.GetOpenShiftMajor() + "." + testReconcilerInstance.GetOpenshiftMinor(),
})
}
return env
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Helpers close over the wrong cr — variable shadowing bug.

deploymentContainerCount and expectedAppServerEnv reference the package-level cr declared in this file (set once in BeforeSuite and updated only there). However, deployment_test.go's outer Describe("App server deployment generation", ...) declares its own var cr *olsv1alpha1.OLSConfig (local to that closure), which shadows the package-level cr for every BeforeEach/It inside it. Calls like deploymentContainerCount(1) and expectedAppServerEnv() inside those It blocks therefore evaluate ByokRAGOnly against the suite-level cr, not the per-test cr that the test actually mutates.

This currently passes only because the package-level cr's ByokRAGOnly stays false (its zero value) for the whole suite, and none of the existing tests that call these helpers exercise ByokRAGOnly=true — so it's a latent footgun rather than an active failure. Any future test that flips the local cr.Spec.OLSConfig.ByokRAGOnly and then relies on these helpers for container-count/env expectations will silently get wrong expected values.

Pass cr explicitly instead of relying on the ambient package variable.

🐛 Suggested fix
-func deploymentContainerCount(base int) int {
+func deploymentContainerCount(cr *olsv1alpha1.OLSConfig, base int) int {
 	if !cr.Spec.OLSConfig.ByokRAGOnly {
 		return base + 1
 	}
 	return base
 }

-func expectedAppServerEnv() []corev1.EnvVar {
+func expectedAppServerEnv(cr *olsv1alpha1.OLSConfig) []corev1.EnvVar {
 	env := []corev1.EnvVar{
 		{
 			Name:  "OLS_CONFIG_FILE",
 			Value: filepath.Join(utils.OLSConfigMountRoot, utils.OLSConfigFilename),
 		},
 	}
 	if !cr.Spec.OLSConfig.ByokRAGOnly {
 		env = append(env, corev1.EnvVar{
 			Name:  utils.OCPClusterVersionEnvVar,
 			Value: testReconcilerInstance.GetOpenShiftMajor() + "." + testReconcilerInstance.GetOpenshiftMinor(),
 		})
 	}
 	return env
 }

This requires updating all call sites in deployment_test.go to pass the test's local cr (e.g. deploymentContainerCount(cr, 1), expectedAppServerEnv(cr)).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/appserver/suite_test.go` around lines 196 - 217, The
helper functions deploymentContainerCount and expectedAppServerEnv are closing
over the package-level cr instead of the per-test cr used inside the App server
deployment tests. Update these helpers to accept the relevant OLSConfig/CR as an
explicit argument, and change all call sites in deployment_test.go to pass the
local cr from each BeforeEach/It block so ByokRAGOnly is evaluated against the
correct test state.

@blublinsky

Copy link
Copy Markdown
Contributor Author

/override "ci/prow/bundle-e2e-4-21"
it is expected for operator only PR

@openshift-ci

openshift-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown

@blublinsky: Overrode contexts on behalf of blublinsky: ci/prow/bundle-e2e-4-21

Details

In response to this:

/override "ci/prow/bundle-e2e-4-21"
it is expected for operator only PR

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@vimalk78 vimalk78 left a comment

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.

AI Review — OLS-3130: Operator-managed OKP / Solr hybrid RAG

Score: 97/100 — PASS

Adherence

# Criterion Status
1 Create additional fields in the CR to configure both OKP and BYOK tools PASS
2 Install OKP image when RAG is configured PASS

Code Quality

One should-fix documentation inconsistency:

  • Spec/code mismatch on max_results: .ai/spec/how/config-generation.md shows max_results: 10 (unchanged context line from pre-existing spec) but SolrHybridMaxResultsDefault = 5 in code. The spec was partially updated (port changed to 9080) but max_results wasn't updated to match the new constant.

Notes

  • Port layout is clean: RHOKP 9080/9443, MCP 8080, app server 8443 — no conflicts
  • Startup probe budget (20s + 34×10s = 6 min) is reasonable for Solr cold start
  • RHOKP security context correctly maintains restricted PSS (RunAsNonRoot, no privilege escalation, drop ALL) with only ReadOnlyRootFilesystem relaxed for Solr data
  • appServerEnv() append is safe — GetProxyEnvVars() returns a fresh slice each call
  • Good catch fixing pre-existing McpServerImage test bug (OLSAppServerImageDefaultOpenShiftMCPServerImageDefault)
  • Test coverage is thorough: sidecar presence/absence, resource overrides, solr_hybrid config, byokRAGOnly, startup script port remapping
  • Bundle regeneration explicitly out of scope per PR description — fine for dev, required before release

🤖 Generated with Claude Code

@vimalk78

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 10, 2026
@blublinsky

Copy link
Copy Markdown
Contributor Author

/override "ci/prow/bundle-e2e-4-21"
it is expected for operator only PR

@openshift-ci

openshift-ci Bot commented Jul 10, 2026

Copy link
Copy Markdown

@blublinsky: Overrode contexts on behalf of blublinsky: ci/prow/bundle-e2e-4-21

Details

In response to this:

/override "ci/prow/bundle-e2e-4-21"
it is expected for operator only PR

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci

openshift-ci Bot commented Jul 10, 2026

Copy link
Copy Markdown

@blublinsky: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@blublinsky

Copy link
Copy Markdown
Contributor Author

/approve

@openshift-ci

openshift-ci Bot commented Jul 10, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: blublinsky

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants