From 83ca6efb2f81a1afaa89c310e20a15155c0d1b8c Mon Sep 17 00:00:00 2001 From: Lucas Alvares Gomes Date: Thu, 9 Jul 2026 11:18:50 +0100 Subject: [PATCH] Remove EnableOCPRAG and OCPRAGVersionOverride With the introduction of OKP the EnableOCPRAG and OCPRAGVersionOverride configuration options are no longer needed. This change remove all code related to EnableOCPRAG and OCPRAGVersionOverride, including the associated conditions, status field, shell script arguments, etc... The generic OCP version helper methods such as DetectOCPVersion and ParseMajorMinorVersion are retained as they are still used by the OKP chunk filter query and console image selection. Signed-off-by: Lucas Alvares Gomes --- api/v1beta1/conditions.go | 18 - api/v1beta1/openstacklightspeed_types.go | 15 - ...ed.openstack.org_openstacklightspeeds.yaml | 15 - ...tspeed-operator.clusterserviceversion.yaml | 2 +- ...ed.openstack.org_openstacklightspeeds.yaml | 15 - .../assets/vector_database_build.py | 3 - .../assets/vector_database_collect.sh | 80 +---- internal/controller/lcore_deployment.go | 34 +- internal/controller/ocp_version.go | 183 ---------- internal/controller/ocp_version_test.go | 329 ------------------ .../openstacklightspeed_controller.go | 20 -- .../assert-openstack-lightspeed-instance.yaml | 4 - .../create-openstack-lightspeed-instance.yaml | 1 - ...-create-openstack-lightspeed-instance.yaml | 1 - ...-assert-openstack-lightspeed-instance.yaml | 4 - ...-update-openstack-lightspeed-instance.yaml | 5 - .../08-assert-openstacklightspeed-update.yaml | 5 - 17 files changed, 13 insertions(+), 721 deletions(-) diff --git a/api/v1beta1/conditions.go b/api/v1beta1/conditions.go index 3c99041..7de488a 100644 --- a/api/v1beta1/conditions.go +++ b/api/v1beta1/conditions.go @@ -27,9 +27,6 @@ const ( // OpenShift Lightspeed Operator Status=True condition which indicates if OpenShift Lightspeed is installed and // operational and it can be used by OpenStack Lightspeed operator. OpenShiftLightspeedOperatorReadyCondition condition.Type = "OpenShiftLightspeedOperatorReady" - - // OCPRAGCondition Status=True condition which indicates the OCP RAG version resolution status - OCPRAGCondition condition.Type = "OCPRAGReady" ) // Common Messages used by API objects. @@ -49,21 +46,6 @@ const ( // OpenShiftLightspeedOperatorReady OpenShiftLightspeedOperatorReady = "OpenShift Lightspeed operator is ready." - // OCPRAGDisabledMessage - OCPRAGDisabledMessage = "OCP RAG is disabled" - - // OCPRAGVersionResolvedMessage - OCPRAGVersionResolvedMessage = "OCP RAG version resolved: %s" - - // OCPRAGVersionFallbackMessage - OCPRAGVersionFallbackMessage = "Cluster version %s is not explicitly supported. Using 'latest' OCP documentation. Supported versions: %v" - - // OCPRAGDetectionFailedMessage - OCPRAGDetectionFailedMessage = "Failed to detect OCP cluster version" - - // OCPRAGOverrideInvalidMessage - OCPRAGOverrideInvalidMessage = "Invalid OCP RAG version override" - // DeploymentCheckFailedMessage DeploymentCheckFailedMessage = "Failed to check deployment status: %s" diff --git a/api/v1beta1/openstacklightspeed_types.go b/api/v1beta1/openstacklightspeed_types.go index 60edb29..65546e9 100644 --- a/api/v1beta1/openstacklightspeed_types.go +++ b/api/v1beta1/openstacklightspeed_types.go @@ -95,16 +95,6 @@ type DatabaseSpec struct { type OpenStackLightspeedSpec struct { OpenStackLightspeedCore `json:",inline"` - // +kubebuilder:validation:Optional - // +kubebuilder:default=false - // Enables automatic OCP documentation based on cluster version - EnableOCPRAG bool `json:"enableOCPRAG,omitempty"` - - // +kubebuilder:validation:Optional - // Allows forcing a specific OCP version instead of auto-detection. - // Format should be like "4.15", "4.16", etc. - OCPRAGVersionOverride string `json:"ocpVersionOverride,omitempty"` - // +kubebuilder:validation:Optional // Database configures persistent storage for PostgreSQL data. // When omitted, an emptyDir volume is used (data is lost on pod reschedule). @@ -211,11 +201,6 @@ type OpenStackLightspeedStatus struct { // ObservedGeneration - the most recent generation observed for this object. ObservedGeneration int64 `json:"observedGeneration,omitempty"` - - // +optional - // ActiveOCPRAGVersion contains the OCP version being used for RAG configuration - // Will be one of: "4.16", "4.18", "latest", or empty if OCP RAG is disabled - ActiveOCPRAGVersion string `json:"activeOCPRAGVersion,omitempty"` } // +kubebuilder:object:root=true diff --git a/bundle/manifests/lightspeed.openstack.org_openstacklightspeeds.yaml b/bundle/manifests/lightspeed.openstack.org_openstacklightspeeds.yaml index 038034d..9582ee5 100644 --- a/bundle/manifests/lightspeed.openstack.org_openstacklightspeeds.yaml +++ b/bundle/manifests/lightspeed.openstack.org_openstacklightspeeds.yaml @@ -75,11 +75,6 @@ spec: This section is not part of the stable API and may change at any time without backward compatibility. type: object x-kubernetes-preserve-unknown-fields: true - enableOCPRAG: - default: false - description: Enables automatic OCP documentation based on cluster - version - type: boolean feedbackDisabled: description: Disable feedback collection type: boolean @@ -155,11 +150,6 @@ spec: description: Name of the model to use at the API endpoint provided in LLMEndpoint type: string - ocpVersionOverride: - description: |- - 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. @@ -193,11 +183,6 @@ spec: status: description: OpenStackLightspeedStatus defines the observed state of OpenStackLightspeed properties: - activeOCPRAGVersion: - description: |- - ActiveOCPRAGVersion contains the OCP version being used for RAG configuration - Will be one of: "4.16", "4.18", "latest", or empty if OCP RAG is disabled - type: string conditions: description: Conditions items: diff --git a/bundle/manifests/openstack-lightspeed-operator.clusterserviceversion.yaml b/bundle/manifests/openstack-lightspeed-operator.clusterserviceversion.yaml index 54e5d3c..25e2af9 100644 --- a/bundle/manifests/openstack-lightspeed-operator.clusterserviceversion.yaml +++ b/bundle/manifests/openstack-lightspeed-operator.clusterserviceversion.yaml @@ -25,7 +25,7 @@ metadata: ] capabilities: Basic Install categories: AI/Machine Learning - createdAt: "2026-07-03T16:05:52Z" + createdAt: "2026-07-09T10:17:14Z" description: AI-powered virtual assistant for Red Hat OpenStack Services on OpenShift features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" diff --git a/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml b/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml index 88f534e..f321107 100644 --- a/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml +++ b/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml @@ -75,11 +75,6 @@ spec: This section is not part of the stable API and may change at any time without backward compatibility. type: object x-kubernetes-preserve-unknown-fields: true - enableOCPRAG: - default: false - description: Enables automatic OCP documentation based on cluster - version - type: boolean feedbackDisabled: description: Disable feedback collection type: boolean @@ -155,11 +150,6 @@ spec: description: Name of the model to use at the API endpoint provided in LLMEndpoint type: string - ocpVersionOverride: - description: |- - 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. @@ -193,11 +183,6 @@ spec: status: description: OpenStackLightspeedStatus defines the observed state of OpenStackLightspeed properties: - activeOCPRAGVersion: - description: |- - ActiveOCPRAGVersion contains the OCP version being used for RAG configuration - Will be one of: "4.16", "4.18", "latest", or empty if OCP RAG is disabled - type: string conditions: description: Conditions items: diff --git a/internal/controller/assets/vector_database_build.py b/internal/controller/assets/vector_database_build.py index 7d64fc1..d319a8c 100644 --- a/internal/controller/assets/vector_database_build.py +++ b/internal/controller/assets/vector_database_build.py @@ -29,9 +29,6 @@ │ ├── / │ │ ├── llama-stack.yaml │ │ └── faiss_store.db - │ └── ocp_X.YZ/ (optional, when OCP RAG is enabled) - │ ├── llama-stack.yaml - │ └── faiss_store.db └── embeddings_model/ Output (written to --vector-db-path, same basenames as the base configs): diff --git a/internal/controller/assets/vector_database_collect.sh b/internal/controller/assets/vector_database_collect.sh index 8f2b86c..dae1ff5 100644 --- a/internal/controller/assets/vector_database_collect.sh +++ b/internal/controller/assets/vector_database_collect.sh @@ -31,13 +31,6 @@ # │ └── vector-db-data-N/ # │ ├── faiss_store.db # │ └── llama-stack.yaml -# ├── ocp_vector_db/ -# │ ├── ocp_X.YZ/ -# │ │ ├── faiss_store.db -# │ │ └── llama-stack.yaml -# │ └── ocp_latest/ -# │ ├── faiss_store.db -# │ └── llama-stack.yaml # ├── embeddings_model/ # │ └── # └── okp_embeddings_model/ @@ -48,8 +41,7 @@ # ├── / # │ ├── vector_db/ # │ │ ├── vector-db-data-1/ -# │ │ ├── vector-db-data-N/ -# │ │ └── ocp_X.YZ/ (if --enable-ocp-rag true and --ocp-version X.YZ) +# │ │ └── vector-db-data-N/ # │ └── embeddings_model/ # │ └── # └── okp_embeddings_model/ (if --enable-okp true) @@ -57,8 +49,6 @@ # # Arguments: # --vector-db-path PATH Target directory for collected data (required) -# --enable-ocp-rag BOOL Enable OCP vector DB collection: true/false (required) -# --ocp-version VERSION OCP version to collect, e.g., "X.YZ" (required) # --enable-okp Enable OKP embedding model collection (flag, default: disabled) set -eu @@ -69,17 +59,6 @@ set -eu # image is mounted. Populated via parse_arguments_and_init. VECTOR_DB_VOLUME_MOUNT_PATH="" -# ENABLE_OCP_RAG specifies whether this script should collect vector database -# content related to OCP (expected to be found under OCP_VECTOR_DB_DIR). -# Must be set to "true" for the collection to be enabled. Populated via -# parse_arguments_and_init. -ENABLE_OCP_RAG="" - -# OCP_VERSION specifies what version of OCP content should be collected from -# the vector database image -> ${OCP_VECTOR_DB_DIR}/ocp_${OCP_VERSION}. Populated -# via parse_arguments_and_init. -OCP_VERSION="" - # ENABLE_OKP specifies whether this script should collect the OKP embedding # model (expected to be found under OKP_EMBEDDING_MODEL_SRC). Defaults to # "false"; set to "true" via --enable-okp to enable collection. @@ -102,16 +81,6 @@ VECTOR_DB_DATA_COLLECT_DIR="" # embeddings model should be stored. Populated via parse_arguments_and_init. EMBEDDINGS_MODEL_DATA_COLLECT_DIR="" -# OCP_VECTOR_DB_DIR specifies the directory within the vector DB container image -# where OCP-specific vector DB data must reside. This script expects to find the -# OCP data exclusively at this location. -OCP_VECTOR_DB_DIR="/rag/ocp_vector_db" - -# OCP_VECTOR_DB_DIR_FALLBACK specifies the directory within the vector DB container -# image that contains the default OCP vector DB data. This path is used when no data -# matching the version specified via --ocp-version is found. -OCP_VECTOR_DB_DIR_FALLBACK="/rag/ocp_vector_db/ocp_latest" - # VECTOR_DB_DIR specifies the directory within the vector DB container image # where general vector DB data must reside. VECTOR_DB_DIR="/rag/vector_db" @@ -140,25 +109,15 @@ parse_arguments_and_init() { VECTOR_DB_VOLUME_MOUNT_PATH="$2" shift 2 ;; - --enable-ocp-rag) - ENABLE_OCP_RAG="$2" - shift 2 - ;; - --ocp-version) - OCP_VERSION="$2" - shift 2 - ;; --enable-okp) ENABLE_OKP="true" shift 1 ;; -h|--help) - echo "Usage: $0 --vector-db-path PATH --enable-ocp-rag BOOL --ocp-version VERSION [--enable-okp]" + echo "Usage: $0 --vector-db-path PATH [--enable-okp]" echo "" echo "Arguments:" echo " --vector-db-path Target path for vector DB data collection" - echo " --enable-ocp-rag Enable OCP RAG collection (true/false)" - echo " --ocp-version OCP version to collect (e.g., 4.16)" echo " --enable-okp Enable OKP embedding model collection (default: disabled)" echo " -h, --help Show this help message" exit 0 @@ -176,16 +135,6 @@ parse_arguments_and_init() { exit 1 fi - if [ -z "${ENABLE_OCP_RAG:-}" ]; then - echo "ERROR: --enable-ocp-rag is required" - exit 1 - fi - - if [ -z "${OCP_VERSION:-}" ]; then - echo "ERROR: --ocp-version is required" - exit 1 - fi - COLLECT_DIR=$(mktemp -d "${VECTOR_DB_VOLUME_MOUNT_PATH}/XXXXXXXXXX") VECTOR_DB_DATA_COLLECT_DIR="${COLLECT_DIR}/vector_db/" EMBEDDINGS_MODEL_DATA_COLLECT_DIR="${COLLECT_DIR}/embeddings_model" @@ -210,26 +159,6 @@ validate_vector_db_dir() { fi } -collect_ocp_vector_db_data() { - if [ "${ENABLE_OCP_RAG}" != "true" ]; then - echo "Collecting of OCP vector db data is DISABLED => Skipping" - return - fi - - echo "Collecting OCP vector DB data ..." - mkdir -p "${VECTOR_DB_DATA_COLLECT_DIR}" - - ocp_dir="${OCP_VECTOR_DB_DIR}/ocp_${OCP_VERSION}" - if [ ! -d "${ocp_dir}" ]; then - echo "Data for OCP version ${OCP_VERSION} not found. Using: ${OCP_VECTOR_DB_DIR_FALLBACK}" - ocp_dir=${OCP_VECTOR_DB_DIR_FALLBACK} - fi - - validate_vector_db_dir "${ocp_dir}" - cp -rL "${ocp_dir}" "${VECTOR_DB_DATA_COLLECT_DIR}" - echo "Discovered and collected OCP vector DB data from ${ocp_dir}" -} - collect_vector_db_data() { echo "Collecting vector DB data ..." mkdir -p "${VECTOR_DB_DATA_COLLECT_DIR}" @@ -243,8 +172,8 @@ collect_vector_db_data() { echo "Discovered and collected vector DB data from ${dir}" done - if [ "${ENABLE_OCP_RAG}" != "true" ] && [ ${vector_db_data_collected} != "true" ]; then - echo "ERROR: ENABLE_OCP_RAG='${ENABLE_OCP_RAG}' and no generic vector db data found." + if [ ${vector_db_data_collected} != "true" ]; then + echo "ERROR: no generic vector db data found." exit 1 fi } @@ -288,7 +217,6 @@ main() { # variables are initialized before proceeding. parse_arguments_and_init "$@" collect_vector_db_data - collect_ocp_vector_db_data collect_embeddings_model collect_okp_embeddings_model } diff --git a/internal/controller/lcore_deployment.go b/internal/controller/lcore_deployment.go index 26cd48c..070aee3 100644 --- a/internal/controller/lcore_deployment.go +++ b/internal/controller/lcore_deployment.go @@ -21,7 +21,6 @@ import ( "fmt" "path" "slices" - "strconv" "strings" common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper" @@ -212,10 +211,7 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins return corev1.PodTemplateSpec{}, err } - initContainers, err := buildInitContainers(ctx, h, instance) - if err != nil { - return corev1.PodTemplateSpec{}, err - } + initContainers := buildInitContainers(instance) return corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -237,16 +233,7 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins // and Lightspeed Stack configuration files, incorporating information from // the provided vector database images. For details on their logic, see: // (1) assets/vector_database_collect.sh and (2) assets/vector_database_build.py. -func buildInitContainers( - ctx context.Context, - helper *common_helper.Helper, - instance *apiv1beta1.OpenStackLightspeed, -) ([]corev1.Container, error) { - ocp_version, err := DetectOCPVersion(ctx, helper) - if err != nil { - return []corev1.Container{}, err - } - +func buildInitContainers(instance *apiv1beta1.OpenStackLightspeed) []corev1.Container { securityContext := &corev1.SecurityContext{ RunAsNonRoot: &[]bool{true}[0], AllowPrivilegeEscalation: &[]bool{false}[0], @@ -270,16 +257,11 @@ func buildInitContainers( containers = append(containers, corev1.Container{ Name: "vector-database-collect", Image: apiv1beta1.OpenStackLightspeedDefaultValues.RAGImageURL, - Command: func() []string { - cmd := []string{ - "sh", VectorDBScriptsMountPath + "/" + VectorDBCollectScriptKey, - "--vector-db-path", VectorDBVolumeMountPath, - "--enable-ocp-rag", strconv.FormatBool(instance.Spec.EnableOCPRAG), - "--ocp-version", ocp_version, - } - cmd = append(cmd, "--enable-okp") - return cmd - }(), + Command: []string{ + "sh", VectorDBScriptsMountPath + "/" + VectorDBCollectScriptKey, + "--vector-db-path", VectorDBVolumeMountPath, + "--enable-okp", + }, SecurityContext: securityContext, Resources: resourceRequirements, VolumeMounts: []corev1.VolumeMount{ @@ -335,7 +317,7 @@ func buildInitContainers( }, }) - return containers, nil + return containers } // buildLightspeedStackConfigVolume returns the volume for the lightspeed-stack config. diff --git a/internal/controller/ocp_version.go b/internal/controller/ocp_version.go index c731940..8ae7677 100644 --- a/internal/controller/ocp_version.go +++ b/internal/controller/ocp_version.go @@ -20,121 +20,13 @@ import ( "context" "fmt" "regexp" - "slices" - "strings" - "github.com/openstack-k8s-operators/lib-common/modules/common/condition" common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper" - apiv1beta1 "github.com/openstack-k8s-operators/lightspeed-operator/api/v1beta1" uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" ) -const ( - // OpenStackLightspeedOCPVectorDBPath - base path for OCP vector databases - OpenStackLightspeedOCPVectorDBPath = "/rag/ocp_vector_db/ocp" - - // OpenStackLightspeedOCPIndexPrefix - prefix for OCP index names - OpenStackLightspeedOCPIndexPrefix = "ocp-product-docs" - - // Supported OCP versions in the RAG database - OCPVersion416 = "4.16" - OCPVersion418 = "4.18" - OCPVersionLatest = "latest" -) - -// SupportedOCPVersions lists the OCP versions available in the RAG database -var SupportedOCPVersions = []string{OCPVersion416, OCPVersion418, OCPVersionLatest} - -// resolveOCPVersion detects and resolves the OCP version to use for RAG configuration. -// Returns the active OCP version to use (or empty string if OCP RAG is disabled). -func (r *OpenStackLightspeedReconciler) resolveOCPVersion( - ctx context.Context, - helper *common_helper.Helper, - instance *apiv1beta1.OpenStackLightspeed, -) string { - Log := helper.GetLogger() - - // If OCP RAG is disabled, mark condition as True with "disabled" message - if !instance.Spec.EnableOCPRAG { - instance.Status.Conditions.MarkTrue( - apiv1beta1.OCPRAGCondition, - apiv1beta1.OCPRAGDisabledMessage, - ) - instance.Status.ActiveOCPRAGVersion = "" - return "" - } - - // Step 1: Detect cluster version - detectedVersion, err := DetectOCPVersion(ctx, helper) - - if err != nil { - Log.Info("Failed to detect OCP version, disabling OCP RAG", "error", err) - cond := condition.FalseCondition( - apiv1beta1.OCPRAGCondition, - condition.ErrorReason, - condition.SeverityError, - apiv1beta1.OCPRAGDetectionFailedMessage, - ) - cond.Message = fmt.Sprintf("%s: %s", apiv1beta1.OCPRAGDetectionFailedMessage, err.Error()) - instance.Status.Conditions.Set(cond) - instance.Status.ActiveOCPRAGVersion = "" - return "" - } - - Log.Info("Detected OCP cluster version", "version", detectedVersion) - - // Step 2: Resolve which version to use (with override and fallback) - activeVersion, isFallback, err := ResolveOCPVersion( - detectedVersion, - instance.Spec.OCPRAGVersionOverride, - instance.Spec.EnableOCPRAG, - ) - - if err != nil { - // Invalid override - Log.Error(err, "Invalid OCP version configuration") - cond := condition.FalseCondition( - apiv1beta1.OCPRAGCondition, - condition.ErrorReason, - condition.SeverityError, - apiv1beta1.OCPRAGOverrideInvalidMessage, - ) - cond.Message = fmt.Sprintf("%s: %s", apiv1beta1.OCPRAGOverrideInvalidMessage, err.Error()) - instance.Status.Conditions.Set(cond) - instance.Status.ActiveOCPRAGVersion = "" - return "" - } - - // Step 3: Update status and conditions based on resolution - instance.Status.ActiveOCPRAGVersion = activeVersion - - if isFallback { - Log.Info("Using 'latest' OCP documentation as fallback", - "detectedVersion", detectedVersion, - "supportedVersions", SupportedOCPVersions) - - cond := condition.TrueCondition( - apiv1beta1.OCPRAGCondition, - "Fallback", - ) - cond.Message = fmt.Sprintf(apiv1beta1.OCPRAGVersionFallbackMessage, - detectedVersion, SupportedOCPVersions) - instance.Status.Conditions.Set(cond) - } else { - Log.Info("Using OCP RAG documentation", "version", activeVersion) - cond := condition.TrueCondition( - apiv1beta1.OCPRAGCondition, - "Resolved", - ) - cond.Message = fmt.Sprintf(apiv1beta1.OCPRAGVersionResolvedMessage, activeVersion) - instance.Status.Conditions.Set(cond) - } - - return activeVersion -} - // DetectOCPVersion detects the OpenShift cluster version func DetectOCPVersion(ctx context.Context, helper *common_helper.Helper) (string, error) { // Use raw client to access cluster-scoped resources @@ -191,78 +83,3 @@ func ParseMajorMinorVersion(fullVersion string) (string, error) { return matches[1], nil } - -// GetOCPIndexName converts version to index name format -// Example: "4.16" -> "ocp-product-docs-4_16" -// -// "latest" -> "ocp-product-docs-latest" -func GetOCPIndexName(version string) string { - // Replace dots with underscores (no-op for "latest") - versionFormatted := strings.ReplaceAll(version, ".", "_") - return fmt.Sprintf("%s-%s", OpenStackLightspeedOCPIndexPrefix, versionFormatted) -} - -// GetOCPVectorDBPath returns the full path to OCP vector DB for given version -// Example: "4.16" -> "/rag/ocp_vector_db/ocp_4.16" -// -// "latest" -> "/rag/ocp_vector_db/ocp_latest" -func GetOCPVectorDBPath(version string) string { - return fmt.Sprintf("%s_%s", OpenStackLightspeedOCPVectorDBPath, version) -} - -// IsSupportedOCPVersion checks if the version is explicitly supported in RAG DB -func IsSupportedOCPVersion(version string) bool { - return slices.Contains(SupportedOCPVersions, version) -} - -// ResolveOCPVersion determines the OCP version to use for RAG configuration -// Returns (version, isFallback, error) -// - version: The version to use (might be "latest" as fallback) -// - isFallback: true if falling back to "latest" for unsupported version -// - error: any error during version resolution -func ResolveOCPVersion(detectedVersion, overrideVersion string, enableOCPRAG bool) (string, bool, error) { - if !enableOCPRAG { - return "", false, nil - } - - // Use override if provided - if overrideVersion != "" { - return overrideVersion, false, nil - } - - if detectedVersion == "" { - return "", false, fmt.Errorf("no OCP version detected") - } - - // Check if detected version is supported - if IsSupportedOCPVersion(detectedVersion) { - return detectedVersion, false, nil - } - - // Fallback to latest for unsupported versions - return OCPVersionLatest, true, nil -} - -// BuildRAGConfigs builds the RAG configuration array. -// OpenStack RAG is always included first. -// OCP RAG is added if ocpVersion is provided. -func BuildRAGConfigs(instance *apiv1beta1.OpenStackLightspeed, ocpVersion string) []interface{} { - rags := []interface{}{ - // OpenStack RAG - map[string]interface{}{ - "image": apiv1beta1.OpenStackLightspeedDefaultValues.RAGImageURL, - "indexPath": OpenStackLightspeedVectorDBPath, - }, - } - - // Add OCP RAG if enabled - if ocpVersion != "" { - rags = append(rags, map[string]interface{}{ - "image": apiv1beta1.OpenStackLightspeedDefaultValues.RAGImageURL, - "indexPath": GetOCPVectorDBPath(ocpVersion), - "indexID": GetOCPIndexName(ocpVersion), - }) - } - - return rags -} diff --git a/internal/controller/ocp_version_test.go b/internal/controller/ocp_version_test.go index e9c7339..546c5b9 100644 --- a/internal/controller/ocp_version_test.go +++ b/internal/controller/ocp_version_test.go @@ -18,81 +18,8 @@ package controller import ( "testing" - - apiv1beta1 "github.com/openstack-k8s-operators/lightspeed-operator/api/v1beta1" -) - -const ( - // testRAGImage is the test image used in unit tests - testRAGImage = "test-image:latest" ) -func TestGetOCPIndexName(t *testing.T) { - tests := []struct { - name string - version string - expected string - }{ - { - name: "Version 4.16", - version: "4.16", - expected: "ocp-product-docs-4_16", - }, - { - name: "Version 4.18", - version: "4.18", - expected: "ocp-product-docs-4_18", - }, - { - name: "Latest version", - version: "latest", - expected: "ocp-product-docs-latest", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := GetOCPIndexName(tt.version) - if result != tt.expected { - t.Errorf("GetOCPIndexName(%s) = %s, want %s", tt.version, result, tt.expected) - } - }) - } -} - -func TestGetOCPVectorDBPath(t *testing.T) { - tests := []struct { - name string - version string - expected string - }{ - { - name: "Version 4.16", - version: "4.16", - expected: "/rag/ocp_vector_db/ocp_4.16", - }, - { - name: "Version 4.18", - version: "4.18", - expected: "/rag/ocp_vector_db/ocp_4.18", - }, - { - name: "Latest version", - version: "latest", - expected: "/rag/ocp_vector_db/ocp_latest", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := GetOCPVectorDBPath(tt.version) - if result != tt.expected { - t.Errorf("GetOCPVectorDBPath(%s) = %s, want %s", tt.version, result, tt.expected) - } - }) - } -} - func TestParseMajorMinorVersion(t *testing.T) { tests := []struct { name string @@ -144,259 +71,3 @@ func TestParseMajorMinorVersion(t *testing.T) { }) } } - -func TestResolveOCPVersion(t *testing.T) { - tests := []struct { - name string - detected string - override string - enableOCPRAG bool - expectedVer string - expectedFallback bool - shouldError bool - }{ - { - name: "OCP RAG disabled", - detected: "4.16", - override: "", - enableOCPRAG: false, - expectedVer: "", - expectedFallback: false, - shouldError: false, - }, - { - name: "Supported version detected", - detected: "4.16", - override: "", - enableOCPRAG: true, - expectedVer: "4.16", - expectedFallback: false, - shouldError: false, - }, - { - name: "Unsupported version - fallback", - detected: "4.17", - override: "", - enableOCPRAG: true, - expectedVer: "latest", - expectedFallback: true, - shouldError: false, - }, - { - name: "Version override", - detected: "4.18", - override: "4.16", - enableOCPRAG: true, - expectedVer: "4.16", - expectedFallback: false, - shouldError: false, - }, - { - name: "Custom override (any version allowed)", - detected: "4.16", - override: "4.99", - enableOCPRAG: true, - expectedVer: "4.99", - expectedFallback: false, - shouldError: false, - }, - { - name: "No version detected", - detected: "", - override: "", - enableOCPRAG: true, - expectedVer: "", - expectedFallback: false, - shouldError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - version, isFallback, err := ResolveOCPVersion(tt.detected, tt.override, tt.enableOCPRAG) - if tt.shouldError { - if err == nil { - t.Errorf("ResolveOCPVersion expected error, got nil") - } - } else { - if err != nil { - t.Errorf("ResolveOCPVersion unexpected error: %v", err) - } - if version != tt.expectedVer { - t.Errorf("ResolveOCPVersion version = %s, want %s", version, tt.expectedVer) - } - if isFallback != tt.expectedFallback { - t.Errorf("ResolveOCPVersion isFallback = %v, want %v", isFallback, tt.expectedFallback) - } - } - }) - } -} - -func TestBuildRAGConfigs(t *testing.T) { - apiv1beta1.OpenStackLightspeedDefaultValues.RAGImageURL = testRAGImage - - t.Run("OCP RAG disabled (empty version)", func(t *testing.T) { - instance := &apiv1beta1.OpenStackLightspeed{} - - configs := BuildRAGConfigs(instance, "") - - if len(configs) != 1 { - t.Errorf("Expected 1 RAG config, got %d", len(configs)) - } - - // Type assert to map[string]interface{} - firstConfig, ok := configs[0].(map[string]interface{}) - if !ok { - t.Fatalf("Expected config to be map[string]interface{}, got %T", configs[0]) - } - - if firstConfig["image"] != testRAGImage { - t.Errorf("Expected image test-image:latest, got %v", firstConfig["image"]) - } - - if firstConfig["indexPath"] != OpenStackLightspeedVectorDBPath { - t.Errorf("Expected indexPath %s, got %v", OpenStackLightspeedVectorDBPath, firstConfig["indexPath"]) - } - - // Verify priority field is NOT present - if _, hasPriority := firstConfig["priority"]; hasPriority { - t.Errorf("Expected no priority field, but it was present") - } - }) - - t.Run("OCP RAG enabled", func(t *testing.T) { - instance := &apiv1beta1.OpenStackLightspeed{} - - configs := BuildRAGConfigs(instance, "4.16") - - if len(configs) != 2 { - t.Errorf("Expected 2 RAG configs, got %d", len(configs)) - } - - // Check OpenStack RAG (first config) - osConfig, ok := configs[0].(map[string]interface{}) - if !ok { - t.Fatalf("Expected first config to be map[string]interface{}, got %T", configs[0]) - } - - if osConfig["image"] != testRAGImage { - t.Errorf("OpenStack RAG image = %v, want test-image:latest", osConfig["image"]) - } - - if osConfig["indexPath"] != OpenStackLightspeedVectorDBPath { - t.Errorf("OpenStack RAG indexPath = %v, want %s", osConfig["indexPath"], OpenStackLightspeedVectorDBPath) - } - - // Verify priority field is NOT present in OpenStack config - if _, hasPriority := osConfig["priority"]; hasPriority { - t.Errorf("Expected no priority field in OpenStack config, but it was present") - } - - // Check OCP RAG (second config) - ocpConfig, ok := configs[1].(map[string]interface{}) - if !ok { - t.Fatalf("Expected second config to be map[string]interface{}, got %T", configs[1]) - } - - if ocpConfig["image"] != testRAGImage { - t.Errorf("OCP RAG image = %v, want test-image:latest", ocpConfig["image"]) - } - - ocpPath, ok := ocpConfig["indexPath"].(string) - if !ok { - t.Fatalf("Expected indexPath to be string, got %T", ocpConfig["indexPath"]) - } - if ocpPath != "/rag/ocp_vector_db/ocp_4.16" { - t.Errorf("OCP indexPath = %s, want /rag/ocp_vector_db/ocp_4.16", ocpPath) - } - - ocpIndexID, ok := ocpConfig["indexID"].(string) - if !ok { - t.Fatalf("Expected indexID to be string, got %T", ocpConfig["indexID"]) - } - if ocpIndexID != "ocp-product-docs-4_16" { - t.Errorf("OCP indexID = %s, want ocp-product-docs-4_16", ocpIndexID) - } - - // Verify priority field is NOT present in OCP config - if _, hasPriority := ocpConfig["priority"]; hasPriority { - t.Errorf("Expected no priority field in OCP config, but it was present") - } - }) - - t.Run("OCP RAG with latest version", func(t *testing.T) { - instance := &apiv1beta1.OpenStackLightspeed{} - - configs := BuildRAGConfigs(instance, "latest") - - if len(configs) != 2 { - t.Errorf("Expected 2 RAG configs, got %d", len(configs)) - } - - // Check OCP RAG with latest version - ocpConfig, ok := configs[1].(map[string]interface{}) - if !ok { - t.Fatalf("Expected second config to be map[string]interface{}, got %T", configs[1]) - } - - ocpPath, ok := ocpConfig["indexPath"].(string) - if !ok { - t.Fatalf("Expected indexPath to be string, got %T", ocpConfig["indexPath"]) - } - if ocpPath != "/rag/ocp_vector_db/ocp_latest" { - t.Errorf("OCP indexPath = %s, want /rag/ocp_vector_db/ocp_latest", ocpPath) - } - - ocpIndexID, ok := ocpConfig["indexID"].(string) - if !ok { - t.Fatalf("Expected indexID to be string, got %T", ocpConfig["indexID"]) - } - if ocpIndexID != "ocp-product-docs-latest" { - t.Errorf("OCP indexID = %s, want ocp-product-docs-latest", ocpIndexID) - } - }) -} - -func TestIsSupportedOCPVersion(t *testing.T) { - tests := []struct { - name string - version string - expected bool - }{ - { - name: "Supported version 4.16", - version: "4.16", - expected: true, - }, - { - name: "Supported version 4.18", - version: "4.18", - expected: true, - }, - { - name: "Supported version latest", - version: "latest", - expected: true, - }, - { - name: "Unsupported version 4.17", - version: "4.17", - expected: false, - }, - { - name: "Unsupported version 4.19", - version: "4.19", - expected: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := IsSupportedOCPVersion(tt.version) - if result != tt.expected { - t.Errorf("IsSupportedOCPVersion(%s) = %v, want %v", tt.version, result, tt.expected) - } - }) - } -} diff --git a/internal/controller/openstacklightspeed_controller.go b/internal/controller/openstacklightspeed_controller.go index 1610bc8..5556164 100644 --- a/internal/controller/openstacklightspeed_controller.go +++ b/internal/controller/openstacklightspeed_controller.go @@ -29,9 +29,7 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" - uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -144,10 +142,6 @@ func (r *OpenStackLightspeedReconciler) Reconcile(ctx context.Context, req ctrl. instance.Status.Conditions.Init(&cl) instance.Status.ObservedGeneration = instance.Generation - // TODO(lpiwowar): Use the resolve OCP version when we add the RAG deployment - // OCP Version Detection and Resolution - must be done early so status field is always set - _ = r.resolveOCPVersion(ctx, helper, instance) - if !instance.DeletionTimestamp.IsZero() { if err := r.reconcileDelete(ctx, helper, instance); err != nil { return ctrl.Result{}, err @@ -267,15 +261,6 @@ func (r *OpenStackLightspeedReconciler) reconcileStatus( // SetupWithManager sets up the controller with the Manager. func (r *OpenStackLightspeedReconciler) SetupWithManager(mgr ctrl.Manager) error { - // Create an unstructured ClusterVersion for watching - // This triggers reconciliation when OCP is upgraded (e.g., 4.16 -> 4.18) - clusterVersion := &uns.Unstructured{} - clusterVersion.SetGroupVersionKind(schema.GroupVersionKind{ - Group: "config.openshift.io", - Version: "v1", - Kind: "ClusterVersion", - }) - return ctrl.NewControllerManagedBy(mgr). For(&apiv1beta1.OpenStackLightspeed{}). Owns(&operatorsv1alpha1.ClusterServiceVersion{}). @@ -292,11 +277,6 @@ func (r *OpenStackLightspeedReconciler) SetupWithManager(mgr ctrl.Manager) error handler.EnqueueRequestsFromMapFunc(r.NotifyAllOpenStackLightspeeds), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). - Watches( - clusterVersion, - handler.EnqueueRequestsFromMapFunc(r.NotifyAllOpenStackLightspeeds), - builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), - ). Watches( &corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.NotifyOpenStackLightspeedsByCAConfigMap), diff --git a/test/kuttl/common/openstack-lightspeed-instance/assert-openstack-lightspeed-instance.yaml b/test/kuttl/common/openstack-lightspeed-instance/assert-openstack-lightspeed-instance.yaml index 0c52ab8..e064d43 100644 --- a/test/kuttl/common/openstack-lightspeed-instance/assert-openstack-lightspeed-instance.yaml +++ b/test/kuttl/common/openstack-lightspeed-instance/assert-openstack-lightspeed-instance.yaml @@ -434,10 +434,6 @@ status: status: "True" reason: Ready message: Setup complete - - type: OCPRAGReady - status: "True" - reason: Ready - message: OCP RAG is disabled - type: OpenStackLightspeedReady status: "True" reason: Ready diff --git a/test/kuttl/common/openstack-lightspeed-instance/create-openstack-lightspeed-instance.yaml b/test/kuttl/common/openstack-lightspeed-instance/create-openstack-lightspeed-instance.yaml index 6e9c7aa..b7b56f7 100644 --- a/test/kuttl/common/openstack-lightspeed-instance/create-openstack-lightspeed-instance.yaml +++ b/test/kuttl/common/openstack-lightspeed-instance/create-openstack-lightspeed-instance.yaml @@ -13,7 +13,6 @@ spec: llmProjectID: test-project-id llmDeploymentName: test-deployment-name llmAPIVersion: v1 - enableOCPRAG: false logging: ogxLogLevel: DEBUG lightspeedStackLogLevel: WARNING diff --git a/test/kuttl/tests/persistent-database/03-create-openstack-lightspeed-instance.yaml b/test/kuttl/tests/persistent-database/03-create-openstack-lightspeed-instance.yaml index 338f7ef..8803735 100644 --- a/test/kuttl/tests/persistent-database/03-create-openstack-lightspeed-instance.yaml +++ b/test/kuttl/tests/persistent-database/03-create-openstack-lightspeed-instance.yaml @@ -13,6 +13,5 @@ spec: llmProjectID: test-project-id llmDeploymentName: test-deployment-name llmAPIVersion: v1 - enableOCPRAG: false database: size: "2Gi" diff --git a/test/kuttl/tests/persistent-database/04-assert-openstack-lightspeed-instance.yaml b/test/kuttl/tests/persistent-database/04-assert-openstack-lightspeed-instance.yaml index 1873cad..d213ad1 100644 --- a/test/kuttl/tests/persistent-database/04-assert-openstack-lightspeed-instance.yaml +++ b/test/kuttl/tests/persistent-database/04-assert-openstack-lightspeed-instance.yaml @@ -44,10 +44,6 @@ status: status: "True" reason: Ready message: Setup complete - - type: OCPRAGReady - status: "True" - reason: Ready - message: OCP RAG is disabled - type: OpenStackLightspeedReady status: "True" reason: Ready diff --git a/test/kuttl/tests/update-openstacklightspeed/07-update-openstack-lightspeed-instance.yaml b/test/kuttl/tests/update-openstacklightspeed/07-update-openstack-lightspeed-instance.yaml index 40a2600..88e0d59 100644 --- a/test/kuttl/tests/update-openstacklightspeed/07-update-openstack-lightspeed-instance.yaml +++ b/test/kuttl/tests/update-openstacklightspeed/07-update-openstack-lightspeed-instance.yaml @@ -30,11 +30,6 @@ spec: llmAPIVersion: v1.1 feedbackDisabled: true transcriptsDisabled: true - # NOTE(lpiwowar): We have to keep enableOCPRAG: false even after the update - # because the OpenStack Lightspeed vector DB image does not contain OCP content. - # We can set it to `true` once the OCP contant is present in the image. - enableOCPRAG: false - ocpVersionOverride: "4.16" logging: ogxLogLevel: "core=debug,providers=info" lightspeedStackLogLevel: ERROR diff --git a/test/kuttl/tests/update-openstacklightspeed/08-assert-openstacklightspeed-update.yaml b/test/kuttl/tests/update-openstacklightspeed/08-assert-openstacklightspeed-update.yaml index 16fd118..8b32c33 100644 --- a/test/kuttl/tests/update-openstacklightspeed/08-assert-openstacklightspeed-update.yaml +++ b/test/kuttl/tests/update-openstacklightspeed/08-assert-openstacklightspeed-update.yaml @@ -273,8 +273,6 @@ spec: llmAPIVersion: v1.1 feedbackDisabled: true transcriptsDisabled: true - enableOCPRAG: false - ocpVersionOverride: "4.16" logging: ogxLogLevel: "core=debug,providers=info" lightspeedStackLogLevel: ERROR @@ -284,9 +282,6 @@ status: status: "True" reason: Ready message: Setup complete - - type: OCPRAGReady - status: "True" - message: OCP RAG is disabled - type: OpenStackLightspeedReady status: "True" reason: Ready