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