Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions api/v1beta1/openstacklightspeed_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,44 @@ const (
// ConsoleContainerImagePF5 is the fall-back console image for PatternFly 5 (OCP < 4.19)
ConsoleContainerImagePF5 = "registry.redhat.io/openshift-lightspeed/lightspeed-console-plugin-pf5-rhel9:1.0.12"

// OKPContainerImage is the fall-back container image for OKP (Offline Knowledge Portal)
OKPContainerImage = "registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest"

// MaxTokensForResponseDefault is the default maximum number of tokens that should be used for response
MaxTokensForResponseDefault = 2048
)

// DevSpec defines developer/experimental feature configuration.
type DevSpec struct {
// +kubebuilder:validation:Optional
// +kubebuilder:validation:items:Enum=okp
// FeatureFlags is a list of feature flag names to enable experimental features.
// Supported flags: "okp" (Offline Knowledge Portal).
FeatureFlags []string `json:"featureFlags,omitempty"`
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// +kubebuilder:validation:Optional
// OKPChunkFilterQuery is a static Solr filter query appended to OKP searches.
// Combined with the default "is_chunk:true" filter using AND.
// Example: "product:*openstack*"
OKPChunkFilterQuery string `json:"okpChunkFilterQuery,omitempty"`
}

// OKPSpec defines configuration for the Offline Knowledge Portal (OKP).
type OKPSpec struct {
// +kubebuilder:validation:Optional
// +kubebuilder:default=true
// Offline controls how source URLs are resolved.
// When true, uses parent_id (offline/Mimir-style).
// When false, uses reference_url (online).
Offline *bool `json:"offline,omitempty"`

// +kubebuilder:validation:Optional
// AccessKey is the name of the Secret containing the access key for the OKP server.
// The secret must contain a key named "access_key".
// An access key can be obtained from https://access.redhat.com/offline/access
AccessKey string `json:"accessKey,omitempty"`
}

// DatabaseSpec defines configuration for persistent PostgreSQL storage.
type DatabaseSpec struct {
// +kubebuilder:validation:Optional
Expand Down Expand Up @@ -84,6 +118,15 @@ type OpenStackLightspeedSpec struct {
// When omitted, an emptyDir volume is used (data is lost on pod reschedule).
// When set, a PersistentVolumeClaim is created and mounted.
Database *DatabaseSpec `json:"database,omitempty"`

// +kubebuilder:validation:Optional
// Dev contains developer/experimental feature configuration.
Dev *DevSpec `json:"dev,omitempty"`

// +kubebuilder:validation:Optional
// OKP configures the Offline Knowledge Portal (OKP) RAG source.
// Only used when "okp" is present in dev.featureFlags.
OKP *OKPSpec `json:"okp,omitempty"`
}

// LoggingConfig defines logging configuration for OpenStackLightspeed components
Expand Down Expand Up @@ -242,6 +285,7 @@ type OpenStackLightspeedDefaults struct {
PostgresImageURL string
ConsoleImageURL string
ConsoleImagePF5URL string
OKPImageURL string
MaxTokensForResponse int
}

Expand All @@ -263,6 +307,8 @@ func SetupDefaults() {
"RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT", ConsoleContainerImage),
ConsoleImagePF5URL: util.GetEnvVar(
"RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT", ConsoleContainerImagePF5),
OKPImageURL: util.GetEnvVar(
"RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT", OKPContainerImage),
MaxTokensForResponse: MaxTokensForResponseDefault,
}

Expand Down
50 changes: 50 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ spec:
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
dev:
description: Dev contains developer/experimental feature configuration.
properties:
featureFlags:
description: |-
FeatureFlags is a list of feature flag names to enable experimental features.
Supported flags: "okp" (Offline Knowledge Portal).
items:
enum:
- okp
type: string
type: array
okpChunkFilterQuery:
description: |-
OKPChunkFilterQuery is a static Solr filter query appended to OKP searches.
Combined with the default "is_chunk:true" filter using AND.
Example: "product:*openstack*"
type: string
type: object
enableOCPRAG:
default: false
description: Enables automatic OCP documentation based on cluster
Expand Down Expand Up @@ -155,6 +174,25 @@ spec:
Allows forcing a specific OCP version instead of auto-detection.
Format should be like "4.15", "4.16", etc.
type: string
okp:
description: |-
OKP configures the Offline Knowledge Portal (OKP) RAG source.
Only used when "okp" is present in dev.featureFlags.
properties:
accessKey:
description: |-
AccessKey is the name of the Secret containing the access key for the OKP server.
The secret must contain a key named "access_key".
An access key can be obtained from https://access.redhat.com/offline/access
type: string
offline:
default: true
description: |-
Offline controls how source URLs are resolved.
When true, uses parent_id (offline/Mimir-style).
When false, uses reference_url (online).
type: boolean
type: object
ragImage:
description: ContainerImage for the OpenStack Lightspeed RAG container
(will be set to environmental default if empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ metadata:
]
capabilities: Basic Install
categories: AI/Machine Learning
createdAt: "2026-05-28T16:28:23Z"
createdAt: "2026-06-08T12:14:19Z"
description: AI-powered virtual assistant for Red Hat OpenStack Services on OpenShift
features.operators.openshift.io/cnf: "false"
features.operators.openshift.io/cni: "false"
Expand Down Expand Up @@ -299,6 +299,8 @@ spec:
value: quay.io/lightspeed-core/lightspeed-to-dataverse-exporter:latest
- name: RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT
value: registry.redhat.io/rhel9/postgresql-16:latest
- name: RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT
value: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
image: quay.io/openstack-lightspeed/operator:latest
livenessProbe:
httpGet:
Expand Down Expand Up @@ -366,6 +368,7 @@ spec:
- ""
resources:
- configmaps
- services
verbs:
- create
- delete
Expand All @@ -378,7 +381,6 @@ spec:
- ""
resources:
- persistentvolumeclaims
- services
verbs:
- create
- get
Expand Down Expand Up @@ -415,6 +417,7 @@ spec:
- deployments
verbs:
- create
- delete
- get
- list
- patch
Expand Down Expand Up @@ -479,4 +482,6 @@ spec:
name: exporter-image-url-default
- image: registry.redhat.io/rhel9/postgresql-16:latest
name: postgres-image-url-default
- image: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
name: okp-image-url-default
version: 0.0.1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ spec:
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
dev:
description: Dev contains developer/experimental feature configuration.
properties:
featureFlags:
description: |-
FeatureFlags is a list of feature flag names to enable experimental features.
Supported flags: "okp" (Offline Knowledge Portal).
items:
enum:
- okp
type: string
type: array
okpChunkFilterQuery:
description: |-
OKPChunkFilterQuery is a static Solr filter query appended to OKP searches.
Combined with the default "is_chunk:true" filter using AND.
Example: "product:*openstack*"
type: string
type: object
enableOCPRAG:
default: false
description: Enables automatic OCP documentation based on cluster
Expand Down Expand Up @@ -155,6 +174,25 @@ spec:
Allows forcing a specific OCP version instead of auto-detection.
Format should be like "4.15", "4.16", etc.
type: string
okp:
description: |-
OKP configures the Offline Knowledge Portal (OKP) RAG source.
Only used when "okp" is present in dev.featureFlags.
properties:
accessKey:
description: |-
AccessKey is the name of the Secret containing the access key for the OKP server.
The secret must contain a key named "access_key".
An access key can be obtained from https://access.redhat.com/offline/access
type: string
offline:
default: true
description: |-
Offline controls how source URLs are resolved.
When true, uses parent_id (offline/Mimir-style).
When false, uses reference_url (online).
type: boolean
type: object
ragImage:
description: ContainerImage for the OpenStack Lightspeed RAG container
(will be set to environmental default if empty)
Expand Down
2 changes: 2 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ spec:
value: quay.io/lightspeed-core/lightspeed-to-dataverse-exporter:latest
- name: RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT
value: registry.redhat.io/rhel9/postgresql-16:latest
- name: RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT
value: registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
Expand Down
3 changes: 2 additions & 1 deletion config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ rules:
- ""
resources:
- configmaps
- services
verbs:
- create
- delete
Expand All @@ -112,7 +113,6 @@ rules:
- ""
resources:
- persistentvolumeclaims
- services
verbs:
- create
- get
Expand Down Expand Up @@ -149,6 +149,7 @@ rules:
- deployments
verbs:
- create
- delete
- get
- list
- patch
Expand Down
7 changes: 7 additions & 0 deletions config/samples/api_v1beta1_openstacklightspeed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ spec:
# database:
# size: "5Gi"
# class: "my-storage-class"
# Uncomment to enable OKP (Offline Knowledge Portal) as an Inline RAG source:
# dev:
# featureFlags:
# - okp
# okpChunkFilterQuery: "product:*openstack*"
# okp:
# accessKey: okp-access-key-secret
1 change: 1 addition & 0 deletions hack/env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT="registry.redhat.io/rhel9/postgr
# the automated pipeline for building OGX-compatible vector database images
# is ready.
export RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT="quay.io/openstack-lightspeed/rag-content:alpha-ogx-os-docs-2025.2"
export RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT="registry.redhat.io/offline-knowledge-portal/rhokp-rhel9:latest"
export WATCH_NAMESPACE="openstack-lightspeed"
20 changes: 20 additions & 0 deletions internal/controller/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import (
_ "embed"
"errors"
"fmt"
"slices"
"strings"

common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper"
apiv1beta1 "github.com/openstack-lightspeed/operator/api/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -126,6 +128,24 @@ func isDeploymentReady(deploy *appsv1.Deployment) bool {
deploy.Status.Replicas == replicas
}

// generateOKPSelectorLabels returns selector labels for OKP components.
func generateOKPSelectorLabels() map[string]string {
return map[string]string{
"app.kubernetes.io/component": "okp-server",
"app.kubernetes.io/managed-by": "openstack-lightspeed-operator",
"app.kubernetes.io/name": "openstack-lightspeed-okp-server",
"app.kubernetes.io/part-of": "openstack-lightspeed",
}
}

// isOKPEnabled returns true if the "okp" feature flag is present in dev.featureFlags.
func isOKPEnabled(instance *apiv1beta1.OpenStackLightspeed) bool {
if instance.Spec.Dev == nil {
return false
}
return slices.Contains(instance.Spec.Dev.FeatureFlags, "okp")
}

// getDeployment retrieves deployment from the cluster
func getDeployment(ctx context.Context, h *common_helper.Helper, name string, namespace string) (*appsv1.Deployment, error) {
deployment := &appsv1.Deployment{}
Expand Down
Loading
Loading