Skip to content

feat: Config for replacing RAG IC with OKP on IA - #3477

Merged
rm3l merged 30 commits into
redhat-developer:mainfrom
gazarenkov:improve-parametrization
Sep 22, 2026
Merged

rm3l merged 30 commits into
redhat-developer:mainfrom
gazarenkov:improve-parametrization

Conversation

@gazarenkov

@gazarenkov gazarenkov commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Description

Summary

  • Add Go template substitution support for default-config and flavour YAML files ({{.Backstage.Name}}, {{.Backstage.Namespace}})
  • Add platform gating for plugin dependencies via rhdh.redhat.com/platform annotation

Features

Template Substitution in Default Config

Enable dynamic value injection in default-config and flavour configuration files using Go template syntax:

data:
  SERVICE_URL: "https://{{.Backstage.Name}}.{{.Backstage.Namespace}}.svc"

This allows plugin configurations to reference instance-specific values like internal service URLs (e.g., http://okp-{{.Backstage.Name}}).

Platform Gating for Plugin Dependencies

Plugin dependency resources can now be filtered by platform using the rhdh.redhat.com/platform annotation:

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: lightspeed-okp
  annotations:
    rhdh.redhat.com/platform: "ocp"  # Only applied on OpenShift

Values: ocp (OpenShift) or k8s (Kubernetes). Resources without annotation are applied on all platforms.

Which issue(s) does this PR fix or relate to

https://redhat.atlassian.net/browse/RHIDP-16793

PR acceptance criteria

  • Tests
  • Documentation

How to test changes / Special notes to the reviewer

  • Unit tests pass for template substitution (TestTemplateSubstitution_DefaultConfig, TestTemplateSubstitution_Flavour)
  • Unit tests pass for platform gating (TestReadPluginDepsPlatformGating, TestMatchesPlatform)
  • Verify template substitution works with intelligent-assistant flavour
  • Verify OCP-only resources (Routes) are not applied on k8s clusters

NOTE: To make it work with k8s imagePullSecret to access registry.redhat.io added to plugin-deps/okp.yaml.

  • Fill it with your token to test on k8s
  • Can remove it for OCP
    Recommendation: Move the okp image to registry.access.redhat.com instead, it is supported but does not require authentication.

Current state of PR allows to deploy LCORE + OKP on Openshift (see picture):

okp

Building Container Images for Testing

Need to test container images from this PR?

For Maintainers: To trigger a test image build, review the code and comment /build-images.
This always builds the HEAD of the PR branch.

For Contributors: Ask a maintainer to run /build-images.

Images will be built and pushed to Quay with links posted in comments.

@gazarenkov gazarenkov changed the title [POC] Config for replacing RAG with OKP on IA [POC] Config for replacing RAG IC with OKP on IA Sep 4, 2026
@maysunfaisal

Copy link
Copy Markdown
Member

Thanks @gazarenkov let me try this out

Comment thread config/profile/rhdh/plugin-deps/okp.yaml Outdated
Comment thread config/profile/rhdh/plugin-deps/okp.yaml
…tion

# Conflicts:
#	config/profile/rhdh/default-config/flavours/intelligent-assistant/configmap-files.yaml
#	config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml
#	config/profile/rhdh/default-config/flavours/intelligent-assistant/dynamic-plugins.yaml
@codecov

codecov Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.13253% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.00%. Comparing base (bb9f524) to head (4489af8).
⚠️ Report is 32 commits behind head on main.

Files with missing lines Patch % Lines
pkg/model/default-config.go 57.14% 3 Missing and 3 partials ⚠️
pkg/template/template.go 86.66% 2 Missing and 2 partials ⚠️
pkg/platform/platform.go 0.00% 2 Missing ⚠️
internal/controller/plugin-deps.go 0.00% 1 Missing ⚠️
pkg/model/runtime.go 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3477      +/-   ##
==========================================
+ Coverage   59.18%   60.00%   +0.81%     
==========================================
  Files          49       51       +2     
  Lines        3474     3560      +86     
==========================================
+ Hits         2056     2136      +80     
- Misses       1229     1230       +1     
- Partials      189      194       +5     
Flag Coverage Δ
nightly ?
unittests 60.00% <83.13%> (+0.81%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/model/db-secret.go 94.73% <100.00%> (ø)
pkg/model/db-service.go 93.10% <100.00%> (ø)
pkg/model/db-statefulset.go 96.29% <100.00%> (ø)
pkg/model/externalconfig.go 42.10% <100.00%> (+6.81%) ⬆️
pkg/model/plugin_deps.go 69.69% <100.00%> (+6.73%) ⬆️
pkg/model/pvcs.go 89.83% <100.00%> (ø)
pkg/model/route.go 67.88% <100.00%> (ø)
pkg/model/secretenvs.go 85.00% <100.00%> (ø)
pkg/model/secretfiles.go 83.33% <100.00%> (ø)
pkg/model/service.go 92.00% <100.00%> (ø)
... and 7 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maysunfaisal maysunfaisal left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Two overall comments:

First, config/profile/rhdh/kustomization.yaml needs two files for running on OpenShift:

- files:
  ...
  - default-config/flavours/intelligent-assistant/networkpolicy.yaml
  name: flavour-intelligent-assistant-config

- files:
  ...
  - plugin-deps/okp.yaml
  name: plugin-deps

And regenerate with

make bundle PROFILE=rhdh
make build-installer PROFILE=rhdh

Second, Confirmed on Kind that Kubernetes renders IA without OKP: no OKP resources, OKP_SERVICE_URL, or OKP RAG configuration. However, there is currently no Kubernetes OKP opt-in path; the templates hard-gate OKP to OpenShift...We should also do Kubernetes OKP opt-in (via Ingress). I msgd you on Slack, we can either document this as an MD file or as a new flavor like how you initially suggested if we want to keep it more simple. IF we are going for the Docs approach, the OKP Deployment and Service must remain available on both platforms. Only the Route should be annotated rhdh.redhat.com/platform: ocp

Comment thread config/profile/rhdh/plugin-deps/okp.yaml
Comment thread config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml Outdated
Comment thread config/profile/rhdh/plugin-deps/okp.yaml Outdated
Comment thread config/profile/rhdh/plugin-deps/okp.yaml Outdated

@maysunfaisal maysunfaisal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

I will open a follow up PR for adding two flavors to enable OKP (OKP will be disabled by default)

@openshift-ci openshift-ci Bot added the lgtm label Sep 21, 2026
@gazarenkov
gazarenkov marked this pull request as ready for review September 21, 2026 13:03
@gazarenkov
gazarenkov requested review from a team as code owners September 21, 2026 13:03
@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

Parameterize configs and replace Intelligent Assistant RAG with OKP

✨ Enhancement ⚙️ Configuration changes 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds runtime Go templating for default and flavour configurations.
• Gates plugin dependencies by platform and deploys OKP for OpenShift Intelligent Assistant.
• Replaces bundled RAG initialization with hardened Llama Stack and OKP configuration.
Diagram

graph TD
  A["Operator reconcile"] --> B["Runtime context"] --> C["Templated config"] --> D{"Platform check"}
  D -->|OCP| E["IA plugins"] --> F["OKP workload"] --> G["Lightspeed Core"]
  D -->|K8s| E
  E --> G
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Pass template context explicitly
  • ➕ Avoids package-global mutable state across concurrent reconciliations
  • ➕ Makes template ownership and test isolation explicit
  • ➕ Prevents one Backstage instance from leaking values into another
  • ➖ Requires threading template data through model initialization and configuration readers
  • ➖ Expands several internal function signatures
2. Unify plugin dependency rendering
  • ➕ Uses one Go-template syntax for configuration and dependency manifests
  • ➕ Eliminates deprecated string replacement for Backstage names
  • ➕ Allows platform conditions and substitutions in the same rendering phase
  • ➖ Requires migrating existing plugin dependency manifests
  • ➖ Needs careful compatibility handling for unrelated brace-based templates
3. Use the cluster-local OKP Service
  • ➕ Avoids ingress-domain coupling and external router traversal
  • ➕ Supports a narrower network policy and direct port 8080 traffic
  • ➕ Provides a clearer path toward Kubernetes support
  • ➖ May not satisfy consumers that require the externally routed endpoint
  • ➖ Still requires solving authenticated image access outside OpenShift

Recommendation: The templating and platform-gating strategy is appropriate for this POC, but productionization should replace the package-global templateData with reconcile-scoped data passed explicitly. The current global can be overwritten by concurrent Backstage reconciliations. A follow-up should also migrate plugin dependencies to the same renderer and prefer the cluster-local OKP Service unless external routing is required.

Files changed (39) +1699 / -380

Enhancement (11) +560 / -202
rhdh-flavour-intelligent-assistant-config_v1_configmap.yamlRegenerate the Intelligent Assistant flavour bundle +192/-113

Regenerate the Intelligent Assistant flavour bundle

• Embeds the Llama Stack profile, platform-conditional OKP configuration, hardened Lightspeed Core deployment, expanded plugin wiring, and OKP egress policy in the generated flavour ConfigMap.

bundle/rhdh/manifests/rhdh-flavour-intelligent-assistant-config_v1_configmap.yaml

configmap-files.yamlConfigure Llama Stack and conditional OKP retrieval +122/-30

Configure Llama Stack and conditional OKP retrieval

• Adds an OGX Llama Stack profile and switches Lightspeed Core to load it. Enables OKP retrieval only on OpenShift and escapes nested prompt placeholders so Go rendering preserves them.

config/profile/rhdh/default-config/flavours/intelligent-assistant/configmap-files.yaml

deployment.yamlHarden Lightspeed Core and remove bundled RAG initialization +21/-36

Harden Lightspeed Core and remove bundled RAG initialization

• Removes the RAG content init container and obsolete storage variables. Adds a restricted security context, writable temporary storage, Hugging Face cache location, and an OpenShift-specific OKP endpoint.

config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml

dynamic-plugins.yamlWire Intelligent Assistant UI and OKP dependency +39/-2

Wire Intelligent Assistant UI and OKP dependency

• Defines frontend routes, translations, providers, and drawer mount points. Adds the OKP backend dependency conditionally on OpenShift and enables the guest authentication backend module.

config/profile/rhdh/default-config/flavours/intelligent-assistant/dynamic-plugins.yaml

plugin-deps.goPass platform information into dependency resolution +1/-1

Pass platform information into dependency resolution

• Forwards the reconciler's platform extension when resolving plugin dependency resources.

internal/controller/plugin-deps.go

default-config.goRender templates before merging default configuration +31/-13

Render templates before merging default configuration

• Applies RHDH-aware Go templates to every base and flavour source before merging. Adds an explicit noMerge strategy that preserves base-only behavior and platform patches.

pkg/model/default-config.go

externalconfig.goExpose the ingress domain to templates +5/-0

Expose the ingress domain to templates

• Adds an accessor for the OpenShift ingress domain used by the template data interface.

pkg/model/externalconfig.go

plugin_deps.goFilter plugin dependencies by target platform +44/-7

Filter plugin dependencies by target platform

• Adds platform annotation filtering while retaining resources without an annotation on every platform. Threads the platform extension through dependency loading and marks legacy placeholder replacement as deprecated.

pkg/model/plugin_deps.go

runtime.goInitialize configuration template data during reconciliation +4/-0

Initialize configuration template data during reconciliation

• Populates template values from the Backstage resource, detected platform, and external cluster configuration before runtime objects are initialized.

pkg/model/runtime.go

platform.goExpose the platform extension to templates +5/-0

Expose the platform extension to templates

• Adds an accessor returning the platform's ocp or k8s extension.

pkg/platform/platform.go

template.goAdd RHDH-aware Go template rendering +96/-0

Add RHDH-aware Go template rendering

• Introduces template data interfaces and rendering for instance identity, platform, and ingress domain. Rendering is skipped when data is unavailable or content does not reference RHDH template fields.

pkg/template/template.go

Refactor (9) +8 / -31
db-secret.goApply explicit base-only merging to database secrets +1/-1

Apply explicit base-only merging to database secrets

• Registers database secret configuration with the shared noMerge policy instead of a nil merge function.

pkg/model/db-secret.go

db-service.goApply explicit base-only merging to database services +1/-1

Apply explicit base-only merging to database services

• Registers database service configuration with the shared noMerge policy.

pkg/model/db-service.go

db-statefulset.goApply explicit base-only merging to database workloads +1/-1

Apply explicit base-only merging to database workloads

• Registers database StatefulSet configuration with the shared noMerge policy.

pkg/model/db-statefulset.go

pvcs.goApply explicit base-only merging to PVCs +1/-1

Apply explicit base-only merging to PVCs

• Registers persistent volume claim configuration with the shared noMerge policy.

pkg/model/pvcs.go

route.goApply explicit base-only merging to routes +1/-1

Apply explicit base-only merging to routes

• Registers route configuration with the shared noMerge policy.

pkg/model/route.go

secretenvs.goApply explicit base-only merging to environment secrets +1/-1

Apply explicit base-only merging to environment secrets

• Registers environment secret configuration with the shared noMerge policy.

pkg/model/secretenvs.go

secretfiles.goApply explicit base-only merging to file secrets +1/-1

Apply explicit base-only merging to file secrets

• Registers file secret configuration with the shared noMerge policy.

pkg/model/secretfiles.go

service.goApply explicit base-only merging to services +1/-1

Apply explicit base-only merging to services

• Registers Backstage service configuration with the shared noMerge policy.

pkg/model/service.go

utils.goRemove the superseded YAML file reader +0/-23

Remove the superseded YAML file reader

• Removes ReadYamlFiles now that default configuration loading performs templating and platform patch handling through the model layer.

pkg/utils/utils.go

Tests (10) +570 / -24
default-config_test.goDisable flavours for raw default-config integration test +1/-0

Disable flavours for raw default-config integration test

• Explicitly supplies an empty flavour list because the test's raw deployment does not contain Intelligent Assistant containers.

integration_tests/default-config_test.go

rhdh-config_test.goUpdate integration expectations after RAG removal +5/-12

Update integration expectations after RAG removal

• Changes the expected init-container count and removes assertions for the retired init-rag-data container.

integration_tests/rhdh-config_test.go

default-config_test.goTest templating in base and flavour configs +72/-0

Test templating in base and flavour configs

• Verifies instance name and namespace substitution in default configuration and enabled flavour sources.

pkg/model/default-config_test.go

plugin_deps_test.goTest platform-gated plugin dependencies +140/-8

Test platform-gated plugin dependencies

• Updates dependency reader calls for the platform parameter and covers OpenShift-only, Kubernetes-only, unannotated, and empty-platform behavior.

pkg/model/plugin_deps_test.go

configmap-envs.yamlAdd base template substitution fixtures +2/-0

Add base template substitution fixtures

• Adds test values referencing the RHDH instance name and namespace.

pkg/model/testdata/testflavours/default-config/configmap-envs.yaml

configmap-envs.yamlAdd flavour template substitution fixture +1/-0

Add flavour template substitution fixture

• Adds a flavour value derived from the templated RHDH instance name.

pkg/model/testdata/testflavours/default-config/flavours/flavor1/configmap-envs.yaml

template_test.goTest template substitution, conditions, and escaping +298/-0

Test template substitution, conditions, and escaping

• Covers basic and runtime substitution, platform conditionals, untouched non-RHDH patterns, missing data, dynamic plugin dependencies, and escaped nested braces.

pkg/template/template_test.go

test_helpers.goProvide mock template data sources +32/-0

Provide mock template data sources

• Adds mock Backstage, platform, and external configuration implementations used by template and model tests.

pkg/template/test_helpers.go

configmap-template.yamlAdd a templated ConfigMap fixture +7/-0

Add a templated ConfigMap fixture

• Provides name, namespace, and service URL placeholders for renderer tests.

pkg/template/testdata/configmap-template.yaml

utils_test.goTest platform patches through lower-level YAML helpers +12/-4

Test platform patches through lower-level YAML helpers

• Updates platform patch tests to load the source manifest and patch explicitly before calling ReadYamls.

pkg/utils/utils_test.go

Documentation (2) +49 / -8
configuration.mdDocument flavour merge ordering and support +48/-7

Document flavour merge ordering and support

• Documents deterministic base-first flavour ordering, supported configuration objects, and the multi-object, package-based, deployment, and base-only merge policies.

docs/configuration.md

interfaces.goClarify base-only merge registration +1/-1

Clarify base-only merge registration

• Updates ObjectConfig documentation to require the explicit noMerge strategy for configuration types without flavour support.

pkg/model/interfaces.go

Other (7) +512 / -115
backstage-operator.clusterserviceversion.yamlRefresh Backstage bundle creation timestamp +1/-1

Refresh Backstage bundle creation timestamp

• Updates the generated Backstage ClusterServiceVersion timestamp for the rebuilt bundle.

bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml

backstage-operator.clusterserviceversion.yamlRefresh RHDH bundle creation timestamp +1/-1

Refresh RHDH bundle creation timestamp

• Updates the generated RHDH ClusterServiceVersion timestamp for the rebuilt bundle.

bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml

rhdh-plugin-deps_v1_configmap.yamlBundle the OKP plugin dependency resources +99/-0

Bundle the OKP plugin dependency resources

• Adds the generated OKP Deployment, OpenShift Route, and ClusterIP Service manifests to the plugin dependency ConfigMap.

bundle/rhdh/manifests/rhdh-plugin-deps_v1_configmap.yaml

networkpolicy.yamlAllow Intelligent Assistant egress to OKP +20/-0

Allow Intelligent Assistant egress to OKP

• Adds an egress NetworkPolicy permitting selected Backstage pods to reach OKP over ports 80 and 8080.

config/profile/rhdh/default-config/flavours/intelligent-assistant/networkpolicy.yaml

kustomization.yamlInclude OKP and network policy configuration +2/-0

Include OKP and network policy configuration

• Adds the Intelligent Assistant NetworkPolicy and OKP dependency manifest to generated profile ConfigMaps.

config/profile/rhdh/kustomization.yaml

okp.yamlDefine the standalone OKP workload +98/-0

Define the standalone OKP workload

• Introduces a security-hardened OKP Deployment with HTTP and Solr endpoints, resource limits, a ClusterIP Service, and an edge-terminated OpenShift Route.

config/profile/rhdh/plugin-deps/okp.yaml

install.yamlRegenerate the consolidated RHDH installation manifest +291/-113

Regenerate the consolidated RHDH installation manifest

• Propagates the new Intelligent Assistant, OKP, plugin, deployment, and network policy configuration into the generated installation YAML.

dist/rhdh/install.yaml

@gazarenkov gazarenkov changed the title [POC] Config for replacing RAG IC with OKP on IA Config for replacing RAG IC with OKP on IA Sep 21, 2026
@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 🔗 Cross-repo conflicts (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Instances render another instance's config ✓ Resolved 🐞 Bug ≡ Correctness
Description
template.SetTemplateData writes the package-global templateData, while ReadDefaultConfig later
calls ApplyTemplate, which reads that same pointer without synchronization. When reconciliations
for two Backstage instances overlap, the later initialization can render the earlier instance's
configuration with the other instance's name, namespace, platform, or ingress domain.
Code

pkg/template/template.go[R29-30]

+// templateData holds the current template data for YAML processing.
+var templateData *TemplateData
Relevance

●● Moderate

Global mutable template state presents a credible concurrency risk, but this architectural concern
lacks close acceptance precedent.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Each reconciliation initializes template data before iterating runtime configurations, while every
configuration source is rendered later through the shared template package state. The global pointer
is written and read without synchronization, so overlapping reconciliations have both a data race
and cross-instance context replacement path.

pkg/model/runtime.go[166-168]
pkg/model/default-config.go[35-42]
pkg/template/template.go[29-46]
pkg/template/template.go[63-95]
internal/controller/backstage_controller.go[117-121]

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

## Issue description
Template context is stored in a package-global pointer, so overlapping reconciliations can overwrite each other's instance-specific values before configuration rendering completes.

## Fix Focus Areas
- pkg/template/template.go[29-47]
- pkg/model/runtime.go[166-168]
- pkg/model/default-config.go[35-42]

## Recommended Fix
Remove the mutable package-global template context. Construct `TemplateData` for each `InitObjects` invocation and pass it explicitly through `ReadDefaultConfig` to `ApplyTemplate` (or make it a receiver-owned immutable renderer), so every render uses its own reconciliation's data.

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



Remediation recommended

2. Readers cannot predict list merging 📘 Rule violation ✧ Quality
Description
The new Deployment Merge section says that flavour patches are applied sequentially but does not
identify the merge as deep or shallow or explain how lists are handled. When base and flavour
deployments both define nested fields or container lists, users cannot determine whether entries
combine or replace one another from this reference.
Code

docs/configuration.md[R413-415]

+**Deployment Merge:**
+- Deployment/StatefulSet configurations from base and flavours are merged
+- Flavour patches are applied sequentially to the base deployment
Relevance

●●● Strong

Recent documentation precedents accept clarifications that explicitly document configuration
semantics and unsupported merge behavior.

PR-#2824
PR-#1406

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 6 requires documentation for layered configuration to state deep-versus-shallow behavior and
list exceptions. The changed documentation only says deployments are merged and patches are
sequential, while the implementation delegates to merge2.MergeStrings with kyaml merge options.

Rule 6: Document configuration merge semantics explicitly
docs/configuration.md[413-415]
pkg/model/deployment.go[512-525]

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 deployment merge documentation gives ordering but omits the depth of the merge and the handling of lists and conflicting nested values.

## Fix Focus Areas
- docs/configuration.md[413-415]

## Recommended Fix
Document that deployment sources use the kyaml merge implementation, state whether nested mappings merge recursively, and describe how lists such as containers, environment variables, and volume mounts combine or replace earlier values.

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


3. Retrieval traffic crosses ingress unencrypted 🐞 Bug ⛨ Security
Description
OKP_SERVICE_URL points Lightspeed Core at an http:// ingress hostname instead of the available
in-namespace OKP Service. On OpenShift the Route explicitly allows insecure HTTP, so retrieval
traffic traverses the router without transport encryption and exposes an unauthenticated external
endpoint.
Code

config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml[R40-41]

+            - name: OKP_SERVICE_URL
+              value: "http://lightspeed-okp-{{.Rhdh.Name}}-{{.Rhdh.Namespace}}.{{.Rhdh.Runtime.IngressDomain}}"
Relevance

●●● Strong

Security finding identifies clear plaintext ingress traffic; internal ClusterIP routing is a
straightforward safer correction.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The deployment sends OKP requests to an HTTP ingress-domain URL, while the new Route permits
insecure HTTP and targets the OKP HTTP port. The same manifest already provides a matching ClusterIP
Service that can be addressed directly without traversing external ingress.

config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml[39-42]
config/profile/rhdh/plugin-deps/okp.yaml[66-78]
config/profile/rhdh/plugin-deps/okp.yaml[82-98]
config/profile/rhdh/default-config/flavours/intelligent-assistant/configmap-files.yaml[247-256]

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

## Issue description
Lightspeed Core accesses OKP through an HTTP OpenShift ingress route even though an in-namespace ClusterIP Service is created, exposing retrieval traffic to the ingress path without encryption.

## Fix Focus Areas
- config/profile/rhdh/default-config/flavours/intelligent-assistant/deployment.yaml[39-42]
- config/profile/rhdh/plugin-deps/okp.yaml[66-78]
- config/profile/rhdh/default-config/flavours/intelligent-assistant/networkpolicy.yaml[12-20]

## Recommended Fix
Set `OKP_SERVICE_URL` to the same-namespace ClusterIP Service, such as `http://lightspeed-okp-{{.Rhdh.Name}}:8080`, and remove the external Route if it is not independently required. If external access is required, separate it from the internal retrieval path and reject insecure Route traffic.

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


4. Kubernetes reconciliation can fail 📘 Rule violation ≡ Correctness
Description
okp.yaml declares an OpenShift Route without the rhdh.redhat.com/platform: ocp annotation,
while matchesPlatform treats unannotated dependency objects as applicable to every platform. When
custom plugin configuration enables the OKP/intelligent-assistant dependency on Kubernetes,
reconciliation applies the unsupported route.openshift.io/v1 object alongside its portable
Deployment and Service to a cluster where the Route CRD is unavailable.
Code

config/profile/rhdh/plugin-deps/okp.yaml[R66-69]

+apiVersion: route.openshift.io/v1
+kind: Route
+metadata:
+  name: lightspeed-okp-{{backstage-name}}
Relevance

●●● Strong

Missing platform annotation directly defeats the PR’s stated platform-gating intent and can apply an
unsupported Route on Kubernetes.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 11 requires reconciliation to skip optional kinds before API calls when their CRDs may be
absent, but the Route is explicitly an OpenShift API type whose metadata contains only a name
despite the OpenShift-only comment. The platform filter returns true when the annotation is absent,
and the reconciler applies every dependency object that survives that filter, proving that this
Route reaches Kubernetes when the dependency is enabled there.

Rule 11: Guard reconciliation logic on optional CRD existence
config/profile/rhdh/plugin-deps/okp.yaml[63-69]
pkg/model/plugin_deps.go[106-134]
internal/controller/plugin-deps.go[35-40]
pkg/model/plugin_deps.go[106-110]
pkg/model/plugin_deps.go[117-134]
internal/controller/plugin-deps.go[29-38]
config/profile/rhdh/plugin-deps/okp.yaml[63-80]
pkg/model/plugin_deps.go[102-135]
internal/controller/plugin-deps.go[26-39]
pkg/platform/platform.go[8-14]

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 OKP dependency's OpenShift Route lacks the platform annotation used by plugin-dependency filtering, so it is treated as applicable to Kubernetes and can reach clusters where the Route CRD is unavailable.

## Fix Focus Areas
- config/profile/rhdh/plugin-deps/okp.yaml[63-69]
- pkg/model/plugin_deps.go[117-135]

## Recommended Fix
Add `metadata.annotations.rhdh.redhat.com/platform: ocp` to the Route while leaving the portable Deployment and Service unannotated so they remain cross-platform. Add a test using the multi-document OKP manifest to verify that Kubernetes returns the Deployment and Service but excludes only the Route, then regenerate the bundle and distribution manifests.

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


View medium (2)
5. Standard platform blocks remain raw 🐞 Bug ≡ Correctness
Description
ApplyTemplate only recognizes selected conditional spellings such as {{- if, {{-if, and
{{if, returning content unchanged for valid Go-template forms like `{{ if eq
.Rhdh.Runtime.Platform "ocp" }}` or references with additional whitespace. A configuration author
using these forms leaves template directives in generated YAML or embedded application
configuration, so parsing can fail instead of applying the intended platform-specific block.
Code

pkg/template/template.go[R74-80]

+	if !strings.Contains(contentStr, "{{.Rhdh.") &&
+		!strings.Contains(contentStr, "{{ .Rhdh.") &&
+		!strings.Contains(contentStr, "{{- .Rhdh.") &&
+		!strings.Contains(contentStr, "{{-if ") &&
+		!strings.Contains(contentStr, "{{- if ") &&
+		!strings.Contains(contentStr, "{{if ") {
+		return content, nil
Relevance

●●● Strong

The guard omits valid spaced Go-template syntax, making this a deterministic local correctness fix.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The pre-parse guard returns raw bytes unless the content contains one of several exact conditional
substrings, including {{if  and {{- if  but not the ordinary spaced form {{ if . Although the
valid conditional contains .Rhdh., that check occurs only after the early return and therefore
cannot recover the skipped content; current tests cover only the recognized trim-marker form.

pkg/template/template.go[63-87]
pkg/template/template_test.go[135-255]
pkg/template/template.go[70-85]
pkg/template/template_test.go[135-158]
pkg/template/template_test.go[220-236]

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 pre-parser heuristic recognizes only a narrow set of whitespace spellings for conditional actions, causing valid Go templates that reference `.Rhdh.` runtime data to be skipped rather than rendered.

## Fix Focus Areas
- pkg/template/template.go[63-87]
- pkg/template/template_test.go[135-255]

## Recommended Fix
Replace the spelling-specific conditional checks with a single detector for `.Rhdh.` before parsing the content with `text/template`, so forms such as `{{ if ... }}`, trim-marker variants, and references with additional whitespace are rendered. Add tests for those variants while retaining coverage for existing escaped non-RHDH braces.

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


6. Guest authentication may fail to load 🔗 Cross-repo conflict ≡ Correctness
Description
The Intelligent Assistant flavour enables the guest-provider overlay tagged next__0.2.20, while
the pinned RHDH repository consistently deploys the Backstage 1.52-compatible bs_1.52.0__0.2.20
artifact. Enabling this default flavour can therefore install an overlay built for a different
Backstage dependency set into the RHDH operand.
Code

config/profile/rhdh/default-config/flavours/intelligent-assistant/dynamic-plugins.yaml[R48-49]

+      - package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-auth-backend-module-guest-provider:next__0.2.20
+        enabled: true
Relevance

●● Moderate

Version alignment concern is plausible, but repository history lacks a close precedent about next
versus Backstage-pinned overlays.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR introduces the moving next overlay tag, whereas both RHDH's normal CI deployment values and
its local dynamic-plugin harness pin the guest provider to the Backstage 1.52-specific artifact. The
RHDH backend dependency list also establishes the operand's concrete guest-provider dependency
version rather than a moving next dependency set.

config/profile/rhdh/default-config/flavours/intelligent-assistant/dynamic-plugins.yaml[42-49]
External repo: redhat-developer/rhdh, .ci/pipelines/value_files/values_showcase.yaml [19-25]
External repo: redhat-developer/rhdh, e2e-tests/local-harness/dynamic-plugins.yaml [70-77]
External repo: redhat-developer/rhdh, packages/backend/package.json [28-38]

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 Intelligent Assistant flavour selects the moving `next__0.2.20` guest-provider overlay, but the pinned RHDH application uses and tests the `bs_1.52.0__0.2.20` build. Align the operator default with the artifact built for the operand's Backstage version.

## Fix Focus Areas
- config/profile/rhdh/default-config/flavours/intelligent-assistant/dynamic-plugins.yaml[48-49]
- bundle/rhdh/manifests/rhdh-flavour-intelligent-assistant-config_v1_configmap.yaml[348-350]
- dist/rhdh/install.yaml[3834-3835]

## Recommended Fix
Replace `next__0.2.20` with `bs_1.52.0__0.2.20`, regenerate the bundle and distribution manifests, and verify the selected tag remains aligned whenever the RHDH operand's Backstage version changes.

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


Grey Divider

Context sources
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 18 rules
✅ Cross-repo context — repo relationships
  Explored: repo: redhat-developer/rhdh (sha: 023f4f28)
  Explored: repo: redhat-developer/rhdh-adr (sha: 02b1e659)
  Explored: repo: redhat-developer/rhdh-plugins (sha: e4402238)
  Explored: repo: redhat-developer/rhdh-chart (sha: 0c6b4aa1)
Review mode: 🧠 Deep: This broad, behavior-changing PR spans templating, platform-gated resource deployment, Kubernetes manifests, plugin dependencies, and runtime configuration across many independent code paths with substantial defect density.

Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread pkg/template/template.go Outdated
@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Tests labels Sep 21, 2026
@rhdh-qodo-merge

Copy link
Copy Markdown

Important

The /generate_labels command by Qodo is sunsetting on the 1st of October 2026 and will no longer be available. We recommend switching to the latest Qodo review capabilities. Learn more

@openshift-ci openshift-ci Bot removed the lgtm label Sep 22, 2026
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.0.0-pr-3477-4489af8 quay.io/rhdh-community/operator:2.0.0-pr-3477
Bundle quay.io/rhdh-community/operator-bundle:2.0.0-pr-3477-4489af8 quay.io/rhdh-community/operator-bundle:2.0.0-pr-3477
Catalog quay.io/rhdh-community/operator-catalog:2.0.0-pr-3477-4489af8 quay.io/rhdh-community/operator-catalog:2.0.0-pr-3477

Comment on lines +11 to +40
pluginConfig:
dynamicPlugins:
frontend:
red-hat-developer-hub.backstage-plugin-intelligent-assistant:
translationResources:
- importName: lightspeedTranslations
module: Alpha
ref: intelligentAssistantTranslationRef
dynamicRoutes:
- path: /intelligent-assistant
importName: LightspeedPage
module: Legacy
mountPoints:
- mountPoint: application/listener
importName: LightspeedFAB
module: Legacy
- mountPoint: application/provider
importName: LightspeedDrawerProvider
module: Legacy
- mountPoint: application/internal/drawer-state
importName: LightspeedDrawerStateExposer
module: Legacy
config:
id: intelligent-assistant
- mountPoint: application/internal/drawer-content
importName: LightspeedChatContainer
module: Legacy
config:
id: intelligent-assistant
priority: 100

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
pluginConfig:
dynamicPlugins:
frontend:
red-hat-developer-hub.backstage-plugin-intelligent-assistant:
translationResources:
- importName: lightspeedTranslations
module: Alpha
ref: intelligentAssistantTranslationRef
dynamicRoutes:
- path: /intelligent-assistant
importName: LightspeedPage
module: Legacy
mountPoints:
- mountPoint: application/listener
importName: LightspeedFAB
module: Legacy
- mountPoint: application/provider
importName: LightspeedDrawerProvider
module: Legacy
- mountPoint: application/internal/drawer-state
importName: LightspeedDrawerStateExposer
module: Legacy
config:
id: intelligent-assistant
- mountPoint: application/internal/drawer-content
importName: LightspeedChatContainer
module: Legacy
config:
id: intelligent-assistant
priority: 100

Not a blocker, but do we really need to redefine the pluginConfig here? It should be inherited from the default config, no?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not a big deal, can be addressed later if needed.

@openshift-ci openshift-ci Bot added the lgtm label Sep 22, 2026
@rm3l rm3l changed the title Config for replacing RAG IC with OKP on IA feat: Config for replacing RAG IC with OKP on IA Sep 22, 2026
@rm3l
rm3l merged commit 91e7712 into redhat-developer:main Sep 22, 2026
10 checks passed
@gazarenkov
gazarenkov deleted the improve-parametrization branch October 1, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request lgtm Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants