Skip to content

feat(lightspeed): replace RAG init container with OKP deployment - #3370

Open
maysunfaisal wants to merge 4 commits into
redhat-developer:mainfrom
maysunfaisal:okp-integration-1
Open

feat(lightspeed): replace RAG init container with OKP deployment #3370
maysunfaisal wants to merge 4 commits into
redhat-developer:mainfrom
maysunfaisal:okp-integration-1

Conversation

@maysunfaisal

@maysunfaisal maysunfaisal commented Aug 18, 2026

Copy link
Copy Markdown

Description

Replace the Lightspeed RAG init container / FAISS vector store with an OKP (Offline Knowledge Portal) backend and swap the Lightspeed dynamic plugins to the Intelligent Assistant plugins.

OKP deployment

  • Add OKP as an operator-managed Deployment, Service, and Route (Solr 8983 + httpd 8080) — new internal/controller/okp.go, wired in backstage_controller.go.
  • Gated on OpenShift. Vanilla K8s swaps in lightspeed-stack-no-okp.yaml so LCORE does not crash without an OKP backend (operator has no Ingress support — RHDHPLAN-423/RHIDP-2176).
  • Inject OKP_SERVICE_URL into the lightspeed-core sidecar before applying objects, avoiding a dual-ReplicaSet rollout.

Plugin swap (Intelligent Assistant)

  • Default lightspeed flavour plugins → oci://quay.io/rhdh/red-hat-developer-hub-backstage-plugin-intelligent-assistant(-backend):{{inherit}}, enabled: true; FE carries the full pluginConfig (dynamicRoutes/mountPoints).
  • Uses quay.io/rhdh (not registry.access.redhat.com) to match the operator's CATALOG_INDEX_IMAGE + RHDH image, so {{inherit}} resolves at the container level (install-dynamic-plugins).

Config & images

  • Align the LCORE sidecar with the OGX image, add HF_HOME + --synthesized-config-output for read-only rootfs, and pin the OKP image to registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:1.2.10-1786628394.
  • Sync vendored Lightspeed configs from lightspeed-configs@main (hack/sync-lightspeed-configs.sh).
  • Regenerate dist/rhdh/install.yaml + bundle/rhdh/manifests/rhdh-flavour-lightspeed-config_v1_configmap.yaml.

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

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

PR acceptance criteria

  • Tests
  • Documentation

How to test changes / Special notes to the reviewer

On OpenShift:

  1. Deploy the operator: make deploy IMG=<operator-image> PROFILE=rhdh
  2. Create the Lightspeed secret with your inference key (e.g. OPENAI_API_KEY) — see examples/lightspeed.yaml.
  3. Apply a Backstage CR with the lightspeed flavour enabled and the secret wired into the lightspeed-core container.
  4. Verify:
    • developer-hub pod 2/2 Running; OKP Deployment/Service/Route 1/1 Running.
    • OKP_SERVICE_URL + HF_HOME injected into the lightspeed-core sidecar; LCORE GET /v1/models returns 200.
    • IA FE/BE plugins resolve via {{inherit}} (digests match the RHDH image's catalog).
    • Intelligent Assistant UI: general chat returns OKP RAG sources; Notebooks answers from an uploaded doc.

On vanilla K8s: OKP is skipped, lightspeed-stack-no-okp.yaml is used, and LCORE starts without crashing.

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.

@maysunfaisal
maysunfaisal requested review from a team as code owners August 18, 2026 19:16
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 72.02381% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.74%. Comparing base (df52c5a) to head (b8ae9d6).

Files with missing lines Patch % Lines
pkg/model/runtime.go 48.64% 14 Missing and 5 partials ⚠️
internal/controller/okp.go 23.52% 13 Missing ⚠️
pkg/model/flavour.go 0.00% 8 Missing ⚠️
pkg/model/okp.go 73.68% 5 Missing ⚠️
internal/controller/backstage_controller.go 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3370      +/-   ##
==========================================
+ Coverage   65.31%   65.74%   +0.42%     
==========================================
  Files          38       43       +5     
  Lines        2465     2633     +168     
==========================================
+ Hits         1610     1731     +121     
- Misses        705      747      +42     
- Partials      150      155       +5     
Flag Coverage Δ
nightly ?
unittests 65.74% <72.02%> (+0.42%) ⬆️

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

Files with missing lines Coverage Δ
pkg/model/okp-deployment.go 100.00% <100.00%> (ø)
pkg/model/okp-route.go 100.00% <100.00%> (ø)
pkg/model/okp-service.go 100.00% <100.00%> (ø)
internal/controller/backstage_controller.go 0.00% <0.00%> (ø)
pkg/model/okp.go 73.68% <73.68%> (ø)
pkg/model/flavour.go 66.12% <0.00%> (-9.80%) ⬇️
internal/controller/okp.go 23.52% <23.52%> (ø)
pkg/model/runtime.go 67.17% <48.64%> (-7.30%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maysunfaisal
maysunfaisal force-pushed the okp-integration-1 branch 2 times, most recently from 51db81c to 3bbec01 Compare August 18, 2026 20:51
Comment thread docs/lightspeed.md Outdated
Comment thread internal/controller/okp.go Outdated
selectorLabels := okpSelectorLabels(backstage.Name)

// OKP Deployment
deployment := &appsv1.Deployment{

@michael-valdron michael-valdron Aug 18, 2026

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.

@maysunfaisal Though I'll mostly let the @redhat-developer/rhdh-install team comment on the operator source changes I'll make one comment on this part.

It makes sense to have controller parsing for OpenShift only parts, I wondering if it would be better to have the OKP deployment specification either in a OKP flavour or a separate OKP deployment specification within the lightspeed (intelligent-assistant) flavour that this controller source parses?

I'm considering the different non-lightspeed flavours users and customers may use as well as any automated patching that may be used here (i.e. patching the OKP image).

fyi @gazarenkov @rm3l

@maysunfaisal maysunfaisal Aug 18, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Valid concern @michael-valdron

Midstream digest-pinning scans YAML manifests, not Go source, so it would miss the OKP image ref in okp.go. A couple of things worth noting:

  • OKP is already lightspeed-only at runtime — applyOkpResources gates on IsFlavourEnabled("lightspeed") && IsOpenshift(), so non-lightspeed users get zero OKP resources today. That said, having it described declaratively in the flavour is cleaner.
  • The move is non-trivial:
    • the operator's config kinds (deployment, service, route) are singletons tied to the main RHDH app, so OKP would need new registered kinds + factories. The existing .ocp/.k8s suffix mechanism also doesn't handle "create-or-skip-entirely" gating, so some Go code will still be needed for the
      OpenShift-only conditional logic.

I'm going to explore options on how best to approach this. Would appreciate any suggestions or guidance from @gazarenkov / @rm3l on the preferred pattern for flavour-owned sidecar resources.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@michael-valdron

The OKP Deployment/Service/Route are now defined in the lightspeed flavour YAML (config/profile/rhdh/default-config/flavours/lightspeed/okp-*.yaml) and applied via the normal model path, rather than constructed imperatively in okp.go.

Each is a separately registered key, still gated to OpenShift. The only bit kept in Go is injecting OKP_SERVICE_URL into the lightspeed-core sidecar, since that value is computed at runtime (CR name/namespace + ingress domain) and can't be a static YAML env. This also means the OKP image string now rides in the bundle ConfigMap, so midstream image pinning can see it.

@maysunfaisal

Copy link
Copy Markdown
Author

Corresponding rhdh-chart PR redhat-developer/rhdh-chart#500

maysunfaisal added a commit to maysunfaisal/rhdh-operator that referenced this pull request Aug 21, 2026
Move the OKP (Offline Knowledge Portal) Deployment, Service, and Route
out of imperative Go construction in internal/controller/okp.go and into
the lightspeed flavour as YAML manifests, so OKP is described like every
other flavour resource and its image string rides in the bundle
ConfigMap (visible to midstream image pinning). Addresses PR redhat-developer#3370
review comment: "should OKP be in the flavour YAML rather than Go?".

Each OKP object is a separately registered model key (OkpDeploymentKey,
OkpServiceKey, OkpRouteKey) with its own MergeFunc, and stays gated to
OpenShift in addToModel. Flavour gating is implicit (files live only in
flavours/lightspeed/). The runtime behavior is unchanged: same objects,
same OpenShift-only gating, same OKP_SERVICE_URL injection into the
lightspeed-core sidecar before apply (no dual ReplicaSet).

Remove applyOkpResources; OKP now flows through the normal
applyObjects(GetRuntimeObjects()) SSA path. Keep prepareOkpEnvVar and
prepareOkpConfig as controller wiring. Regenerate bundle manifests and
dist/rhdh/install.yaml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maysunfaisal added a commit to maysunfaisal/rhdh-operator that referenced this pull request Aug 21, 2026
Move the OKP (Offline Knowledge Portal) Deployment, Service, and Route
out of imperative Go construction in internal/controller/okp.go and into
the lightspeed flavour as YAML manifests, so OKP is described like every
other flavour resource and its image string rides in the bundle
ConfigMap (visible to midstream image pinning). Addresses PR redhat-developer#3370
review comment: "should OKP be in the flavour YAML rather than Go?".

Each OKP object is a separately registered model key (OkpDeploymentKey,
OkpServiceKey, OkpRouteKey) with its own MergeFunc, and stays gated to
OpenShift in addToModel. Flavour gating is implicit (files live only in
flavours/lightspeed/). The runtime behavior is unchanged: same objects,
same OpenShift-only gating, same OKP_SERVICE_URL injection into the
lightspeed-core sidecar before apply (no dual ReplicaSet).

Remove applyOkpResources; OKP now flows through the normal
applyObjects(GetRuntimeObjects()) SSA path. Keep prepareOkpEnvVar and
prepareOkpConfig as controller wiring. Regenerate bundle manifests and
dist/rhdh/install.yaml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rm3l

rm3l commented Aug 24, 2026

Copy link
Copy Markdown
Member

/build-images

@github-actions

Copy link
Copy Markdown
Contributor

Image build failed

See workflow run for details: https://github.com/redhat-developer/rhdh-operator/actions/runs/32705736214

Triggered by @rm3l

@rm3l

rm3l commented Aug 24, 2026

Copy link
Copy Markdown
Member

/build-images

@github-actions

Copy link
Copy Markdown
Contributor

Image build failed

See workflow run for details: https://github.com/redhat-developer/rhdh-operator/actions/runs/32705962118

Triggered by @rm3l

maysunfaisal added a commit to maysunfaisal/rhdh-operator that referenced this pull request Aug 24, 2026
Move the OKP (Offline Knowledge Portal) Deployment, Service, and Route
out of imperative Go construction in internal/controller/okp.go and into
the lightspeed flavour as YAML manifests, so OKP is described like every
other flavour resource and its image string rides in the bundle
ConfigMap (visible to midstream image pinning). Addresses PR redhat-developer#3370
review comment: "should OKP be in the flavour YAML rather than Go?".

Each OKP object is a separately registered model key (OkpDeploymentKey,
OkpServiceKey, OkpRouteKey) with its own MergeFunc, and stays gated to
OpenShift in addToModel. Flavour gating is implicit (files live only in
flavours/lightspeed/). The runtime behavior is unchanged: same objects,
same OpenShift-only gating, same OKP_SERVICE_URL injection into the
lightspeed-core sidecar before apply (no dual ReplicaSet).

Remove applyOkpResources; OKP now flows through the normal
applyObjects(GetRuntimeObjects()) SSA path. Keep prepareOkpEnvVar and
prepareOkpConfig as controller wiring. Regenerate bundle manifests and
dist/rhdh/install.yaml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maysunfaisal

Copy link
Copy Markdown
Author

/build-images

@github-actions

Copy link
Copy Markdown
Contributor

PR images built successfully!

Images are available for testing:

  1. Operator: quay.io/rhdh-community/operator:2.0.0-pr-3370-9726670
  2. Bundle: quay.io/rhdh-community/operator-bundle:2.0.0-pr-3370-9726670
  3. Catalog: quay.io/rhdh-community/operator-catalog:2.0.0-pr-3370-9726670

Also available with PR number tag:

  • quay.io/rhdh-community/operator:2.0.0-pr-3370
  • quay.io/rhdh-community/operator-bundle:2.0.0-pr-3370
  • quay.io/rhdh-community/operator-catalog:2.0.0-pr-3370

Triggered by @maysunfaisal

@Jdubrick Jdubrick 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.

Just a general question as well: will OKP get cleaned up if someone disables the lightspeed flavour?

Comment thread config/profile/rhdh/default-config/flavours/lightspeed/dynamic-plugins.yaml Outdated
Comment thread docs/lightspeed.md Outdated
Comment thread docs/lightspeed.md Outdated
@rm3l

rm3l commented Aug 26, 2026

Copy link
Copy Markdown
Member

/cc @gazarenkov

@openshift-ci
openshift-ci Bot requested a review from gazarenkov August 26, 2026 13:13
@maysunfaisal

Copy link
Copy Markdown
Author

/build-images

@github-actions

Copy link
Copy Markdown
Contributor

PR images built successfully!

Images are available for testing:

  1. Operator: quay.io/rhdh-community/operator:2.0.0-pr-3370-ec0b6e3
  2. Bundle: quay.io/rhdh-community/operator-bundle:2.0.0-pr-3370-ec0b6e3
  3. Catalog: quay.io/rhdh-community/operator-catalog:2.0.0-pr-3370-ec0b6e3

Also available with PR number tag:

  • quay.io/rhdh-community/operator:2.0.0-pr-3370
  • quay.io/rhdh-community/operator-bundle:2.0.0-pr-3370
  • quay.io/rhdh-community/operator-catalog:2.0.0-pr-3370

Triggered by @maysunfaisal

@gazarenkov gazarenkov 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.

To add the additional resources needed for your plugin please use Plugin dependencies feature instead.

You can see how it implemented in orchestrator flavour as well (it uses sonataflow dependencies).

@maysunfaisal

maysunfaisal commented Aug 27, 2026

Copy link
Copy Markdown
Author

To add the additional resources needed for your plugin please use Plugin dependencies feature instead.

You can see how it implemented in orchestrator flavour as well (it uses sonataflow dependencies).

Thanks @gazarenkov, looked into plugin-deps for OKP. Our manifests are already declarative YAML, not imperative Go:

config/profile/rhdh/default-config/flavours/lightspeed/
  okp-deployment.yaml
  okp-service.yaml
  okp-route.yaml

The Go wrappers (pkg/model/okp-*.go) only add metadata + platform gating. okp.go creates nothing and it just handles two things plugin-deps can't:

  1. OpenShift gating — OKP uses a Route, which doesn't exist on vanilla K8s. LCORE also crashes if rag/okp config is present but Solr is unreachable, so the operator must strip those config sections on non-OpenShift. Plugin-deps applies unconditionally.

  2. OKP_SERVICE_URL injection — LCORE needs to know where OKP lives. The URL is built at runtime from the CR name + cluster ingress domain (e.g. http://lightspeed-okp-<name>-<ns>.<domain>), then injected into the LCORE container env. Plugin-deps only creates standalone resources — it can't modify another container's env.

plugin-deps OKP needs
Platform gating No Skip all 3 resources on vanilla K8s
Env injection into another container No OKP_SERVICE_URL → LCORE
Config swap by platform No Strip rag/okp on K8s

Orchestrator's sonataflow deps are standalone resources, no cross-container wiring or platform gating needed. OKP needs both.

Open to discussion if there's a path to extend plugin-deps for these cases!

maysunfaisal and others added 4 commits August 28, 2026 16:38
…DP-16103]

Remove the init-rag-data init container and FAISS vector store from the
lightspeed flavour. Add OKP (Offline Knowledge Portal) as a Deployment,
Service, and Route managed by the operator, gated on OpenShift; vanilla
K8s swaps in the lightspeed-stack-no-okp.yaml config to avoid LCORE
crashing without an OKP backend. Inject OKP_SERVICE_URL into the
lightspeed-core sidecar before applying objects to avoid a dual
ReplicaSet rollout. Align the LCORE sidecar with the OGX image and pin
the OKP image. Sync vendored Lightspeed configs from
lightspeed-configs@main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the OKP (Offline Knowledge Portal) Deployment, Service, and Route
out of imperative Go construction in internal/controller/okp.go and into
the lightspeed flavour as YAML manifests, so OKP is described like every
other flavour resource and its image string rides in the bundle
ConfigMap (visible to midstream image pinning). Addresses PR redhat-developer#3370
review comment: "should OKP be in the flavour YAML rather than Go?".

Each OKP object is a separately registered model key (OkpDeploymentKey,
OkpServiceKey, OkpRouteKey) with its own MergeFunc, and stays gated to
OpenShift in addToModel. Flavour gating is implicit (files live only in
flavours/lightspeed/). The runtime behavior is unchanged: same objects,
same OpenShift-only gating, same OKP_SERVICE_URL injection into the
lightspeed-core sidecar before apply (no dual ReplicaSet).

Remove applyOkpResources; OKP now flows through the normal
applyObjects(GetRuntimeObjects()) SSA path. Keep prepareOkpEnvVar and
prepareOkpConfig as controller wiring. Regenerate bundle manifests and
dist/rhdh/install.yaml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ext, docs [RHIDP-16103]

Switch IA plugin references from oci://...inherit to ref:// pattern
(per rm3l review, rhdh#5204). Add OTEL_SDK_DISABLED=true to LCORE env
to prevent crash when OTEL collector unreachable. Add securityContext to
LCORE and OKP containers matching the operator RHDH deployment precedent.
Update docs: remove inherit note, add accuracy caveat for vanilla K8s
without OKP knowledge base.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…RHIDP-16103]

Bundle and dist regeneration after rebasing onto main (intelligent-assistant
rebranding). Fix .npmrc integration test init container count (2→1) since
OKP replaces the RAG init container.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@gazarenkov

gazarenkov commented Sep 1, 2026

Copy link
Copy Markdown
Member

Thanks for explanations, @maysunfaisal

I think I understand your point and it tells me that we probably would need a bit improve the framework to:

  • have platform gating in plugin-deps
  • make it possible to inject env vars and mount files using not only static resources name but templating it like "my-service-<cr-name>"

But before going to it, I would like to understand why it is important in this concrete case. Please correct me if I am wrong:

  • As I can see The OKP container (Solr + httpd) is "standard" and should work on any K8s.

  • The service provided by this container should be accessible internally, especially since in LCORE container is in the same namespace.

  • So, we create Deployment, Service and send via env var the URL to LCORE. Why do we need Openshift Route?

  • Question: Do we need OKP instance (Deployment, Service) per RHDH instance or it can be shared inside namespace? (just to understand how important is it, in practice several RHDH instances per workspace hardly needed in absolutely most cases)

@maysunfaisal

maysunfaisal commented Sep 1, 2026

Copy link
Copy Markdown
Author

Thanks for explanations, @maysunfaisal

[.. truncated ..]

  • Question: Do we need OKP instance (Deployment, Service) per RHDH instance or it can be shared inside namespace? (just to understand how important is it, in practice several RHDH instances per workspace hardly needed in absolutely most cases)

Thanks @gazarenkov, great questions. Let me address each (with Agentic help as it was used for rhdh-operator and rhdh-chart):

Why the Route?

OKP isn't just a backend for LCORE — it also serves the RAG reference pages that users click in the chat UI. When the Intelligent Assistant/Lightspeed chatbot returns grounded answers, the response includes clickable reference_urls (e.g. RHDH product docs). Those links point to OKP's httpd, which serves the indexed content. The user's browser needs to reach OKP to render those pages.

A ClusterIP Service is only reachable from within the cluster. The browser is outside — so without a Route (or Ingress), the reference links are dead.

Why OpenShift-only gating?

Two reasons:

  1. The OKP image (registry.redhat.io/offline-knowledge-portal/rhokp-rhel9) requires Red Hat registry auth. On OpenShift, the global pull secret handles this automatically. On vanilla K8s, users would need to manually configure imagePullSecrets — the chart supports this as an opt-in (okp.imagePullSecrets), but it's not a seamless default experience. On rhdh-local for example, users would need to podman login. (As to why RHOKP does not support a public image, you can read their justification here and it was brought up to them how this is not ideal. Mainly because of licenses and OKP image have RH Knowledge Base..)

  2. The operator currently has no Ingress support (tracked as RHDHPLAN-423 / RHIDP-2176). Without Ingress, there's no way to expose OKP externally on vanilla K8s. So OpenShift (Route) is the only viable path in the operator today.

On the chart side redhat-developer/rhdh-chart#500, we do support vanilla K8s as an opt-in — users set okp.ingress.host and it renders an Ingress instead of a Route.

One OKP per RHDH instance — temporary

Yes, currently each RHDH install provisions its own OKP Deployment. We've raised this with the OKP team and they have an epic for standalone installation: RHOKP-1632 with child stories for Helm (RHOKP-1690) and Operator (RHOKP-1691) deployment. Once those land, OKP can be independently installed and shared. We have had discussions about this in meeting with the RHOKP team and how it is not a great UX.

@gazarenkov

gazarenkov commented Sep 2, 2026

Copy link
Copy Markdown
Member

@maysunfaisal
Thanks for info

Route

Curious how UX of K8s vs Openshift end-users differs?

What if we provide Route based automation for Openshift users only and for K8s instruct that for this feature they have to configure the networking (ingress, loadbalancer etc) and provide it's URL manually?
This way Deployment and Service are functional in any platform but external assess requires additional actions in k8s

I see why we need this conditional deployment (at least for Route), let me think how to implement it better with plugin-deps (it should not be that complex I think)

OKP instances

I understand, deploying it independently makes sense in prod (however self-created instance is useful for quick start scenario). This way the only thing the plugin needed is URL (or 2 URLs: internal and external), no additional resources to create.

So, as the per-RHDH is not the point we can consider per-namespace (which in most cases the same), right?

@maysunfaisal

maysunfaisal commented Sep 2, 2026

Copy link
Copy Markdown
Author

@gazarenkov

Route

Yes, that's exactly how it works today in this PR. On OpenShift, the operator creates a Route automatically. On vanilla K8s, the operator does not create any networking resource because there is no Ingress support; the user would need to configure Ingress/LoadBalancer themselves and provide the URL. The Helm chart takes a similar approach where it auto-detects OpenShift for Route creation, and offers opt-in Ingress on K8s.

Regarding enhancing plugin-deps with platform gating and templated env injection, happy to refactor to use that once it's available, but I'd prefer not to block this PR on that future work unless the turn around time is 1 day or so. We are currently blocking on other 2.1 Feature work for Intelligent Assistant (this repo as @Jdubrick is putting some changes in + midstream Gitlab rhdh repo for pinning OKP digest image and removing the old RHDH RAG from Lightspeed) due to these PRs and we have one Sprint before 2.1 FF.

OKP instances

Per-CR is intentional as it keeps lifecycle simple since each CR owns its OKP and cleans it up on delete (at the cost of fist time quick start and resource consumption).

Per-namespace is possible without any bundle or midstream impact (the OKP resources stay in the flavour ConfigMap either way), but it adds reconciliation complexity: multiple Backstage CRs would race on the same OKP Deployment, and we'd need to coordinate who owns it and when to delete it.

If the goal is a shared, independently-managed OKP, the OKP team is working on that under RHOKP-1632, they also have OKP as MCP for Q4 on their agenda, so I am not trying to over-engineer how OKP is deployed right now, for what may seem to be temporary.

(This is also consistent with redhat-developer/rhdh-chart#500 where we have one RHDH/LCORE deployment and OKP deployment per helm release).

What are your thoughts?

@gazarenkov

Copy link
Copy Markdown
Member

@maysunfaisal
thanks for info

Based on our conversation I've identified the following framework enhancements we could implement:

  1. Templating support for default-config - make it possible to reference internal services per-instance, e.g. URL=http://okp-{{.Backstage.Name}}
  2. Plugin dependencies platform gating, can make it with dedicated annotation like rhdh.redhat.com/platform= to apply resources only on specific platforms

The only question I have for the time: where do we need to inject the Route-related URL to be used in frontend? My understanding it should be backstage container but as I can see you inject it to Lcore container. Thoughts?

but I'd prefer not to block this PR on that future work unless the turn around time is 1 day or so. We are currently blocking on other 2.1 Feature work for Intelligent Assistant

I am sorry to not to know about this approach earlier, the problem is that it introduces plugin-specific logic directly into the operator model, which isn't the direction we want to take, it is hardly supportable way. The operator should remain plugin-agnostic and provide generic mechanisms that any plugin can leverage.
To help to implement it ASAP I've created the Feature to track: https://redhat.atlassian.net/browse/RHDHPLAN-1763
I spent some time on it and think I can make a POC shortly and share to test with your config and see.

Thanks

@maysunfaisal

maysunfaisal commented Sep 3, 2026

Copy link
Copy Markdown
Author

@gazarenkov

The only question I have for the time: where do we need to inject the Route-related URL to be used in frontend? My understanding it should be backstage container but as I can see you inject it to Lcore container. Thoughts?

The ENV injection is happening to the LCORE container here in my changes https://github.com/redhat-developer/rhdh-operator/pull/3370/changes#diff-f16bc2e3b21ea94fe1e0cb23af92be4335ce36540bcef4c07d420c97067aeb6dR26 (internal/controller/okp.go - prepareOkpEnvVar())

This is relatively easy on rhdh-chart due to helm templating magic but i had to do this for Go operator.

The OKP deployment is separate from the RHDH/LCORE deployment; so we had to use the above approach to get the OKP Route endpoint and set it to OKP_SERVICE_URL into the lightspeed-core container (LCORE) because LCORE service needs to connect to OKP Service for RAG to work. Check out the gist for the Container Spec from when I had RHDH pod running from a redhat-developer/rhdh-chart#500 test i did earlier today with Armel reviews. Let me know if you have further questions about OKP_SERVICE_URL. Here are all the resources from the same rhdh-chart test for reference (it is similar for this PR):

$ oc get po,deploy,svc,route,secret -n rhdh-test
NAME                                                    READY   STATUS    RESTARTS   AGE
pod/rhdh-postgresql-0                                   1/1     Running   0          99m
pod/rhdh-redhat-developer-hub-5cc69f5c74-dz6xq          2/2     Running   0          41m
pod/rhdh-redhat-developer-hub-ia-okp-7fd8c74879-xxpmm   1/1     Running   0          99m

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rhdh-redhat-developer-hub          1/1     1            1           99m
deployment.apps/rhdh-redhat-developer-hub-ia-okp   1/1     1            1           99m

NAME                                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
service/rhdh-postgresql                    ClusterIP   172.30.202.197   <none>        5432/TCP            99m
service/rhdh-postgresql-hl                 ClusterIP   None             <none>        5432/TCP            99m
service/rhdh-redhat-developer-hub          ClusterIP   172.30.64.162    <none>        7007/TCP,9464/TCP   99m
service/rhdh-redhat-developer-hub-ia-okp   ClusterIP   172.30.67.118    <none>        8080/TCP            99m

NAME                                                        HOST/PORT                                                                                   PATH   SERVICES                           PORT           TERMINATION     WILDCARD
route.route.openshift.io/rhdh-redhat-developer-hub          rhdh-redhat-developer-hub-rhdh-test.apps.mfaisal-sep032026.rhdh-pai.devfile-ci.com          /      rhdh-redhat-developer-hub          http-backend   edge/Redirect   None
route.route.openshift.io/rhdh-redhat-developer-hub-ia-okp   rhdh-redhat-developer-hub-ia-okp-rhdh-test.apps.mfaisal-sep032026.rhdh-pai.devfile-ci.com          rhdh-redhat-developer-hub-ia-okp   httpd          edge/Allow      None

So, the RHDH plugin Intelligent Assistant frontend just renders what LCORE returns - OKP links pointing to RHDH docs in OKP Service. User is able to click them on the browser and see the RHDH docs from OKP service.

LCORE needs the OKP Route URL to construct the citation links on LCORE server-side.

I am sorry to not to know about this approach earlier, the problem is that it introduces plugin-specific logic directly into the operator model, which isn't the direction we want to take, it is hardly supportable way. The operator should remain plugin-agnostic and provide generic mechanisms that any plugin can leverage.

I understand the sentiment but Intelligent Assistant (IA, formerly Lightspeed) is now included by default OOTB as a flavor with upstream RHDH. Previously, Lightspeed used initContainers and volume mounts directly to RHDH deployment to set up RAG but that is now taken away and replaced by a standalone OKP Deployment/Svc/Route. From my POV, I was just plugging out and plugging in how RAG is set up. OKP resources are just dependencies of a default config Lightspeed/IA.

Maybe standalone OKP resources and platform gating is a deal breaker? But let me know how you feel about this and also about your progress on https://redhat.atlassian.net/browse/RHDHPLAN-1763 because I may have to react differently based on that decision like whether I can make OKP changes to upstream and midstream before FF 🤔

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.

6 participants