Skip to content

Commit c60a659

Browse files
Merge pull request #110 from umago/okp
Enable OKP support
2 parents 8faeaf1 + 93f533b commit c60a659

33 files changed

Lines changed: 1047 additions & 24 deletions

api/v1beta1/openstacklightspeed_types.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
2222
"k8s.io/apimachinery/pkg/api/resource"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/runtime"
2425
)
2526

2627
const (
@@ -45,10 +46,37 @@ const (
4546
// ConsoleContainerImagePF5 is the fall-back console image for PatternFly 5 (OCP < 4.19)
4647
ConsoleContainerImagePF5 = "registry.redhat.io/openshift-lightspeed/lightspeed-console-plugin-pf5-rhel9:1.0.12"
4748

49+
// OKPContainerImage is the fall-back container image for OKP (Offline Knowledge Portal)
50+
OKPContainerImage = "registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest"
51+
4852
// MaxTokensForResponseDefault is the default maximum number of tokens that should be used for response
4953
MaxTokensForResponseDefault = 2048
5054
)
5155

56+
// DevSpec is the internal structure for the Dev field. Not exposed in the CRD.
57+
// May change at any time without backward compatibility.
58+
type DevSpec struct {
59+
FeatureFlags []string `json:"featureFlags,omitempty"`
60+
OKPChunkFilterQuery string `json:"okpChunkFilterQuery,omitempty"`
61+
OKPRagOnly bool `json:"okpRagOnly,omitempty"`
62+
}
63+
64+
// OKPSpec defines configuration for the Offline Knowledge Portal (OKP).
65+
type OKPSpec struct {
66+
// +kubebuilder:validation:Optional
67+
// +kubebuilder:default=true
68+
// Offline controls how source URLs are resolved.
69+
// When true, uses parent_id (offline/Mimir-style).
70+
// When false, uses reference_url (online).
71+
Offline *bool `json:"offline,omitempty"`
72+
73+
// +kubebuilder:validation:Optional
74+
// AccessKey is the name of the Secret containing the access key for the OKP server.
75+
// The secret must contain a key named "access_key".
76+
// An access key can be obtained from https://access.redhat.com/offline/access
77+
AccessKey string `json:"accessKey,omitempty"`
78+
}
79+
5280
// DatabaseSpec defines configuration for persistent PostgreSQL storage.
5381
type DatabaseSpec struct {
5482
// +kubebuilder:validation:Optional
@@ -84,6 +112,16 @@ type OpenStackLightspeedSpec struct {
84112
// When omitted, an emptyDir volume is used (data is lost on pod reschedule).
85113
// When set, a PersistentVolumeClaim is created and mounted.
86114
Database *DatabaseSpec `json:"database,omitempty"`
115+
116+
// +kubebuilder:validation:Optional
117+
// OKP configures the Offline Knowledge Portal (OKP) RAG source.
118+
OKP *OKPSpec `json:"okp,omitempty"`
119+
120+
// +kubebuilder:validation:Optional
121+
// +kubebuilder:pruning:PreserveUnknownFields
122+
// Dev contains developer/experimental configuration.
123+
// This section is not part of the stable API and may change at any time without backward compatibility.
124+
Dev runtime.RawExtension `json:"dev,omitempty"`
87125
}
88126

89127
// LoggingConfig defines logging configuration for OpenStackLightspeed components
@@ -242,6 +280,7 @@ type OpenStackLightspeedDefaults struct {
242280
PostgresImageURL string
243281
ConsoleImageURL string
244282
ConsoleImagePF5URL string
283+
OKPImageURL string
245284
MaxTokensForResponse int
246285
}
247286

@@ -263,6 +302,8 @@ func SetupDefaults() {
263302
"RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT", ConsoleContainerImage),
264303
ConsoleImagePF5URL: util.GetEnvVar(
265304
"RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT", ConsoleContainerImagePF5),
305+
OKPImageURL: util.GetEnvVar(
306+
"RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT", OKPContainerImage),
266307
MaxTokensForResponse: MaxTokensForResponseDefault,
267308
}
268309

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 47 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/manifests/lightspeed.openstack.org_openstacklightspeeds.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ spec:
6969
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
7070
x-kubernetes-int-or-string: true
7171
type: object
72+
dev:
73+
description: |-
74+
Dev contains developer/experimental configuration.
75+
This section is not part of the stable API and may change at any time without backward compatibility.
76+
type: object
77+
x-kubernetes-preserve-unknown-fields: true
7278
enableOCPRAG:
7379
default: false
7480
description: Enables automatic OCP documentation based on cluster
@@ -155,6 +161,24 @@ spec:
155161
Allows forcing a specific OCP version instead of auto-detection.
156162
Format should be like "4.15", "4.16", etc.
157163
type: string
164+
okp:
165+
description: OKP configures the Offline Knowledge Portal (OKP) RAG
166+
source.
167+
properties:
168+
accessKey:
169+
description: |-
170+
AccessKey is the name of the Secret containing the access key for the OKP server.
171+
The secret must contain a key named "access_key".
172+
An access key can be obtained from https://access.redhat.com/offline/access
173+
type: string
174+
offline:
175+
default: true
176+
description: |-
177+
Offline controls how source URLs are resolved.
178+
When true, uses parent_id (offline/Mimir-style).
179+
When false, uses reference_url (online).
180+
type: boolean
181+
type: object
158182
ragImage:
159183
description: ContainerImage for the OpenStack Lightspeed RAG container
160184
(will be set to environmental default if empty)

bundle/manifests/openstack-lightspeed-operator.clusterserviceversion.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ metadata:
2525
]
2626
capabilities: Basic Install
2727
categories: AI/Machine Learning
28-
createdAt: "2026-05-28T16:28:23Z"
28+
createdAt: "2026-06-11T09:06:59Z"
2929
description: AI-powered virtual assistant for Red Hat OpenStack Services on OpenShift
3030
features.operators.openshift.io/cnf: "false"
3131
features.operators.openshift.io/cni: "false"
@@ -299,6 +299,8 @@ spec:
299299
value: quay.io/lightspeed-core/lightspeed-to-dataverse-exporter:latest
300300
- name: RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT
301301
value: registry.redhat.io/rhel9/postgresql-16:latest
302+
- name: RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT
303+
value: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
302304
image: quay.io/openstack-lightspeed/operator:latest
303305
livenessProbe:
304306
httpGet:
@@ -366,6 +368,7 @@ spec:
366368
- ""
367369
resources:
368370
- configmaps
371+
- services
369372
verbs:
370373
- create
371374
- delete
@@ -378,7 +381,6 @@ spec:
378381
- ""
379382
resources:
380383
- persistentvolumeclaims
381-
- services
382384
verbs:
383385
- create
384386
- get
@@ -415,6 +417,7 @@ spec:
415417
- deployments
416418
verbs:
417419
- create
420+
- delete
418421
- get
419422
- list
420423
- patch
@@ -479,4 +482,6 @@ spec:
479482
name: exporter-image-url-default
480483
- image: registry.redhat.io/rhel9/postgresql-16:latest
481484
name: postgres-image-url-default
485+
- image: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
486+
name: okp-image-url-default
482487
version: 0.0.1

config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ spec:
6969
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
7070
x-kubernetes-int-or-string: true
7171
type: object
72+
dev:
73+
description: |-
74+
Dev contains developer/experimental configuration.
75+
This section is not part of the stable API and may change at any time without backward compatibility.
76+
type: object
77+
x-kubernetes-preserve-unknown-fields: true
7278
enableOCPRAG:
7379
default: false
7480
description: Enables automatic OCP documentation based on cluster
@@ -155,6 +161,24 @@ spec:
155161
Allows forcing a specific OCP version instead of auto-detection.
156162
Format should be like "4.15", "4.16", etc.
157163
type: string
164+
okp:
165+
description: OKP configures the Offline Knowledge Portal (OKP) RAG
166+
source.
167+
properties:
168+
accessKey:
169+
description: |-
170+
AccessKey is the name of the Secret containing the access key for the OKP server.
171+
The secret must contain a key named "access_key".
172+
An access key can be obtained from https://access.redhat.com/offline/access
173+
type: string
174+
offline:
175+
default: true
176+
description: |-
177+
Offline controls how source URLs are resolved.
178+
When true, uses parent_id (offline/Mimir-style).
179+
When false, uses reference_url (online).
180+
type: boolean
181+
type: object
158182
ragImage:
159183
description: ContainerImage for the OpenStack Lightspeed RAG container
160184
(will be set to environmental default if empty)

config/manager/manager.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ spec:
8181
value: quay.io/lightspeed-core/lightspeed-to-dataverse-exporter:latest
8282
- name: RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT
8383
value: registry.redhat.io/rhel9/postgresql-16:latest
84+
- name: RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT
85+
value: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
8486
securityContext:
8587
allowPrivilegeEscalation: false
8688
capabilities:

config/rbac/role.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ rules:
100100
- ""
101101
resources:
102102
- configmaps
103+
- services
103104
verbs:
104105
- create
105106
- delete
@@ -112,7 +113,6 @@ rules:
112113
- ""
113114
resources:
114115
- persistentvolumeclaims
115-
- services
116116
verbs:
117117
- create
118118
- get
@@ -149,6 +149,7 @@ rules:
149149
- deployments
150150
verbs:
151151
- create
152+
- delete
152153
- get
153154
- list
154155
- patch

config/samples/api_v1beta1_openstacklightspeed.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ spec:
1515
# database:
1616
# size: "5Gi"
1717
# class: "my-storage-class"
18+
# Uncomment to enable OKP (Offline Knowledge Portal) as an Inline RAG source:
19+
# okp:
20+
# accessKey: okp-access-key-secret
21+
# dev:
22+
# featureFlags:
23+
# - okp
24+
# okpChunkFilterQuery: "product:(*openstack* OR *openshift*)"
25+
# okpRagOnly: true

hack/env.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT="registry.redhat.io/rhel9/postgr
66
# the automated pipeline for building OGX-compatible vector database images
77
# is ready.
88
export RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT="quay.io/openstack-lightspeed/rag-content:alpha-ogx-os-docs-2025.2"
9+
export RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT="registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest"
910
export WATCH_NAMESPACE="openstack-lightspeed"

internal/controller/assets/vector_database_build.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"""
6161

6262
import argparse
63+
import functools
6364
from pathlib import Path
6465
from typing import Any, Iterable, Optional, Callable
6566
import logging
@@ -218,7 +219,9 @@ def ogx_process(ogx_config_source_path: Path, ogx_config_target: dict[str, Any])
218219

219220
# -- Lightspeed Stack functions ----------------------------------------------
220221
def lstack_process(
221-
ogx_config_source_path: Path, lstack_config_target: dict[str, Any]
222+
ogx_config_source_path: Path,
223+
lstack_config_target: dict[str, Any],
224+
okp_rag_only: bool = False,
222225
) -> dict[str, Any]:
223226
"""Update Lightspeed stack config with RAG entries from OGX config source."""
224227
ogx_config_source = load_yaml_file(ogx_config_source_path)
@@ -243,7 +246,8 @@ def lstack_process(
243246
},
244247
)
245248

246-
add_unique(lstack_config_target["rag"]["inline"], vector_store_id)
249+
if not okp_rag_only:
250+
add_unique(lstack_config_target["rag"]["inline"], vector_store_id)
247251
return lstack_config_target
248252

249253

@@ -276,6 +280,12 @@ def parse_arguments() -> argparse.Namespace:
276280
required=True,
277281
help="Path (as pathlib.Path) to the base Lightspeed Stack configuration file",
278282
)
283+
parser.add_argument(
284+
"--okp-rag-only",
285+
action="store_true",
286+
default=False,
287+
help="When set, skip adding vector store IDs to rag.inline (OKP is the only RAG source)",
288+
)
279289

280290
return parser.parse_args()
281291

@@ -284,7 +294,8 @@ def main() -> None:
284294
"""main"""
285295
args = parse_arguments()
286296
config_build(args.vector_db_path, args.ogx_config_path, ogx_process)
287-
config_build(args.vector_db_path, args.lightspeed_stack_path, lstack_process)
297+
lstack_fn = functools.partial(lstack_process, okp_rag_only=args.okp_rag_only)
298+
config_build(args.vector_db_path, args.lightspeed_stack_path, lstack_fn)
288299

289300

290301
if __name__ == "__main__":

0 commit comments

Comments
 (0)